# Translations

Most of the files in this folder are generated by `react-intl` **CLI tool**:

- `<root>/translations/en-US.json` <- output of _extracting_ the default messages, which you can send to your translators.
- `<root>/translations/[locale].json` <- the files that your translators make for the other locales
- `<root>/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

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 replacing `en-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`.

## Formatting Messages

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="..." />`

### Adding Message Id

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.

## Testing with a Pseudo Locale

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: `[!! Ṕŕíííṿâćććẏ ṔṔṔŏĺíííćẏ !!]`

# Localization

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](https://documentation.b2c.commercecloud.salesforce.com/DOC1/topic/com.demandware.dochelp/OCAPI/current/usage/Localization.html).

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](https://documentation.b2c.commercecloud.salesforce.com/DOC2/topic/com.demandware.dochelp/content/b2c_commerce/topics/admin/b2c_configuring_site_locales.html).

Here’s an example of locale configuration in sites configuration:

```js
// 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'
      }
   }
]
```

## How to Add a New Locale

The process for adding a new locale is as follows:

1. Create/enable the new locale in Business Manager of your B2C Commerce instance
2. Enable the locale's currency too in Business Manager
3. Add the new locale and its currency to your targeted site in `config/sites.js`
4. 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
5. Place the files you receive from your translation team into the `<root>/translations/` folder
6. Run `npm run compile-translations`

## Tips

Here are a few useful things to know for developers.

### User-Preferred Locales vs. App-Supported Locales

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:

1. Get the app-supported locales, which are defined in each site object in `config/sites.js` (under `l10n.supportedLocales` of your targeted site).
2. 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.
3. If there’s a match between these 2 sets of locales, then the app would use it as the target locale.
4. Otherwise, the app would fall back to the locale of the inline `defaultMessage`s. 

### How to Detect the Active Locale

- Within component render, `useLocale` hook is available to you: `const locale = useLocale()`
- Within a page’s `getProps` you can call utility function `resolveLocaleFromUrl` like this:

```js
ProductDetail.getProps = async ({res, params, location, api}) => {
    const locale = resolveLocaleFromUrl(`${location.pathname}${location.search}`)
    ...
}
```

### Dynamic Loading of the Translation Files

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.

### Link Component

The generated project comes with its own `Link` component. It automatically inserts the locale in the URLs for you.
