Localization

Utilities to load and manage localization data.

Installation

yarn add @commercetools-frontend/l10n

Additionally, install the peer dependency (if not present):

yarn add react

Supported locales

  • en
  • de
  • es
  • fr-FR
  • pt-BR
  • zh-CN

To retrieve supported locales, use the getSupportedLocales and getSupportedLocale helper functions.

import {
getSupportedLocales,
getSupportedLocale,
} from '@commercetools-frontend/l10n';
// `getSupportedLocales` returns all supported locales
console.log(getSupportedLocales());
// ["en", "de", "es", "fr-FR", "pt-BR", "zh-CN"]
// `getSupportedLocale` returns the specified locale if it's supported; otherwise, it returns the default locale
console.log(getSupportedLocale('en')); // Output: 'en'
console.log(getSupportedLocale('sv')); // Output: 'en'

Hooks

useCountries

A React hook that loads country data based on the provided locale.

import { useCountries } from '@commercetools-frontend/l10n';
function MyComponent() {
const { isLoading, data: countries } = useCountries('en');
if (isLoading) return <LoadingSpinner />;
return <div>Countries: {JSON.stringify(countries)}</div>;
// Countries format: { <countryCode>: <countryLabel> }
// Example: { "de": "Germany" }"
}

useCurrencies

A React hook that loads currency data based on the provided locale.

import { useCurrencies } from '@commercetools-frontend/l10n';
function MyComponent() {
const { isLoading, data: currencies } = useCurrencies('en');
if (isLoading) return <LoadingSpinner />;
return <div>Currencies: {JSON.stringify(currencies)}</div>;
// Currencies format: { <currencyCode>: { label, symbol } }
// Example: { "EUR": { "label": "Euro", "symbol": "€" } }
}

useLanguages

A React hook that loads language data based on the provided locale.

import { useLanguages } from '@commercetools-frontend/l10n';
function MyComponent() {
const { isLoading, data: languages } = useLanguages('en');
if (isLoading) return <LoadingSpinner />;
return <div>Languages: {JSON.stringify(languages)}</div>;
// Languages format: { <languageCode>: { language, country } }
// Example with primary language: { "es": { "language": "Spanish" } }
// Example with language of a region:
// { "es-AR": { "language": "Spanish", "country": "Argentina" } }
}

useTimeZones

A React hook that loads time zone data based on the provided locale.

import { useTimeZones } from '@commercetools-frontend/l10n';
function MyComponent() {
const { isLoading, data: timeZones } = useTimeZones('en');
if (isLoading) return <LoadingSpinner />;
return <div>Time zones: {JSON.stringify(timeZones)}</div>;
// Time zones format: { <timezone>: { name, abbr, offset } }
// Example:
// { "Europe/Berlin": { "name": "Central European Time - Berlin", "abbr": "CEST", "offset": "+02:00" } }
}

Utilities

Within the Common API Types in the Composable Commerce HTTP API is the LocalizedString type.

In the following example, the Product name is defined as a LocalizedString:

Product (Composable Commerce HTTP API)JavaScript
{
// `name` is a `LocalizedString`
// as defined by https://docs.commercetools.com/api/projects/products#productdata
name: {
en: 'Milk';
}
}

However, the Composable Commerce GraphQL API represents the LocalizedString type differently:

type TLocalizedString = {
__typename?: 'LocalizedString';
locale: string;
value: string;
};
Product (returned from the Composable Commerce GraphQL API)JavaScript
{
nameAllLocales: [
{
locale: 'en',
value: 'Milk',
},
];
}

To distinguish these two formats, in the context of the Merchant Center, the graphql-shape is referenced as LocalizedField. The following helper functions are provided to transform values between these two formats:

  • applyTransformedLocalizedStrings
  • applyTransformedLocalizedFields
  • transformLocalizedFieldToLocalizedString
  • transformLocalizedStringToLocalizedField

Additionally, the formatLocalizedString helper function converts a LocalizedString into a string, deriving the value based on the provided data locale and fallback order.

applyTransformedLocalizedStrings

A helper function that transforms an object containing a LocalizedString-shaped value into an object with a list of LocalizedField-shaped values based on specified field name mappings.

The primary use case is to convert the LocalizedString field format when integrating REST API responses within GraphQL queries.

Example usageJavaScript
const output = applyTransformedLocalizedStrings(
{
id: '1',
name: { en: 'Milk', de: 'Milch' },
},
[{ from: 'name', to: 'nameAllLocales' }]
);
console.log(output);
// { id: 1, nameAllLocales: [{ locale: 'de', value: 'Milch' }, { locale: 'en', value: 'Milk' }] }

applyTransformedLocalizedFields

A helper function that transforms an object with a list of LocalizedField values into a LocalizedString-shaped object based on specified field name mappings.

Example usageJavaScript
const product = {
nameAllLocales: [
{
locale: 'en',
value: 'Milk',
},
{
locale: 'de',
value: 'Milch',
},
],
};
const fieldNameTransformationMappings = [
{
from: 'nameAllLocales',
to: 'name',
},
];
const transformedProduct = applyTransformedLocalizedFields(
product,
fieldNameTransformationMappings
);
console.log(transformedProduct);
// { name: { de: 'Milch', en: 'Milk' } }

