Internationalization (i18n) and localization (l10n) in React apps

Internationalization (i18n) and localization (l10n) - what is the difference?

Internationalization isn’t, of course, an issue related only to a web application and this should be the rule and not the exception that all user interfaces are internationalized and localized. However, because of the global nature of the web, these processes are especially important for a web application. Definitions of internationalization vary, but as I intend to discuss this issue in connection with React (which is a web application framework), I’m going to focus on definitions provided by the World Wide Web Consortium. According to W3C:

  • Localization refers to the adaptation of a product, application or document content to meet the language, cultural and other requirements of a specific target market (a locale).
  • Internationalization is the design and development of a product, application or document content that enables easy localization for target audiences that vary in culture, region, or language.

If you've ever wondered:

  • l10n is numeronym that stands for localization, where 10 is the number of letters between l and n,
  • i18n stands for internationalization, where 18 is the number of letters between i and n in the English word.

Internationalized web apps provide a great user experience

Some may think of localization only as a synonym for text translations that are part of the user interface or documentation translations. But localization is much more than that. Users can speak different languages but they also have different cultural expectations. As software creators in the whole process of design and development, we should think not only about how to customize text but also:

  • numeric, date and time formats - there is a subtle difference between MM/DD/YYYY and DD/MM/YYYY notation, which may lead to significant misunderstandings,
  • currency formats -  i.e. in the UK amounts are defined by £50 but in Poland's notation, you will have 50£, in the USA it is natural to separate thousands with commas and decimals with dots, while in Poland you will use spaces and commas accordingly,
  • keyboard usage,
  • collation and sorting,
  • symbols, icons, colors (red and green don't mean the same thing everywhere),
  • text and graphics containing references to objects, actions or ideas which, in a given culture, may be subject to misinterpretation or viewed as insensitive,
  • varying legal requirements.

W3C also points out, that internationalization is about designing and developing in a way that removes barriers to localization or international deployment. Obviously, internalization requires developers to include in their applications predefined localization data like a date and time formats, local calendars, number formats, and numeral systems, sorting and presentation of lists, handling of personal names and forms of address, etc.

Challenges to face:

  • support for bidirectional text, vertical text or other non-Latin typographic features,
  • ensuring that layout can deal with text that is 2-3 times longer than English and also 50% less than English (e.g German or Russian is usually much longer and Japanese and Chinese are often shorter),
  • text on images - replacing text in HTML is easy and can be done automatically, replacing text in graphics is not easy at all, removing texts from graphics may make designer unhappy but in general, should save time,
  • pluralization (in English there only distinguishes between 1 element and 2-∞ elements but in Polish, you need to cover more cases 1 element, 2-4 elementy, 5-20 elementów and again 21-24 elementy and so on).

So, just to summarize: 

Internationalization is the process of preparing an application to support more than one language and data format. Localization is the process of adapting an internationalized application to support a specific region or locale. Internationalization doesn't have to include localization of the application content into another language.

To internationalize your software you need to include design and development practices that allow such a migration to take place easily when such need occurs. 

What is locale?

In computing, a locale is a set of parameters that defines the user's language, country and any special variant preferences that have an effect on the user interface. It refers to the lingual and cultural expectations for a region and it is represented by a code, that usually defines the language or the language-region combination. 

Examples:

  • en for English
  • pl for Polish
  • en-US for English as spoken in the United States
  • en-GB for English as spoken in the United Kingdom
  • nl-BE for Dutch as spoken in Belgium
  • nl-NL for Dutch as spoken in the Netherlands
  • and so on.

Internationalization and React

Type i18n react for search in npm and almost 500 results will be returned. Some of these packages are feature-rich some are for narrow specific needs. Based on our experience while adding internationalization mechanism we usually prefer using react-intl. It is probably the most popular solution for i18n in React. It is a part of Formatjs, which is a modular collection of JavaScript libraries for internationalization, so it is developed with respect for standards and best practices. In our opinion, it is a very powerful library that supports 150+ languages and allows you to use different data notations.

To add a react-intl to your React project install package with:

npm install react-intl

or

yarn add react-intl

Then wrap everything in IntlProvider and you can use several dedicated components to support different aspects of internationalization.

To fulfill its role, the library needs translation objects (in JSON format) which simply pairs text with keys. There are two approaches on how to deal with that in the application:

  • the first one is to have a file with translations in your repository, import it and directly pass it to the configuration,
  • the second one is to fetch translations object from an API and after fetching it from an endpoint pass it to configuration. 

Both approaches are good and choosing which one to use depends on your needs. If your application needs an internet connection and you want to have full control over translations to change some texts in a fly you should use the 2nd approach with API but if the app does not have an internet connection you have to use an approach with a local file.

Configuration 

So, how to start?

import { IntlProvider } from 'react-intl';

import messages_de from './translations/de.json';
import messages_en from './translations/en.json';

const messages = {
'de': messages_de,
'en': messages_en,
};

const i18nConfig = {
defaultLocale: 'de',
messages,
};

// use user’s browser language
// and/or introduce mechanism for user to set up their preferences
const language = navigator.language.split(/[-_]/)[0];

ReactDOM.render(
<IntlProvider
locale={language}
defaultLocale={i18nConfig.defaultLocale}
messages={i18nConfig.messages[language]}
>
<App />
</IntlProvider>,
document.getElementById('root')
);

After setting up this simple configuration, you can use several dedicated React components to display different content based on defined locale. Among all those issues I wrote before, i18n is all about separating elements that can be localized from source code in a way that easily allows to load alternatives based on user preferences (an easy way to change those preferences is also important). These components help you do that:

1. Date Formatting Components

  • <FormattedDate /> - to format dates
  • <FormattedDateParts /> - to provide more customization to FormattedDate by allowing children function to have access to underlying parts of the formatted date and thus to e.g style them in a different way
  • <FormattedTime /> - to format times,
  • <FormattedTimeParts /> - analogous to FormattedDateParts`
  • <FormattedRelativeTime /> - formats a date relative to now; e.g. "3 hours ago",

2. Number Formatting Components

  • <FormattedNumber /> - to format numbers and decimals, with separators and units, widely used to display currencies and percentages; probably one of the most powerful among react-inlt components, that allows to format number to be displayed as e.g. 1,000, $1,000.00, 50,5%, 1,000kB or 1,000 degrees Fahrenheit
  • <FormattedNumberParts /> - more customized way to format numbers, allows children function to have access to underlying parts of the formatted date,
  • <FormattedPlural /> - to format plurals and quantities,that selects a plural category (zero, one, two, few, many, or other) and render the corresponding element,

3. List Formatting Components

  • <FormattedList /> - to format list of elements,

4. String Formatting Components

  • <FormattedMessage /> - recommended for string formatting, because it provides great rich-text formatting features while also being more performant,
  • <FormattedHTMLMessage /> - provided for apps that have legacy external strings which contain HTML,

Why you should use react-intl? 

A nice advantage of react-intl is that you do not have to create translations for your default language. There is an option to set the default message for translations directly as a prop of a component. If in the translations object there will be no necessary key the message will be taken from that option. It is really helpful when internationalization appears as a requirement for an already existing project. Thanks to that you can create new components with the library and keep the old one as they are and migrate it later.

Another good thing about react-intl is that you have two ways to insert text into a component. By default, it is good to use a dedicated react component that will return an HTML <p> tag with text (it also can be changed and you can return any HTML tag with text). Additionally, there is a possibility to get a plain text, which is very helpful if you need to pass translation to another component that requires a string as props.

Last but not least, react-intl is written in TypeScript, so, guess what - it has first-class TS support, oh yeah.

If in the process of design and development you are wondering whether your app will be used by people around the world you should definitely do i18n and you should do it the right way. Remember that is is not only about translation. There are plenty of tools that can be used to make this process developer-friendly and react-intl for React application definitely should be considered as the first choice.

Want to learn more insightful tips about React? Read about our Test-driven development approach! And if you would like to raise your skills within a great JS team - check our job offers

Navigate the changing IT landscape

Some highlighted content that we want to draw attention to to link to our other resources. It usually contains a link .