Norbert Suski

Senior Frontend Developer

May 25, 2020 in Development

I’ll start telling you about myself from my roots. Before I became a programmer, my whole world was filming, photography, and making music. Happily, this part of me is still there. Oh, I almost forgot — basketball! I love both playing basketball and going to games...

How to translate React application with react-i18next - part 2

In one of my previous posts, I briefly described how to translate React application with react-i18next package. Now, I want to show you how you can detect the language and give user the possibility of changing it.

You can go through the first post and create a simple web application or check my GitHub repository at the end of the article. Anyway, I used the exact code examples as in the above-mentioned article. So beware — I won’t explain the examples here! : )

Preparation

To make things happen we need one additional package - i18next-browser-languageDetector. Let's install it with command: 

npm install i18next-browser-languagedetector

And that's it for the preparation point. This package will allow us to detect the language based on a browser.

Detecting language

Now, we should wire it up with our application in i18n.js file. The whole file will look like this:

import i18n from 'i18next';
import { initReactI18next } from 'react-i18next';
import LanguageDetector from 'i18next-browser-languagedetector';

const resources = {
  en: {
    translation: {
      "translated-paragraph": "We are going to translate this paragraph - how will it be in Polish?"
    }
  },
  pl: {
    translation: {
      "translated-paragraph": "Przetlumaczymy ten paragraf - jak to bedzie po Polsku?"
    }
  }
};

i18n
  .use(initReactI18next)
  .use(LanguageDetector)
  .init({
    resources,
    fallbackLng: 'en'
  });

export default i18n;

As you can see, we passed the LanguageDetector object to use function of i18next. But this is not enough — we need to define an object with options for detection mechanism. There is a bunch of properties we can utilize, but we will focus on the basic stuff. Let's create the object and pass it to i18n:

const DETECTION_OPTIONS = {
  order: ['navigator']
};

i18n
  .use(LanguageDetector)
  .use(initReactI18next)
  .init({
    detection: DETECTION_OPTIONS,
    resources,
    fallbackLng: 'en'
  });

This is the easiest setup we can create. What happened here? We passed the DETECTION_OPTIONS object to detection property which is used by LanguageDetector. Detection options contain order property in which we can define the order used by LanguageDetector to find out user's language. We used the navigator option so that LanguageDetector can grab the language of a user's browser. You can try this out by changing the language of your browser (or by installing Locale Switcher plugin in Chrome).

You may ask what will happen if there appear 'pl-PL' or 'en-GB’, etc. as a detected user's language? Well, If we won't define translations for 'en-GB',  then an unspecified 'en' will get selected automatically.

Changing language

Ok, it's time to implement the language switch functionality. We simply put 'English' and 'Polish' texts in the header with the possibility of clicking them. We need to import i18n from i18next package, as well, because there’s a function called changeLanguage which accepts language code as the first argument. And that's it — now, when you click on 'English' the language should change to English, and so on.

import React from 'react';
import i18n from 'i18next';

const Header = ()=> {
  return <header>
    <span onClick={()=> i18n.changeLanguage('en')}>English</span>
    <span onClick={()=> i18n.changeLanguage('pl')}>Polish</span>
  </header>;
}

export default Header;

But wait — if we change the language and refresh the page, the language will reset to default one. Why? Because we don’t save the set language anywhere. We need to handle it, as well.

Caching language settings

We already know what detection options are and how we can utilize them. Now, we will use them to cache user language. Here’s a little change that we need to make first:

const DETECTION_OPTIONS = {
  order: ['localStorage', 'navigator'],
  caches: ['localStorage']
};

A new option has appeared there! In this piece of code, we use localStorage in order property and we also added a new option: caches. Here, we can define where to store user language if it changes. Let's take a look on the developer tools in a browser:

As you can see, the current language is cached in the browser's local storage. What happened here? The first step of the application was trying to detect user language from localStorage, but it wasn’t there (on the first run). After that the app took the language from navigator (browser language). And at the end, it cached the language to local storage. Every next run of the application will take the language from browser's local storage. Now, when you click on the English language it will also be saved in local storage and after refreshing it, it will still be there.

Let's take a quick look at the other order and caches options. Caches contain a smaller list of options:

  • localStorage - which we’ve used already
  • cookie - this option saves the language to cookie

The list of options available for order is much bigger:

  • localStorage - already explained
  • navigator - also already explained
  • cookie - use when language is cached to cookie
  • htmlTag - it takes language from lang attribute in html tag (<html lang="language">)
  • querystring - reads language from the query string in URL (?lng=language)
  • path - is useful when we put language into url like: site.com/language/something
  • subdomain - when we want to use language as a subdomain like: language.site.com

Summary

The localization topic is quite a big thing and I know that we’ve just scratched the surface of the issue. That's why I really want to encourage you to read the documentation thoroughly and try out different options to adjust it to your needs. Below, you can find a couple of useful links:

GitHub repo: https://github.com/norbertsuski/translations-app

Back to top