bene : studio is a global consultancy, helping startups, enterprises and HealthTech companies to have better product

Internationalize your React App with React Intl

React-intl extracting messages and generating auto id

At bene : studio we love knowledge sharing to help the community of professionals. With 10+ years and over 100 projects behind us, we have a vast amount of experience. This is why we have launched a knowledge base on our blog with regular updates of tutorials, best practices, and open source solutions.

These materials come from our internal workshops with our team of developers and engineers.

Pardon the interruption, we have an important message!

We are looking to expand our team with talented developers. Check out our open positions and apply.

What is internationalization (i18n) and why is it important?

We can read the following definition on formatjs.io:

Internationalized software supports the languages and cultural customs of people throughout the world. Localized software adapts to a specific language and culture by translating text into the user’s language and formatting data in accordance with the user’s expectations.

Besides the translations of simple messages, you can also make use of pluralization, create parameterized messages, or even localized time formats.

The popular and well-known package called react-intl makes internationalization an easy task: 

https://www.npmjs.com/package/react-intl

But what if we want more than just creating translated messages and using them? In this blog post we are dealing with extra functionalities that make react-intl usage even more convenient. We are starting with basic usage, then cover more advanced topics. Feel free to skip any chapter if you are already familiar with it.

How React-intl works

Intl Provider

To start using react-intl, first similarly to redux, you need a provider. There you have to set the locale, defaultLocale, and messages.

Locale can be used later to make specific decisions, but its main purpose is to make the formatting of the dates. Most projects will probably don’t use the locale variable, but in some cases it will be a must have. Default locale is used when defining default messages, we’ll discuss it later. The messages property is a JSON-based object containing the translation of the site.

It is advisable to use dot notation to define the IDs.

Defining messages

To use messages in a component we advise having a messages file next to each component.

Here you can set an id and a default message. The defaultMessage property is used when there is no definition in the JSON file for the specific language. Also good to see them through the development. You can also provide a description for other developers.

FormattedMessage and formatMessage

There are two ways to format a message, depending on your needs.

To use it as a component, use FormattedMessage.

Or if you need a string version, you can use the formatMessage function instead. This is a must have for input placeholders for example.

useIntl and injectIntl

If you need the formatMessage or any other function (like formatDate), you need the intl context. In functional components you can use the useIntl hook, see the example above (available from version 3). Both in functional components and in React Components you can use the injectIntl.

Normal workflow

The order of the following workflow can be customized.

  • Write your messages in the component (optional)
  • Define the messages in the messages file
  • Write the new message to the JSON file
  • Use the message with FormattedMessage or formatMessage

Workflow with extracting messages

The purpose of extracting messages is to make the development faster and increase the readability of the code. It will be faster because you do not need to add the messages to the JSON file during development and the code will be more readable because there will be default messages to help understand the context besides the variables. A message id or variable can be a good start, but the default message is the best option.

The order of the workflow with extracting messages is the following.

  • Write your messages in the component (optional)
  • Define the messages in the messages file
  • Use the message with FormattedMessage or formatMessage

The last step is to extract the messages, which can happen before releases.

“extract-messages”: “NODE_ENV=development extract-messages -l=en,hu -o src/messages -d en –flat true ‘src/**/!(*.test).js'”

You can define which messages should be included. The default flag (-d) is telling the extractor which language should be populated with the default messages, the other languages will be left empty.

You can use the flat option at first. If you would like to make the JSON files smaller you go width the non-flat version, but then you will need a flattener method when using the messages.

You can also run some calculations if it’s worth the non-flattened version or not, but the compressions work quite well nowadays, so you may save a few kilobytes.

Auto id

If you would like to make the creation of IDs easier, you can use auto id generation.

In the case of ESLint, you need to have a .babelrc file. (You have to eject in case of create-react-app, or you can use react-native-rewired)

In case of Typescript, you also need a .babelrc.

Plus, you have to add the following plugin to your tsconfig file.

Usage

Here comes the easy part, because you don’t need to specify the ID.

src/App/messages.ts

Base on your file structure, the messages JSON file should look like this after extracting the messages:

Example

https://github.com/benestudio/react-intl-extract-autoid

Fun facts, special usage

American vs British English

When localizing your application the first step can be to make a different American (en-us) and British (en-gb) version. React-intl treats “en” as “en-us”, so if you are not defining the US or UK version then it will go with the US version.

A minimum effort can be to just set the correct locale based on the language of the user’s browser. This can help to make the dates look localized at least.

Other differences include using different words like biscuit (UK) vs cookie (US), spellings like color (US) vs colour (UK).

Variables

You can use variables in your messages the following way.

Pluralization

You can use react-intl to pluralize your messages.

In English it may be trivial since the only exception is one, but in other languages, like in Polish, there are 4 cases.

https://developer.mozilla.org.cach3.com/en/Localization_and_Plurals

Using HTML in messages

Until version 3, you could use FormattedHTMLMessage, but it’s no longer supported. Instead, you have to define HTML tags like values.

messages.js

In the component:

Thanks to that, you don’t have to worry that the translators may misspell something. This way you can also easily change the attributes of the tags, like the href attribute.

If you wish to have line-breaks in the message, instead of <br> you have to use it with a variable like this.

The reason for this is that the package doesn’t allow self-closing tags.

We are done, hope you liked this article.

Contribution

You can find the source code on our Github

We invite everyone to leave feedback in the form of an issue or contribute by creating a pull request.

Our engineers Dani and Gábor contributed to this article.

Did you like this? Join us!

Want to ask some questions? Share them with us via e-mail to partner@benestudio.co and we can set up a talk with our engineers.

Fancy working for the studio where you can work on international projects and write articles like this? Check out our open positions!

Looking for a partner for your next project? Check out our services page to see what we do and let’s set up a free consultation.

React-intl extracting messages and generating auto id

Let bene : studio enhance
your digital product!