Multi-Language Support

Provide localized product information and pricing for global markets using the Products V2 API's built-in localization capabilities.

Overview

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.

Key Features

  • Multi-language Product Descriptions: Localize product names, descriptions, and notices
  • Localized Pricing: Display prices in user's preferred currency
  • Regional Customization: Tailor products for specific markets
  • Language-specific Content: Manage content for different languages
  • Automatic Translation: Support for automatic content translation
  • Fallback Support: Graceful fallback to default language

Implementation Examples

1. Basic Localization

Implement basic localization for product information:

Basic
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}&currency=${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);
});

2. Multi-language Product Creation

Create products with multi-language support:

Multi-language
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);
  });

3. Currency Localization

Handle currency localization and conversion:

Currency
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}&currency=${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}&currency=${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);
  });

5. Language Fallback System

Implement a robust language fallback system:

Language
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}&currency=${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>