React-Intl v2

This blog post will be about how to set up the new and improved react-intl v2.


Historically it has been a pain point when talking about internationalize your web applications. For me the most annoying part has been that first you have to define your translation keys in the code base, after this you have to navigate to some assets directory and traverse a (big/huge) file in json/key-value format and add a value to the defined key.

If one forget to add any of the aforementioned keys and/or values in the correct places, depending on your implementation of i18n-handling anything can happen. In best cases some kind of fallback kicks in and at least present the key taken from the code.
With react-intl 1.x your code crashes on the client with a (helpful) message about you have forgotten to add the value in the correct language json file.

Another problematic thing about react-intl 1.x is unit-testing. This is due to the fact that the library is based on a mixin and react context. This means that in unit-testing you have to supply the messages for the child components of the tested one. All of this can be a real hassle.

React-intl 2 – The new and fancy way of doing translations

react-intl v2 lets you define all the translations inline with the rest of the code, with a key, a description of how the translation is used and also a fallback-translation to use while developing.

Once it is time to get all these messages translated, you only have to do a webpack build with the babel-plugin react-intl plugin. This will extract all the defined messages from the code base into JSON files. These files are then sent to your translators and they translate all of these messages and the translations is put into a flat JSON hash and this is then loaded into your code and you have a i18n enabled app. So enough with theory!

Lets get going

All of the code is available in this github-repo:


First of all we need to set up webpack to be able to handle the extraction of our future messages and also we want to code with ES2015 of course. Lets install react, webpack and some dependencies:

So with everything installed lets drop a fairly out of the box webpack.config.js into the mix.

So now we got webpack up and going, but we will need to create one more file do be able to use the message-extraction in the build-step which I mentioned earlier.

So create a file called .babelrc and add the following content.

This tells webpack to use the react-intl plugin. The options which we pass in tells the plugin in which folder we want the extracted messages and that we require descriptions for all messages, otherwise the build will fail.

Now we got all the config set up.

Coding time

First of all we need to create the ./src/app.jsx which we told webpack was our entry point.

So in this file we import and add the swedish locale to react-intl so that stuff like FormattedNumber and other locale specific functionality works. React-intl comes bundled with a lot [citation needed] of locales, just import and add the ones you need.

The IntlProvider is the react component wich actually wires up the translation functionality to our app. For now we just tell it that we would like to use Swedish locale and language.
Inside of IntlProvider we can now add our real component(s) with business-logic.
Lastly we render our app to the DOM at the correct elementNode.

Now it’s time to take a look at the actual creation of translated components. Create a file called ./components/translated-component.jsx.

This file is using two different ways of defining translation messages. The first one is by using the defineMessages function which creates a translations-object. From this object we can then get a specific translation (translation.predefinedTranslation) and spread it to the to the FormattedMessage.

The FormattedMessage is a react component which will do the actual replacement of translations at runtime.

The other way to define a translation is to do i inline of the FormattedMessage (or one of the other components provided by react-intl).

Notice that both ways accept three attributes, id, defaultMessage and description.

Finally we have some working code, fire it up with

and navigate to localhost:8080 in a browser. It will look something like:


and if you open the console it will say:

This means that we are not yet providing any translations for the keys in Swedish, and therefore fall back to the defaultMessage. Time to fix this.

First we do a build to extract all the translated messages:

When this is done, lets take a look in the ./extracted-messages/ folder.
Here we now have a file called translated-component.json and the content of this file is

This is the file which we send to our translators, from it they know which keys to translate and also they are given a context of how/where the translation will be used.

The outcome from those translations will be put in a flat json-file with the following structure:

This we put in the file ./l10n/sv-SE.json. And finally we update our ./src/app.jsx:

Notice here that we are importing the translations (row 6) and attach those to the IntlProvider as the messages-prop (row 13).

Now we can fire this up again with npm run start:dev and see the final result:


We have now created a translated app powered by react-intl v2!
As mentioned before the code is available in the following github-repo:

Well I guess that was all for this time. I hope you liked it.

Hello World!

Obviously it is required of me to name this first post Hello world, due to the sole fact that the entire blog will be about (frontend) development. The plan is to roll out handy tips of how to do certain stuff, see it as documentation which will be helpful for at least myself, and therefore hopefully to someone else aswell.

If I were to be asked a direct question regarding which topics I will visit with my future posts, I would answer something of the following:

This blogs content will be filled with tips related to how to build an isomorphic react app. Also, it will not be an introductory course of react or anything similar.

With this I mean that I will not explain every single detail but rather assume that the reader of this blog does have some basic knowledge of frontend development. And the knowledge will not ramp up from basics in the early posts to more advanced topics later on, there will just be random slices of the Whole sort of general mish mash.