Most of the files in this folder are generated by react-intl CLI tool:
pwa/app/translations/en.json<- output of extracting the default messages, which you can send to your translatorspwa/app/translations/[locale].json<- the files that your translators make for the other localespwa/app/translations/compiled/[locale].json<- output of compiling the messages into AST format- Compiling helps improve the performance because it allows
react-intlto skip the parsing step
- Compiling helps improve the performance because it allows
Several npm scripts are available to you that make it easier to use the CLI tool. See pwa/package.json for more details.
- To extract the default messages in your app, run
npm run extract-default-translationsto have all of the default messages extracted into their own JSON file. - To compile the translations from all of the locales, run
npm run compile-translations. - To run both an extract and compile, run
npm run build-translations
The default locale, supported locales, and currency settings are defined in pwa/package.json in an object called l10n.
The locale ids in pwa/package.json follow the format supported by OCAPI and Commerce API: <language code>-<country code> as defined in this InfoCenter topic: OCAPI localization 21.8.
The currency code in l10n.supportedCurrencies and l10n.supportedLocales[n].preferredCurrency follow the ISO 4217 standard.
Important: The supported locale settings in pwa/package.json must match the locale settings for your B2C Commerce instance. For more information about configuring locales on a B2C Commerce instance, see this InfoCenter topic: Configure Site Locales.
Here’s the default locale configuration in pwa/package.json:
"l10n": {
"supportedCurrencies": [
"GBP",
"EUR",
"CNY",
"JPY"
],
"defaultCurrency": "GBP",
"supportedLocales": [
{
"id": "en-GB",
"preferredCurrency": "GBP"
},
{
"id": "fr-FR",
"preferredCurrency": "EUR"
},
{
"id": "it-IT",
"preferredCurrency": "EUR"
},
{
"id": "zh-CN",
"preferredCurrency": "CNY"
},
{
"id": "ja-JP",
"preferredCurrency": "JPY"
}
],
"defaultLocale": "en-GB"
}
The default messages used by the locale selector are defined in the _app component:
export const defaultLocaleMessages = defineMessages({
'en-GB': {defaultMessage: 'English (United Kingdom)'},
'fr-FR': {defaultMessage: 'French (France)'},
'it-IT': {defaultMessage: 'Italian (Italy)'},
'zh-CN': {defaultMessage: 'Chinese (China)'},
'ja-JP': {defaultMessage: 'Japanese (Japan)'}
})
These messages are used in places where the name of the locale is rendered (such as the locale selector).
When adding a new supported locale to pwa/package.json, you must update the defaultLocaleMessages in the _app component. Not doing so will result in errors when starting the app.
To support localization for multiple locales, write messages...
- inline in the components, so it’s easier to see where in the page or component that they get used in
- and in the default locale (for example, in English)
For example, in your React component, you can add formatted messages like intl.formatMessage({defaultMessage: '...'}) or <FormattedMessage defaultMessage="..." />
At the minimum, only defaultMessage is the required parameter. The message id is optional. If you don’t specify it, the id is auto-generated for you.
During your development, you extract and compile the messages and pass the generated JSON files to the translation team, as well as using the translated files in the app.
We’ve provided the following npm scripts to help you:
npm run build-translationsto extract and compile default messages into the default locale- run this whenever you add a new formatted message to your components to update the default locale's translations
The above script can be further broken down into two sub scripts:
npm run extract-default-translationsto extract the default messagesnpm run compile-translationsto compile all translation files in thepwa/app/translations/folder into Abstract Syntax Tree (AST) formatreact-intlcan use this AST format to bypass the parsing step and thus, save a bit of time.
Whenever you run npm run prod:build, build-translations is run automatically in case you forgot to extract the latest messages.
To check whether you’ve wrapped all of the hardcoded strings with either intl.formatMessage() or <FormattedMessage /> , there’s a quick way to test that by running npm run start:pseudolocale. It runs your local dev server with the locale forced to the pseudo locale.
Loading the site in your browser, you can quickly see that those messages that have been formatted have a long SSS appended to them.
Putting all of the above together, the process for adding a new locale is as follows:
- Enable the new locale in Business Manager of your B2C Commerce instance
- Add the new locale to
pwa/package.json - In the
_appcomponent, add the new locale to thedefaultLocaleMessagesobject and define a default message - If the new locale is your new default locale:
- Update your React components' default messages to the new default locale's language
- In
pwa/package.json, set the new default locale - Run
npm run extract-default-translationsto extract the new default locale's translations intopwa/app/translations/[defaultLocale].json - Send the extracted translations to your translation team
- Place the files you receive from your translation team into the
pwa/app/translations/folder - Run
npm run compile-translations
Here are a few useful things to know for developers.
How a locale gets chosen depends on whether there’s a match found between 2 sets of locales. On a high level, it looks like this:
- Get the app-supported locales, which are defined in
pwa/package.json(underl10n.supportedLocales). - Get the user-preferred locales, which are what the visitors prefer to see. The developer is responsible for fully implementing them in their own projects within the special
_appcomponent. - If there’s a match between these 2 sets of locales, then the app would use it as the target locale.
- Otherwise, the app would fall back to its default locale (which is defined in
package.jsonunderl10n.defaultLocale).
- Within component render,
useIntlhook is available to you:const {locale} = useIntl() - Within a page’s
getPropsthere’s aparamsprop (specificallyparams.locale) coming from the routes that can tell you about which locale is being used in the current page URL.
Using dynamic import, regardless of how many locales the app supports, it would load only one locale at a time.
Initially, on app load, the translated messages are part of the server-rendered html. Afterwards on the client side, when dynamically changing the locale, the app would download the JSON file associated with that locale.
- Each locale is a separate JSON file in the bundle. And it’s served with a 1-year cache header.
- When a new bundle is deployed, you must download the JSON files again.
The generated project comes with its own Link component. It automatically inserts the locale in the URLs for you.