Skip to main content
Version: 2.x

Translate your application

International e-commerce websites often need to translate their UI into several languages to make sure that they reach a broader range of customers. This documentation will show how this works for static content in your application.

note

If you want to configure your application to support multiple languages, please refer to Configure multiple stores.

Front-Commerce manages your translations by using react-intl, a standard library in the React ecosystem. This library works by transforming your static values in React Components. These components will then fetch your translations and display them in your application.

Declare translations in your application

For instance, let's see how to transform your values in react-intl Components.

Strings

import { FormattedMessage } from "react-intl";

<FormattedMessage
id="My.Component.Id.messageId"
defaultMessage="Default translation"
/>;

Dates

import { FormattedDate } from "react-intl";

<FormattedDate value={date} year="numeric" month="long" day="2-digit" />;

Prices

import { FormattedNumber } from "react-intl";

<FormattedNumber
value={value.amount}
style="currency"
currency={value.currency}
/>;
note

However, for this particular use case we have abstracted this in Front-Commerce with the theme/components/atoms/Price component (and its variants: ProductPrice, PriceOrFree). We recommend you to use it instead, so you could benefit from better integration with its related GraphQL Type.

You can find the full set of components in the React Intl Components documentation

Without React Component

These components will be enough in most cases. However, the issue with these is that it wraps your string within a React Element, which may be troublesome when you actually need to handle the string itself.

For instance, this is the case when you want to add some label attributes to your DOM elements.

<span class="icon" aria-label="Icon title displayed for screen readers" />

Fortunately, this is correctly handled by react-intl if you use defineMessages combined with injectIntl HOC or the useIntl hook.

You can learn more about hooks in the react documentation.

import { defineMessages, useIntl } from "react-intl";

const messages = defineMessages({
ariaLabel: {
id: "screen-reader-icon-title",
defaultMessage: "Icon title displayed for screen readers",
},
});

const MyComponentWithHook = (props) => {
const intl = useIntl();
return (
<span class="icon" aria-label={intl.formatMessage(messages.ariaLabel)} />
);
};

Translate what's in your components

Now that you have defined what should be translated in your application, you actually need to translate your application. This is a two-step process:

  1. Run the following script that will fetch all your translatable strings in your application and gather them in a JSON file located in translations/[locale].json

    npm run translate
  2. Translate the strings available in those files, and you are good to go 🙂

    ProTip™

    You can use tools like BabelEdit to help translate and keep your translations in sync.

Note that for some translations you won't need to change anything. This usually happens for the default language and for business phrases such as "SKU", etc.

However, react-intl will warn you against those cases because it might be an actual translation that is missing. Luckily, you can opt-out of this warning for specific translations ids by adding it to the translations/whitelist_[locale].json file.

This task can be daunting at first, but it will make your life easier in the future when you will need to know which string was not translated in a recent update.

Translations fallback

With react-intl translations are usually grouped into a single file. In our case, we would expect them to be in translations/[locale].json. But in Front-Commerce's case, we don't want you to be troubled by translations that are handled by the core.

That's why Front-Commerce uses a mechanism called translations fallbacks. Instead of relying on a single file for translations, Front-Commerce will look out for translations in the following locations and pick the ones that exist:

Front-Commerce core

  • node_modules/front-commerce/translations/[short-locale].json or
  • node_modules/front-commerce/translations/[locale].json

from your modules declared in .front-commerce.js

  • <my-module>/translations/[short-locale].json or
  • <my-module>/translations/[locale].json

from your project

  • translations/[short-locale].json or
  • translations/[locale].json

[short-locale] here means that we are only taking the first particle of the locale. E.g. if the locale was en-GB, the short-locale would be en. That's how en-GB would load translations from both en.json and en-GB.json files.

If a translation key is defined in multiple files, the last one (according to the above list) will be be used. This is especially useful if you want to change the core's translations.

ProTip™

You can see exactly which translation files are used by opening the files located in .front-commerce/translations/.

Please keep in mind that when you run npm run translate, new keys will be added to translations/[locale].json. However, if you are developing a module it can make sense to add the translations to <my-module>/translations/[locale].json. You can do this by using npm run translate -- -m <my-module>.

About dynamic content

react-intl lets you translate your static content. But what about dynamic content? Things like product title and description, CMS pages, etc.

This is done on the GraphQL side. The principle is that when a user is connected to Front-Commerce, they will be assigned a storeViewCode in their session (see Configure multiple stores for more details).

This code will then be used by your GraphQL loaders to retrieve the correct content from your backend. Learn more about GraphQL loaders.