Most of the files in this folder are generated by react-intl
CLI tool:
app/translations/en-US.json
<- output of extracting the default messages, which you can send to your translators.app/translations/[locale].json
<- the files that your translators make for the other localesapp/translations/compiled/[locale].json
<- output of compiling the messages into AST format- Compiling helps improve the performance because it allows
react-intl
to 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 package.json
for more details.
- To extract the default messages, run
npm run extract-default-translations
to have all the default messages extracted into a json file. By default, en-US.json is the file that's generated. If you wish to extract your messages into a different json file, simply update the script by replacingen-US
with your desired locale. - To compile the translations from all the locales, run
npm run compile-translations
. - To run both an extract and compile, run
npm run build-translations
.
For all the hardcoded translations in your site, write them...
- 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/fallback 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.
To check whether you’ve wrapped all 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 would look like this: [!! Ṕŕíííṿâćććẏ ṔṔṔŏĺíííćẏ !!]
Since the Retail React App supports multiple sites feature, this means each site can have its own localization setup. In each site,
the default locale, supported locales, and currency settings are defined in a site object in config/sites.js
under ll0n
.
The locale ids l10n.supportedLocales[n].id
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 l10n.supportedLocales
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 an example of locale configuration in sites configuration:
// config/sites.js
modules.exports = [
{
id: 'site-id',
l10n: {
supportedCurrencies: ['GBP', 'EUR', 'CNY', 'JPY'],
defaultCurrency: 'GBP',
supportedLocales: [
{
id: 'de-DE',
preferredCurrency: 'EUR'
},
{
id: 'en-GB',
preferredCurrency: 'GBP'
},
{
id: 'es-MX',
preferredCurrency: 'MXN'
},
// other locales
],
defaultLocale: 'en-GB'
}
}
]
The process for adding a new locale is as follows:
- Create/enable the new locale in Business Manager of your B2C Commerce instance
- Enable the locale's currency too in Business Manager
- Add the new locale and its currency to your targeted site in
config/sites.js
- If the new locale is also going to be the locale of your inline default messages:
- Update those default messages to be in that locale's language
- Run
npm run extract-default-translations
to extract the new translations - Send the extracted translations to your translation team
- Place the files you receive from your translation team into the
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 each site object in
config/sites.js
(underl10n.supportedLocales
of your targeted site). - 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
_app
component. - 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 the locale of the inline
defaultMessage
s.
- Within component render,
useLocale
hook is available to you:const locale = useLocale()
- Within a page’s
getProps
you can call utility functionresolveLocaleFromUrl
like this:
ProductDetail.getProps = async ({res, params, location, api}) => {
const locale = resolveLocaleFromUrl(`${location.pathname}${location.search}`)
...
}
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.