Provide localized product information and pricing for global markets using the Products V2 API's built-in localization capabilities.
Multi-language support enables you to provide localized product information, pricing, and content for global markets. The Products V2 API provides comprehensive localization features including multi-language product descriptions, localized pricing, and regional customization.
Implement basic localization for product information:
class LocalizationManager {
constructor(apiKey) {
this.apiKey = apiKey;
this.baseUrl = 'https://api.joinsherpa.io/v2/products';
this.supportedLanguages = [
'en-US', 'en-GB', 'fr-FR', 'de-DE', 'es-ES',
'it-IT', 'pt-BR', 'ja-JP', 'ko-KR', 'zh-CN'
];
}
// Get product in specific language
async getProductInLanguage(productId, language, currency = 'USD') {
try {
const response = await fetch(
`${this.baseUrl}/${productId}?language=${language}¤cy=${currency}`,
{
headers: {
'x-api-key': `${this.apiKey}`,
},
}
);
if (!response.ok) {
const errorData = await response.json();
throw new Error(`API Error: ${errorData.message}`);
}
const product = await response.json();
return product;
} catch (error) {
console.error(`Failed to get product ${productId} in ${language}:`, error);
throw error;
}
}
// Get products with localization
async getProductsWithLocalization(filters = {}) {
const params = new URLSearchParams();
// Add language and currency
if (filters.language) params.append('language', filters.language);
if (filters.currency) params.append('currency', filters.currency);
// Add other filters
Object.entries(filters).forEach(([key, value]) => {
if (key !== 'language' && key !== 'currency' && value !== undefined) {
params.append(key, value);
}
});
const response = await fetch(`${this.baseUrl}?${params}`, {
headers: {
'Authorization': `Bearer ${this.apiToken}`,
},
});
if (!response.ok) {
const errorData = await response.json();
throw new Error(`API Error: ${errorData.message}`);
}
return await response.json();
}
// Get localized product name
getLocalizedProductName(product, language) {
// In a real implementation, you might have language-specific names
// For now, we'll use the default name
return product.name || 'Unknown Product';
}
// Get localized product description
getLocalizedProductDescription(product, language) {
// In a real implementation, you might have language-specific descriptions
// For now, we'll use the default description
return product.description || 'No description available';
}
}
// Usage examples
const localizationManager = new LocalizationManager('YOUR_API_KEY');
// Get product in French
localizationManager.getProductInLanguage('turkey-evisa-tourism', 'fr-FR', 'EUR')
.then(product => {
console.log('Product in French:', product.name);
console.log('Price in EUR:', product.pricing.price, product.pricing.currency);
});
// Get products with localization
localizationManager.getProductsWithLocalization({
destination: 'TUR',
language: 'de-DE',
currency: 'EUR'
}).then(products => {
console.log('Products in German:', products);
});Create products with multi-language support:
class MultiLanguageProductManager {
constructor(apiKey) {
this.apiKey = apiKey;
this.baseUrl = 'https://api.joinsherpa.io/v2/products';
}
// Create product with localization enabled
async createLocalizedProduct(productData) {
try {
const response = await fetch(this.baseUrl, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'x-api-key': `${this.apiKey}`,
},
body: JSON.stringify({
...productData,
localizeProduct: true
}),
});
if (!response.ok) {
const errorData = await response.json();
throw new Error(`API Error: ${errorData.message}`);
}
const product = await response.json();
console.log('Localized product created:', product.productId);
return product;
} catch (error) {
console.error('Failed to create localized product:', error);
throw error;
}
}
// Create product with multiple language versions
async createProductWithMultipleLanguages(baseProductData, languageVersions) {
const results = [];
for (const [language, localizedData] of Object.entries(languageVersions)) {
try {
const productData = {
...baseProductData,
...localizedData,
productId: `${baseProductData.productId}-${language}`,
localizeProduct: true
};
const product = await this.createLocalizedProduct(productData);
results.push({ success: true, language, product });
} catch (error) {
results.push({ success: false, language, error: error.message });
}
}
return results;
}
// Update product with localized content
async updateProductWithLocalization(productId, localizedData) {
try {
const response = await fetch(`${this.baseUrl}/${productId}`, {
method: 'PATCH',
headers: {
'Content-Type': 'application/json',
'x-api-key': `${this.apiKey}`,
},
body: JSON.stringify({
...localizedData,
localizeProduct: true
}),
});
if (!response.ok) {
const errorData = await response.json();
throw new Error(`API Error: ${errorData.message}`);
}
const updatedProduct = await response.json();
console.log('Product updated with localization:', updatedProduct.productId);
return updatedProduct;
} catch (error) {
console.error('Failed to update product with localization:', error);
throw error;
}
}
}
// Usage examples
const multiLangManager = new MultiLanguageProductManager('YOUR_API_KEY');
// Create product with localization
const baseProductData = {
name: 'Turkey eVisa',
programId: 'turkey-evisa',
productId: 'turkey-evisa-tourism',
status: 'ACTIVE',
type: 'visa',
subType: 'E_VISA',
numberOfEntries: 'SINGLE',
travelPurposes: ['TOURISM'],
destinations: ['TUR'],
eligibleNationalities: ['USA'],
priceBreakdown: [
{ type: 'GOVERNMENT_FEE', price: 50.00 },
{ type: 'APPLICATION_SERVICE_FEE', price: 25.00 }
]
};
multiLangManager.createLocalizedProduct(baseProductData)
.then(product => {
console.log('Localized product created:', product);
});
// Create product with multiple language versions
const languageVersions = {
'fr-FR': {
name: 'Visa électronique Turquie',
description: 'Visa électronique pour le tourisme en Turquie'
},
'de-DE': {
name: 'Türkei e-Visa',
description: 'Elektronisches Visum für den Tourismus in der Türkei'
},
'es-ES': {
name: 'Visa electrónico TurquÃa',
description: 'Visa electrónico para turismo en TurquÃa'
}
};
multiLangManager.createProductWithMultipleLanguages(baseProductData, languageVersions)
.then(results => {
console.log('Multi-language products created:', results);
});Handle currency localization and conversion:
class CurrencyLocalizationManager {
constructor(apiKey) {
this.apiKey = apiKey;
this.baseUrl = 'https://api.joinsherpa.io/v2/products';
this.currencyMap = {
'en-US': 'USD',
'en-GB': 'GBP',
'fr-FR': 'EUR',
'de-DE': 'EUR',
'es-ES': 'EUR',
'it-IT': 'EUR',
'pt-BR': 'BRL',
'ja-JP': 'JPY',
'ko-KR': 'KRW',
'zh-CN': 'CNY'
};
}
// Get currency for language
getCurrencyForLanguage(language) {
return this.currencyMap[language] || 'USD';
}
// Get product with localized currency
async getProductWithLocalizedCurrency(productId, language) {
const currency = this.getCurrencyForLanguage(language);
try {
const response = await fetch(
`${this.baseUrl}/${productId}?language=${language}¤cy=${currency}`,
{
headers: {
'x-api-key': `${this.apiKey}`,
},
}
);
if (!response.ok) {
const errorData = await response.json();
throw new Error(`API Error: ${errorData.message}`);
}
const product = await response.json();
return product;
} catch (error) {
console.error(`Failed to get product with localized currency:`, error);
throw error;
}
}
// Get products with localized currency
async getProductsWithLocalizedCurrency(filters = {}) {
const language = filters.language || 'en-US';
const currency = this.getCurrencyForLanguage(language);
const params = new URLSearchParams();
params.append('language', language);
params.append('currency', currency);
// Add other filters
Object.entries(filters).forEach(([key, value]) => {
if (key !== 'language' && value !== undefined) {
params.append(key, value);
}
});
const response = await fetch(`${this.baseUrl}?${params}`, {
headers: {
'Authorization': `Bearer ${this.apiToken}`,
},
});
if (!response.ok) {
const errorData = await response.json();
throw new Error(`API Error: ${errorData.message}`);
}
return await response.json();
}
// Format price for display
formatPriceForDisplay(price, currency, language) {
const formatter = new Intl.NumberFormat(language, {
style: 'currency',
currency: currency
});
return formatter.format(price);
}
// Get localized price breakdown
getLocalizedPriceBreakdown(product, language) {
const currency = this.getCurrencyForLanguage(language);
const pricing = product.pricing;
if (!pricing || !pricing.breakdown) {
return [];
}
return pricing.breakdown.map(fee => ({
type: fee.type,
price: fee.price,
currency: currency,
formattedPrice: this.formatPriceForDisplay(fee.price, currency, language),
label: fee.label
}));
}
}
// Usage examples
const currencyManager = new CurrencyLocalizationManager('YOUR_API_KEY');
// Get product with localized currency
currencyManager.getProductWithLocalizedCurrency('turkey-evisa-tourism', 'fr-FR')
.then(product => {
console.log('Product in French with EUR:', product.name);
console.log('Price:', product.pricing.price, product.pricing.currency);
});
// Get products with localized currency
currencyManager.getProductsWithLocalizedCurrency({
destination: 'TUR',
language: 'de-DE'
}).then(products => {
console.log('Products in German with EUR:', products);
});
// Format price for display
const price = 75.00;
const formattedPrice = currencyManager.formatPriceForDisplay(price, 'EUR', 'fr-FR');
console.log('Formatted price:', formattedPrice); // €75,00`} />
### 4. Regional Customization
Implement regional customization for different markets:
```javascript title="Regional Customization"
class RegionalCustomizationManager {
constructor(apiKey) {
this.apiKey = apiKey;
this.baseUrl = 'https://api.joinsherpa.io/v2/products';
this.regionalSettings = {
'US': { language: 'en-US', currency: 'USD', timezone: 'America/New_York' },
'GB': { language: 'en-GB', currency: 'GBP', timezone: 'Europe/London' },
'FR': { language: 'fr-FR', currency: 'EUR', timezone: 'Europe/Paris' },
'DE': { language: 'de-DE', currency: 'EUR', timezone: 'Europe/Berlin' },
'ES': { language: 'es-ES', currency: 'EUR', timezone: 'Europe/Madrid' },
'IT': { language: 'it-IT', currency: 'EUR', timezone: 'Europe/Rome' },
'BR': { language: 'pt-BR', currency: 'BRL', timezone: 'America/Sao_Paulo' },
'JP': { language: 'ja-JP', currency: 'JPY', timezone: 'Asia/Tokyo' },
'KR': { language: 'ko-KR', currency: 'KRW', timezone: 'Asia/Seoul' },
'CN': { language: 'zh-CN', currency: 'CNY', timezone: 'Asia/Shanghai' }
};
}
// Get regional settings for country
getRegionalSettings(countryCode) {
return this.regionalSettings[countryCode] || this.regionalSettings['US'];
}
// Get products for specific region
async getProductsForRegion(countryCode, filters = {}) {
const settings = this.getRegionalSettings(countryCode);
const regionalFilters = {
...filters,
language: settings.language,
currency: settings.currency
};
const params = new URLSearchParams();
Object.entries(regionalFilters).forEach(([key, value]) => {
if (value !== undefined) {
params.append(key, value);
}
});
const response = await fetch(`${this.baseUrl}?${params}`, {
headers: {
'Authorization': `Bearer ${this.apiToken}`,
},
});
if (!response.ok) {
const errorData = await response.json();
throw new Error(`API Error: ${errorData.message}`);
}
const products = await response.json();
// Add regional context to products
return products.map(product => ({
...product,
regionalContext: {
countryCode,
language: settings.language,
currency: settings.currency,
timezone: settings.timezone
}
}));
}
// Get product for specific region
async getProductForRegion(productId, countryCode) {
const settings = this.getRegionalSettings(countryCode);
try {
const response = await fetch(
`${this.baseUrl}/${productId}?language=${settings.language}¤cy=${settings.currency}`,
{
headers: {
'x-api-key': `${this.apiKey}`,
},
}
);
if (!response.ok) {
const errorData = await response.json();
throw new Error(`API Error: ${errorData.message}`);
}
const product = await response.json();
return {
...product,
regionalContext: {
countryCode,
language: settings.language,
currency: settings.currency,
timezone: settings.timezone
}
};
} catch (error) {
console.error(`Failed to get product for region ${countryCode}:`, error);
throw error;
}
}
// Get regional product recommendations
async getRegionalRecommendations(countryCode, destination, options = {}) {
const products = await this.getProductsForRegion(countryCode, {
destination,
status: 'ACTIVE',
...options
});
// Sort by regional preferences
return products.sort((a, b) => {
// Prioritize products with regional context
if (a.regionalContext && !b.regionalContext) return -1;
if (!a.regionalContext && b.regionalContext) return 1;
// Sort by price
return (a.pricing?.price || 0) - (b.pricing?.price || 0);
});
}
// Format product for regional display
formatProductForRegion(product, countryCode) {
const settings = this.getRegionalSettings(countryCode);
return {
...product,
displayName: product.name,
displayPrice: this.formatPriceForRegion(product.pricing?.price || 0, settings.currency, settings.language),
displayCurrency: settings.currency,
displayLanguage: settings.language,
regionalSettings: settings
};
}
formatPriceForRegion(price, currency, language) {
const formatter = new Intl.NumberFormat(language, {
style: 'currency',
currency: currency
});
return formatter.format(price);
}
}
// Usage examples
const regionalManager = new RegionalCustomizationManager('YOUR_API_KEY');
// Get products for French market
regionalManager.getProductsForRegion('FR', { destination: 'TUR' })
.then(products => {
console.log('Products for French market:', products);
});
// Get product for German market
regionalManager.getProductForRegion('turkey-evisa-tourism', 'DE')
.then(product => {
console.log('Product for German market:', product);
});
// Get regional recommendations
regionalManager.getRegionalRecommendations('US', 'TUR')
.then(products => {
console.log('Recommendations for US market:', products);
});Implement a robust language fallback system:
class LanguageFallbackManager {
constructor(apiKey) {
this.apiKey = apiKey;
this.baseUrl = 'https://api.joinsherpa.io/v2/products';
this.fallbackChain = {
'en-GB': ['en-US', 'en'],
'en-CA': ['en-US', 'en-GB', 'en'],
'fr-CA': ['fr-FR', 'fr'],
'pt-PT': ['pt-BR', 'pt'],
'zh-TW': ['zh-CN', 'zh'],
'zh-HK': ['zh-CN', 'zh-TW', 'zh']
};
}
// Get fallback languages for a given language
getFallbackLanguages(language) {
return this.fallbackChain[language] || ['en-US'];
}
// Get product with fallback support
async getProductWithFallback(productId, language, currency = 'USD') {
const fallbackLanguages = [language, ...this.getFallbackLanguages(language)];
for (const fallbackLang of fallbackLanguages) {
try {
const response = await fetch(
`${this.baseUrl}/${productId}?language=${fallbackLang}¤cy=${currency}`,
{
headers: {
'x-api-key': `${this.apiKey}`,
},
}
);
if (response.ok) {
const product = await response.json();
return {
...product,
actualLanguage: fallbackLang,
requestedLanguage: language,
isFallback: fallbackLang !== language
};
}
} catch (error) {
console.warn(`Failed to get product in ${fallbackLang}:`, error.message);
continue;
}
}
throw new Error(`Failed to get product ${productId} in any supported language`);
}
// Get products with fallback support
async getProductsWithFallback(filters = {}) {
const language = filters.language || 'en-US';
const fallbackLanguages = [language, ...this.getFallbackLanguages(language)];
for (const fallbackLang of fallbackLanguages) {
try {
const params = new URLSearchParams();
params.append('language', fallbackLang);
Object.entries(filters).forEach(([key, value]) => {
if (key !== 'language' && value !== undefined) {
params.append(key, value);
}
});
const response = await fetch(`${this.baseUrl}?${params}`, {
headers: {
'x-api-key': `${this.apiKey}`,
},
});
if (response.ok) {
const products = await response.json();
return products.map(product => ({
...product,
actualLanguage: fallbackLang,
requestedLanguage: language,
isFallback: fallbackLang !== language
}));
}
} catch (error) {
console.warn(`Failed to get products in ${fallbackLang}:`, error.message);
continue;
}
}
throw new Error(`Failed to get products in any supported language`);
}
// Check if language is supported
isLanguageSupported(language) {
const supportedLanguages = [
'en-US', 'en-GB', 'fr-FR', 'de-DE', 'es-ES',
'it-IT', 'pt-BR', 'ja-JP', 'ko-KR', 'zh-CN'
];
return supportedLanguages.includes(language);
}
// Get best available language
getBestAvailableLanguage(requestedLanguage) {
if (this.isLanguageSupported(requestedLanguage)) {
return requestedLanguage;
}
const fallbackLanguages = this.getFallbackLanguages(requestedLanguage);
for (const fallbackLang of fallbackLanguages) {
if (this.isLanguageSupported(fallbackLang)) {
return fallbackLang;
}
}
return 'en-US'; // Default fallback
}
}
// Usage examples
const fallbackManager = new LanguageFallbackManager('YOUR_API_KEY');
// Get product with fallback support
fallbackManager.getProductWithFallback('turkey-evisa-tourism', 'en-CA', 'CAD')
.then(product => {
console.log('Product with fallback:', product);
if (product.isFallback) {
console.log(`Using fallback language: ${product.actualLanguage}`);
}
});
// Get products with fallback support
fallbackManager.getProductsWithFallback({
destination: 'TUR',
language: 'fr-CA'
}).then(products => {
console.log('Products with fallback:', products);
});
// Check language support
const isSupported = fallbackManager.isLanguageSupported('en-CA');
console.log('Is en-CA supported:', isSupported);
// Get best available language
const bestLanguage = fallbackManager.getBestAvailableLanguage('en-CA');
console.log('Best available language:', bestLanguage);`} />
## Best Practices
### Language Management
- **Consistent Naming**: Use consistent language codes (ISO 639-1)
- **Fallback Support**: Implement robust fallback mechanisms
- **Content Validation**: Validate localized content for accuracy
- **Translation Quality**: Ensure high-quality translations
### Currency Handling
- **Regional Mapping**: Map languages to appropriate currencies
- **Exchange Rates**: Use current exchange rates for conversions
- **Formatting**: Format prices according to regional standards
- **Validation**: Validate currency codes and amounts
### Performance Optimization
- **Caching**: Cache localized content for better performance
- **Lazy Loading**: Load language-specific content on demand
- **CDN**: Use CDN for static localized content
- **Compression**: Compress localized content for faster delivery
### User Experience
- **Language Detection**: Automatically detect user's preferred language
- **Language Switching**: Provide easy language switching
- **Consistent UI**: Maintain consistent UI across languages
- **Accessibility**: Ensure accessibility in all languages
<InfoCard title="💡 Localization Tips" color="blue">
- Use language fallback systems for better user experience
- Map languages to appropriate currencies for each region
- Implement regional customization for different markets
- Validate localized content for accuracy and completeness
</InfoCard>
<InfoCard title="🚀 Getting Started" color="green">
Start with basic localization for your primary markets and gradually
expand to support additional languages and regions.
</InfoCard>