In this article, we will take a look at the different libraries we have at disposal for React i18n. We will also understand the pros and cons for each option in terms of flexibility, scalability and most of all, developer productivity as its very important to have a consistent view of the app.
Understanding the pros and cons of each library takes time and effort. The main reason is that almost every language has different rules and conventions and adapting to them in the scope of those libraries, is tricky to do it right.
At the time of this writing, I’m using just the latest versions of React v16.11.0 and React Router v5.1.2. I’ve also added the code examples in this GitHub repo.
The Base Project
Let’s start by layering a base project that we would like to localize. It would be a typical, unopinionated React project with a minimal boilerplate, useful for starting out fresh. Create a new app using Create React App and update the App.js with the following content:
And the Home.css component as:
This library is one of the most popular solutions for i18n in React and it’s now part of Formatjs. Offered by Yahoo is bundled with common locale data like dates, currencies, numbers, and support for over 150+ languages. It builds upon the concepts of the ECMAScript’s ECMAScript’s Internationalization API namespace.
In order to use it, we need to configure a few things first.
First we need to install it:
yarn add react-intl
Then on the root of the application just before we render the initial component, we need to add the following bootstrapping code:
Notice that the i18nConfig contains all the specific language translations for the current locale. We could have loaded this config before the application starts using a JSON Webpack loader or an Ajax call.
When we have loaded our supported locale and config messages, then we only need to wrap the application with the that will apply the i18n context available for our internal React Components:
Finally, we are ready to provide our translated components. We need to convert our existing text in the Home component into a series of FormattedMessage components:
Then, we need to update our translations to match the keys for each one of the messages:
Among other things, React-intl offers some extra components:
- FormattedDate: Formats locale-specific dates.
- ForrmattedTime: Formats locale-specific times.
- FormattedRelative: Formats locale-specific relative durations.
- FormattedNumber: Formats locale-specific numbers and decimals.
- FormattedPlural: Formats locale-specific plurals and quantities.
There is also support for React Hooks via the useIntl hook. To use it in our Functional Components, instead of importing the above components, we just call the hook and it will return the imperative formatting API as an object for us:
React-intl offers a good overall package for internationalizing your React Application. However, it is not without its disadvantages. You cannot use it for non-react components as it requires the top level component to inject the context to the children. We will see how the next library helps with providing a holistic solution to this problem.
react-intl-universal is a React internationalization package developed by Alibaba Group. It builds on top of React-intl by allowing non-React components use the library by providing a singleton object that can be used to load the current locale. Let’s see how we can use this library in our project.
Install it first:
yarn add react-intl-universal
Using the i18nConfig we need to load the translations and pass them through the intl.init method call:
Once we update the state we can render the App component:
Now the API for accessing those translations is simple:
It can also handle locale-specific messages for Times, Dates, Decimals and Plurals.
LinguiJS is considered a newcomer in this list, offering an impressive array of powerful features for i18n. It’s clean, simple and with low overhead. Not to mention it works with React too!
Let’s see an example usage. First we need to install a bunch of libraries:
yarn add --dev @lingui/cli @lingui/macro @babel/core babel-core@bridge
yarn add @lingui/react
Next we need to add a configuration file for the CLI tool that will extract and compile the messages. Create the following file with this config:
We specify that we need a JSON format (using minimal) for our message formats and they will be saved in the src/locales folder.
Now let’s create the Home.js Component:
Then we need to extract and compile the messages that we are going to translate:
Note that, when you run the app the first time you will see only the English translations and not the Greek. That’s because the Greek translations are missing. We will have to add them to the src/locales/el/messages.json before we run the compile command:
Once we’ve completed those step’s, we only have to load those messages into the I18nProvider component:
Now if we run the app we will see the same screen translated as before. LinguiJS offers a lot of cool features so I urge you to consider it for your next project.
Having explored those three powerful libraries for localization, let’s see one more option that competes equally with the latter.
i18next aims to target high as it promises to give you a complete solution to localize your product from web to mobile and desktop. i18next is a plugin-based framework and provides you with plugins to:
- detect the user language
- load the translations
- optionally cache the translations
- extension, by using post-processing – e.g. to enable sprintf support.
It works well with small projects and scales when the project has many translation files to load.
Let’s see how we can use it in our React App.
Install it first:
yarn add i18next react-i18next i18next-browser-languagedetector
Next, we need to create a file that will load our i18next configuration and any plugins we need to use. Let’s create a file named i18n.js and put our translations there:
We needed to put some fallback translations so that we have at least English displayed. Also, we used a LanguageDetector plugin that will use a variety of method to detect the clients supported languages.
Next, we need to update our root component to use this i18n config inside the index.js:
So now we are ready to go. Let’s see how we can use it in our main Home.js component:
We need to wrap our component with the withTranslation HOC passing our namespace. Then we have access to our translations. The Trans component enables you to nest any react content to be translated as one string. Supports both plural and interpolation.
We also added a little language switcher there. If you try to use it you may notice that the switch happens almost instantly and it does not reload the page.
When it comes to internationalizing your React apps, it’s important to provide a holistic and future-proof solution that will not inhibit your development efforts. At the end of the day, it’s not just updating some JSON files. Fortunately, Phrase can make your life as a developer easier! To learn more about Phrase, please refer to the Getting Started guide.
If you found these libraries helpful, stay tuned on this blog for more articles related to this subject, because we are not there yet. I18n has a lot of factors you need to consider and great care has to be given in order to provide the best locale experience for your global community of users.