How to Automate Translations of Format.JS Locales

by Denis Augsburger

In this blog post we want to show how to integrate machine translation directly in the developer workflow with Format.JS (or their implementations react-intl & ember-intl). As a result you can iteratively develop your app and have the latest translation result directly available.

Usage of Format.JS

We will focus on react-intl but the info is also suitable for ember-intl. There are two ways to use react-intl. You can either use it directly in your components with the provided JSX-Components or you can use them programmatically.

 // programmatical usage
 const message = intl.formatMessage(
    {
      id: "app.todayReminder",
      // Default Message in English
      defaultMessage: "Hello {username}, how are you?",
    },
    {username: "John"}
 );    

 // component usage
 <FormattedMessage
   id="app.todayReminder"
   defaultMessage="Hello {username}, how are you?"
   values={{username: "John"}}
 />

If you define the id, make sure they are unique across all files.

Prepare for Translation

Before you can start to localize your app - either with machine translation or translation agency - you need to extract your locale files from your source code. For Format.JS, there's an extractor via the CLI that does exactly this:

yarn add -D @formatjs/cli

See FormatJS CLI for more information.

Then add the script to the npm package.json.

{ ...
  "scripts": {
     "translate": "formatjs extract --format=simple"
   }
}

This extract command stores all default messages with their corresponding ids in a single JSON file. Without the format=simple parameter it would also extract the descriptions from the components/functions.

Automate Localization with Machine Translation

With Simpleen you can automatically translate your extracted locale files. Simply install simpleen via npm or yarn globally or locally. In this example, we install it locally with the following command:

yarn add -D simpleen

Read more about the Simpleen CLI.

Next you need to configure your project. To do this you run the following:

yarn run simpleen init

Answer the questions and by default a file simpleen.config.json is saved. It could look similar to this:

{
  "source_language": "EN",
  "target_languages": ["FR", "DE", "IT", "JA"],
  "interpolation": "i18n",
  "input_path": "./src/translations/en.json",
  "output_path": "./src/translations/$locale.json",
  "auth_key": "AUTHENTICATION_KEY"
}

The input path accepts glob patterns. With these you can also define multiple input files. Here are some common project strucutres:

Project strucutre Input path Output path
Extracted single locale file ./src/translations/en.json ./src/translations/$locale.json
Extracted single uppercased locale file ./src/translations/EN.json ./src/translations/$LOCALE.json
Multiple locale files in one folder ./src/translations/en/*.json ./src/translations/$locale/$file.json
Locale files in multiple folders ./src/translations/*/en.json ./src/translations/$folder/$locale.json

After initializing your project you can run simpleen translate. Combine this command with the extract command from above and enjoy extraction and translation in one step.

Add the simpleen translate command, i. e. to the translate script of your npm package.

{ ...
  "scripts": {
     "translate": "formatjs extract --format=simple && simpleen translate"
  }
}

Now you can run the translate command and it will automatically export all i18n keys with the default message. It will translate your locale files to each target language.

yarn run translate

This is a good starting point for your i18n project. You are constantly aware of how your project looks and works in other languages. Some projects are fine with machine translations, others will evolve and translations are adapted by professional translators or according to user feedback. Therefore you need to prevent Simpleen to overwrite adapted translations. You can do this seperately for each target language with the following lock command.

yarn run simpleen lock

Run this command after you improved your translations. It is also necessary after moving your translation results around.

Our goal is to improve the developer experience in multi-lingual projects. With the combination of machine translation and localization, we provide faster results to globalize web, app and game projects. You can test and localize your project in new innovative ways, for example with UI and UX tests, community-driven translations, an already translated product for translators or bilingual team members. It gives you the opportunity to release your product or service in multiple languages faster, enter new markets and reach more users/customers.