Reactive Stack

Translate Your React.js App With React-Intl

Cover Image for Translate Your React.js App With React-Intl
Benoit Tremblay
Benoit Tremblay

How do you translate a React.js app efficiently? The answer is simple: react-intl. It is by far the best option to use in React and provide awesome tooling to help you manage those translations easily as well as help translators use standards they know.

Write Your Translable Text

The main component in react-intl for text translation is the <FormattedMessage /> component like so.

npm install --save react-intl
import { FormattedMessage } from 'react-intl';

export default function Hello({ name }) {
  return (
    <FormattedMessage
      description="Greeting message"
      defaultMessage="Hello {name}, nice to see you!"
      values={{
        name,
      }}
    />
  );
}

You can see a few interesting things here. First, we have a description prop that tells the translator what this message is. It is super useful to give more context on where the text is being used. However, it will never be displayed. You will also be able to strip it away in your production build.

You can also notice the way defaultMessage is being formatted. Instead of splitting the beginning and the end of the sentence, it contains a variable with the name of the user. That syntax is super powerful and based on ICU syntax. Here is a couple of things you can do with it:

  • Plurals: {count, plural, one {cat} other {cats}} where count is the name of the value to use to check if it is plural or not.
  • Genders: {gender, female {wife} male {husband}} where the gender value is male or female
  • Formatting (date, time, currency, numbers): {published, date, short}

You can read more about the ICU syntax.

You might also want to use a text outside of a render. Maybe you need to pass that value to a component and it only accepts strings. You can do so by using intl.formatMessage instead with the same parameters.

Extracting the Translations

Before we extract the labels, we have to add a babel plugin to generate the ID as well as do a few optimizations.

npm install --save-dev babel-plugin-formatjs

.babelrc.json

{
  "plugins": [
    [
      "formatjs",
      {
        "idInterpolationPattern": "[sha512:contenthash:base64:6]",
        "ast": true
      }
    ]
  ]
}

Now that you have some text to translate, you can extract them by using the CLI tool.

npm install --save-dev @formatjs/cli

You can now create a script with the extraction command:

formatjs extract 'src/**/*.ts*' --out-file lang/en.json --id-interpolation-pattern '[sha512:contenthash:base64:6]'

This will generate a JSON that can be translated. You also have the option to target other Translation Management System format.

Serving the Translation

Now it's time to serve your translation so that it can display other languages than your default one. First we need to compile your translated file so that it strip away the unnecessary stuff.

formatjs compile lang/fr.json --ast --out-file compiled-lang/fr.json

When you have your compiled file, now you can use the <IntlProvider /> to serve the correct langauge.

import React from 'react';
import ReactDOM from 'react-dom';
import { IntlProvider } from 'react-intl';

function loadLocaleData(locale: string) {
  switch (locale) {
    case 'fr':
      return import('compiled-lang/fr.json');
    default:
      return import('compiled-lang/en.json');
  }
}

function App({ locale, message }) {
  return (
    <IntlProvider locale={locale} defaultLocale="en" messages={messages}>
      <MainApp />
    </IntlProvider>
  );
}

async function bootstrapApplication(locale, mainDiv) {
  const messages = await loadLocaleData(locale);
  ReactDOM.render(<App locale={locale} messages={messages} />, mainDiv);
}

One important part to notice is the loadLocaleData. It is using code-splitting to only load the active language. It is a very good way to make sure your bundle size doesn't get too large because it includes all langauges.

Do you want to better organize your apps? Read How to Organize Your React.js App Folders.

Want More Content About React.js?
Subscribe to Our Newsletter

* indicates required

We will never spam you.