This is the legacy documentation of Project-level Custom Applications, which is in maintenance mode. Visit the new documentation for Org-level Custom Applications.
Translations
Merchant Center applications use react-intl
, a library built on top of the ECMAScript Internationalization API.
In the React components, you can use things like <FormattedMessage>
or intl.formatMessage
to render the correct translation message based on the active locale
.
We usually define a messages.js
file co-located to the React component using those messages. The file defines messages as following:
import { defineMessages } from 'react-intl';export default defineMessages({title: {id: 'StateMachines.ListView.title',description: 'The page title of state machines list',defaultMessage: 'State Machines',},});
This is the default message, which will be used in case there is no translation available for the given locale
.
Extracting messages for translations
To generate translation files, you can use the official @formatjs/cli
package to extract message from React Intl messages files. For example:
formatjs extract \--out-file=./src/i18n/data/core.json \'src/**/messages.js'
Based on your translation tool, you may need to transform the extracted messages to the appropriate format. For that you can write a formatter file and pass it as the --format
option to the script.
formatjs extract \--format=./intl-transformer.js--out-file=./src/i18n/data/core.json \'src/**/messages.js'
At commercetools we use Transifex as our translation tool. Therefore, in our applications we generate a core.json
file with the key being the message id and the value being the default Intl message.
{"StateMachines.ListView.title": "State Machines"}
The core.json
is the so-called source file, which should be used as reference file for the translations in the other locales.
As a convention, we store the translation files in a i18n
folder:
└── src└── i18n└── data├── core.json├── en.json└── de.json
Using the messages in the application
The JSON files containing the translations need to be loaded within the application. The <ApplicationShell>
expects a applicationMessages
prop that is used to load the messages in the react-intl
provider.
The applicationMessages
prop can either be a JSON object or a function returning a Promise with the loaded messages.
To keep the bundle size low, the application should only load the messages for a specific locale and not all of them. This can be achieved by using the Code-Splitting feature.
Given the translation messages are located in the i18n/data
folder, you can define a function to dynamically load the messages:
// entry-point.jsconst loadMessages = lang => {let loadAppI18nPromise;switch (lang) {case 'de':loadAppI18nPromise = import('../../i18n/data/de.json' /* webpackChunkName: "app-i18n-de" */);break;case 'es':loadAppI18nPromise = import('../../i18n/data/es.json' /* webpackChunkName: "app-i18n-es" */);break;default:loadAppI18nPromise = import('../../i18n/data/en.json' /* webpackChunkName: "app-i18n-en" */);}return loadAppI18nPromise.then(result => result.default,error => {console.warn(`Something went wrong while loading the app messages for ${lang}`,error);return {};});};const Application = () => (<ApplicationShell// other propsapplicationMessages={loadMessages}/>);