Comparing react i18n: conclusion (part 5)

Learned lessons

2019/01/28 2019/02/20    react javascript


If you value your workflow, and getting everything in a neat package, js-lingui is easier to implement, and it comes with a toolchain maintained by the originator of the library itself. i18next and js-lingui both use the more reasonable syntax <Trans>or t(), whereas React-intl use the 16-character long <FormattedMessage>. As for documentation js-lingui > i18next > React-intl, the documentation of the latter were nothing but a list of the internal API. Both i18next and react-into require you to supply your own extraction scripts to manage the messages, however, there are community solutions for react-intl.


Extraction and coverage checking

Js-lingui winds this one, because the extraction and coverage tool comes with the system. It’s easy to use, easy to configure, and builds optimised message files.

React-intl comes with a Babel-macro, but that’s all. You’ll need to rely on external libraries, or write your own Node.js command line tools to parse the output from the macro, or do it by hand.

i18next also provide a tool, but it is as bare bones as that of React-intl, and requires more configuring. Furthermore, there are no third party tools made (that I know of) to sipmlify this.

Switching between languages

I18next provides a function that can be gotten from props within the entire app, because it’s readily supplied by the provider.

React-Intl and Js-lingui assumes you are using some external state handler, like Redux, so you’ll have to manage that yourself. For React-intl I used a component written by someone else, and for Js-lingui I just made a simple wrapper.

Installation and implementing in existing code base

All libraries are quite equal in this regard: they all require a provider, as well as manual wrapping of all the messages. As mentioned elsewhere, i18next require more configuration than the others.

Syntax and broilerplate

Js-lingui has the best syntax our of the box. It’s very declarative and React-isch, it does not clutter the code too much, and it’s quite easy to understand.

I18next was inspired by js-lingui and now also have the Trans-component, but recommends using t(). It’s simple, it’s quite easy to pass down values, and it’s easy to type.

React-intl uses the 16-character long FormattedMessage-component, and the message should be supplied as props. It feels weird and when nesting it feels even weirder, as the declarative style with props is mixed with the message file format within a prop.


Js-lingui has the best documentation, hands down. It’s pedagogically written and covers many use cases, especially react. It does also provide an extensive guide on how to actually format plurals. I did not even need to find any tutorials, because the documentation was easy enough to follow.

I18next and the react bindings have documentation, but it feels unpolished and sloppy. It’s not always clear where to find what you need, and for some reason (probably due to CSS), on many pages you are greeted with a huge picture of the authors face. I had to rely om a couple of tutorials, and I still am not sure I understand the configuration files clearly.

React-intl has the worst documentation of the three, with is nothing more than a list of the available components and their props. I had to rely on a couple of tutorials, and some Google fu.


React-intl has long been seen as the standard choice for internationalisation of React apps. I must admit, that I cannot really understand why as I find its syntax overly verbose. It is built on the top of the format.js library. Both are Yahoo projects. It’s worth to mention that the lead developer of React-intl has left Yahoo and there are several people worried about its future.

i18next is maintained by the community, but is backed a little by the company locize, which services it promotes.

Js-lingui is a love child of someone who found the above libraries lacking, and made one he himself would like to use. While it’s not as old and popular as the others, the documentation is better written and everything, down to the internal structure, is explained in detail. The library is in active development and the author, as well as contributors, answer issues on Github.


General considerations:

How well does it fit into our current development workflow?

All of the libraries would fit equally well (and be equally annoying to implement). However, closing i18next would require a considerate amount of time fixing a solution for extracting messages.

How will the translations be handled?

The translations, as well as their compiled forms in the case of js-lingui, should preferably be in source control. Since we’re currently only going to support English and Swedish, the translations can be handle as any other issue and merged into the code.

How will this affect the deployment pipeline?

Unless we opt to dynamically import the message translations, which would be unnecessary as we only have two languages to support, there should not be any problems with the pipeline as the necessary files are merely static .js or .json files.

L10n and i18n specific considerations:

Message as key, or unique id?

In the case of React-intl unique id keys are mandatory, the other two can use the messages themselves as keys. If we chose to go the route of unique ids as keys, we will need a key for every message, and some kind of system as to what they should be called. That would take considerable time to come up with, and probably require meetings.

However, keys have the pro of making the messages independent of the original or default language content. If the default language first used as message keys is changed, there will either be a mismatch, or an older version of the message will be used as the key.

Handling of plurals and numbers?

Everyone who does anything to the code will have to learn how the chosen library handles things like plurals, days, dates and numbers. This is not hard, but does require some effort.

Will non ui-text need to be translated?

As far as I know, there is no need to translate other text string than those presented within the Apps components. If there is, however, it’s important to note that React-intl is not able to do this.

How should the locale be set?

The locale can be set in different ways:

This should probably be left to the customer to decide, but it’s possible to do with all the libraries.

Unless it’s necessary, the easiest solution is to save the language choice, in case it is made with a switch, as a cookie in the users browser. This will mean the back end won’t have to implement another field in the user database, and that the front end will not have to make Ajax requests. It is, however, entirely possible to implement should the customer want so.

In case of more languages being added

It would be preferable to know whether it is planned to add more languages, as this could change the implementation from the start, thus saving time in the future.