The primary use case is transforming response fields shaped as LocalizedFields from the Composable Commerce GraphQL API for use in views with @commercetools-frontend/ui-kit components.

Example: Transforming response fieldsJavaScript React
// fetching a product from the Composable Commerce GraphQL API returns a product with a `nameAllLocales`
const product = useMcQuery(ProductQuery, {
context: GRAPHQL_TARGETS.COMMERCETOOLS_PLATFORM,
});
// Since LocalizedTextInput accepts a value in the format `{ [key: string]: string }`,
// we transform our product to match the required shape
const transformedProduct = applyTransformedLocalizedFields(
product,
fieldNameTransformMappings
);
// Finally, we are ready to render our form with the correctly shaped `name`
return <LocalizedTextInput name="name" value={transformedProduct.name} />;

transformLocalizedFieldToLocalizedString

A helper function that transforms a list of LocalizedField values into a LocalizedString-shaped object.

This transformation is helpful when converting data to initialize a form.

Example usageJavaScript
const output = transformLocalizedFieldToLocalizedString([
{ locale: 'en', value: 'Milk' },
{ locale: 'de', value: 'Milch' },
]);
console.log(output);
// {en: 'Milk', de: 'Milch'}

transformLocalizedStringToLocalizedField

A helper function that transforms a LocalizedString object into a list of LocalizedField values.

This transformation is helpful for form conversions, where you need to prepare data for Composable Commerce GraphQL API mutations that expect LocalizedString as the input type.

Example usageJavaScript
const output = transformLocalizedStringToLocalizedField({
en: 'Milk',
de: 'Milch',
});
console.log(output);
// [{ locale: 'en', value: 'Milk' }, { locale: 'de', value: 'Milch' }]

formatLocalizedString

A helper function that transforms a LocalizedString to a string, deriving the value from the provided data locale and fallback order. If the value cannot be derived, a fallback value is used instead.

The data locale is a value controlled by the Merchant Center user using the data locale switcher. The list of available options is derived from the list of languages specified in the project. The selected value can be read from the dataLocale property in the application context.

If the selected data locale does not match any of the localized string values, it is recommended to display a fallback value using the formatLocalizedString function.

Example usage

The following examples are based on the following Product object:

Product exampleJavaScript
const product = {
name: {
en: 'Milk',
de: 'Milch',
},
};

Scenario 1

The Merchant Center user has selected the de data locale. Since our example Product contains a value for the de locale, the localized value "Milch" is returned, as expected.

const translatedName = formatLocalizedString(product, {
key: 'name',
locale: 'de',
});
console.log(translatedName);
// 'Milch'

Scenario 2

The Merchant Center user has selected the sv data locale, however, our example Product does not contain a value for this locale.

In this case, the formatLocalizedString function retrieves the next available value from product.name based on a predefined order of locales (further details in the fallback order section). In this case, it falls back to the en locale and appends a hint (EN) to indicate that this value is from an alternate locale.

const translatedName = formatLocalizedString(product, {
key: 'name',
locale: 'sv',
});
console.log(translatedName);
// 'Milk (EN)'

Scenario 3

The Merchant Center user has selected the de-AT data locale. While our example Product specifies a value for de, it does not specify a value for de-AT.

In this case, "Milch" is returned because the formatLocalizedString function extracts the primary language subtag from the locale and then tries to match it to the available values. Since de is the primary language subtag of de-AT, the function selects de as the closest available value from product.name.

const translatedName = formatLocalizedString(product, {
key: 'name',
locale: 'de-AT',
});
console.log(translatedName);
// 'Milch'

Fallback

To provide greater flexibility, the formatLocalizedString function allows you to specify a fallback value, which is used as a last resort.

const translatedName = formatLocalizedString(product, {
obj: product,
key: 'name',
locale: 'sv',
fallback: '-',
});

If no explicit fallback is provided, and no value can be derived based on the locale and fallback order (see next section), an empty string is returned.

Fallback order

When no matching locale is found, the formatLocalizedString function selects the next available value from product.name.

To control the order in which the function attempts to find a match before resorting to the specified fallback value, you can specify a list of locales using fallbackOrder. This allows for customization of the fallback strategy to prioritize specific locales or values as needed.

const translatedName = formatLocalizedString(product, {
obj: product,
key: 'name',
locale: 'sv',
fallbackOrder: ['en', 'de', 'es', 'it'],
fallback: '-',
});

When to use

When rendering a LocalizedString for a given Resource, it’s practical to use formatLocalizedString along with the application context. This approach leverages the project languages, to ensure that the most appropriate localized value is displayed.

import Text from '@commercetools-uikit/text';
import { useApplicationContext } from '@commercetools-frontend/application-shell-connectors';
import { NO_VALUE_FALLBACK } from '@commercetools-frontend/constants';
const { dataLocale, projectLanguages } = useApplicationContext(
(applicationContext) => ({
dataLocale: applicationContext.dataLocale,
// The Application Context also exposes the languages that are defined on the Project settings
// we can rely on this to determine the fallback order.
// This helps with consistency, although you can specify the fallback order however you want
projectLanguages: context.project.languages,
})
);
return (
<Text.Headline>
{formatLocalizedString(product, {
key: 'name',
locale: dataLocale,
fallback: NO_VALUE_FALLBACK,
fallbackOrder: projectLanguages,
})}
</Text.Headline>
);