Nuno Grilo Pinheiro
Software Localization Tutorials
4 min readMay 16, 2016

--

I18N For React

Unless you are in an English speaking market and never expected to have non-english speaking customers, you have at least once stumbled on the problem of page internationalization, at least the most common case, page translation.

As a developer of University software in Portugal, i18n is a main requirement of the applications. All the applications obviously need to be in Portuguese since some older users do not know how to speak English. Due to the high popularity of student exchange programmes, the application also needs to be in English, the “universal” language.

Making my first full client side React application, I thought it would be rewarding for me to add support for i18n.

My First Approach

In my first approach I tried to use a library made by a friend. This library works based on data-* attributes which are added to the HTML elements. The value given to these attributes defines the message keys to be injected on the elements. Through a simple method call the whole page can be re-translated without a full page refresh. All seemed perfect and I really liked its simplicity, but it did not fit React.

Since React is component based, and I happen to use mostly third party components, such as react-mdl and react-autocomplete, I do not have access to most of the inner html components. This means that I cannot (easily) add the data attributes to these elements and I cannot use this tool to perform my localization.

What Exists on the React Community

Since my first approach was not going to work I went to Google some solutions and ended up Yahooing this solution: https://github.com/yahoo/react-intl

My first big problem was finding how to dynamically translate the application. It seems the framework is not very opinionated regarding dynamic updates, so every person needs to create his own solution, which in my point should be given out of the box as part of the tool.

To perform the translation, this framework offers components which receive a key and display the translated value. I then realized that I was about to stumble on the same problem as in my first approach. Most of the out of the box components that I use have messages defined as properties. For example, the TextField in react-mdl receives the label as a property, not as an inner component. This means that once more I would not be able to translate some parts of the application.

React is all about components, however, this made me realize that components will hardly be a solution for i18n.

The Old Solution and the missing problem

Since I will need to translate keys before passing them as properties to other components, I decided to use the old approach: call an i18n function which does this work. Lots of solutions exist out there, for example i18next and Polyglot. I decided to go with Polyglot.

But this still kept me with one problem: how to dynamically update the views after a locale change request?

The easiest solution would be to simply change the key property of my root Component, leading to a whole re-render of the page. This solution is however inefficient, when we change the key, react will consider the component as a different component, and the DOM will need to be re-rendered, skipping the awesome optimizations made by react on component change. Calling forceUpdate on the root component would probably skip the inner components since their states were not changed.

Mixins for the rescue

My solution was to create a mixin which I can apply to my i18n-aware components. By simply adding this mixin to all the components which perform i18n, a force update will be called over the components.

Under the hood what this mixin does is to listen to a redux store. To ignite a page translation we simply call the dispatch method over this store with the new locale.

This solution, in collaboration with the i18n method calls through Polyglot, ended up solving all the problems I had in an efficient way. You can check the code and API on GitHub.

Extra features

If you are building a huge application and/or are distributing your application in a lot of languages, you may want to avoid enforcing all your language contents to all your users, avoiding some precious network consuming.

To fill this need I added locale fetching out of the box. When a user changes the language, a GET request will be made to fetch a file with the name “<path>/<locale>.json”. This path must be configured by the library user.

I also added a server side method to read the JSON. You should use this method to inject the current locale data on the page. This way, your first page will already have the localized messages it requires, avoiding a GET request until the user explicitly changes the locale.

How they do it where you from?

This was my solution for the i18n problem, but I am pretty sure other people already fixed this problem before. Have you? Please leave a comment below with your solution, and if you think this is a good one please recommend it and share it!

--

--