React. Adding translations with i18next
The i18next library is probably the best option available to add translations to a website developed with ReactReact. Adding translations with i18next

In this article I want to tell you the basic elements of the i18next library, which has a very simple integration with the ReactJS library which will allow us to add translations to our texts in a very very simple way. It also has its own hooks, something that comes as an addition now that functional components are the trend in development with this library.
In addition, this same library can be used with both React and React Native, which is a tremendous advantage since we can recycle the logic associated with it if we are forced to develop for web and mobile platforms.
And yes, although we will not see it in this article, i18next is 100% compatible with server side rendering and frameworks like NextJS.
So without lingering any longer, let’s see the main features it offers us!
🧰 Installation and configuration
The first thing we will do is install i18next using npm / yarn:
yarn add react-i18next
Then it will be necessary to configure the library to be able to use it within our components. This is recommended to do in a separate file (for that of separating the logic) that we will import in the index.js
file of our project.
In my case, I usually create this configuration file inside the config
folder, as you can see on line 4 of the following piece of code:

The initial configuration of the library can be as simple as the one you see below:

We will import the i18next
library and configure it as follows:
- Through the
use
method we will configure the plugin that allows connecting the library with React. - In the
use
method we will specify by means of an object the translations of our application, leaving them grouped by language. In our case, we have two languages available: “en” and “es” and a translation that we will access through the title identifier / key. - In addition, in the
init
method we will also set the current language as well as the default language to be used when a translation is not available in the selected language.
With this we will already have the library configured and ready to work as we will see below.
Using the current language of the browser
If we want the language of our application to be that of the browser, we can use the navigator
object of the browser to obtain it and thus access the language configured by the user (lines 6 and 7 of the following piece of code):

If we want to avoid this check, the library has the i18next-browser-languagedetector plugin that will automatically set the language of the application, also remembering this selection in the local storage of the browser for future visits (something that is very useful if the user later change language). The plugin can be installed using yarn:
yarn add i18next-browser-languagedetector
And where we are configuring the library import it and pass it to the i18next
library through the use
method:
...
import LanguageDetector from 'i18next-browser-languagedetector';i18n.use(LanguageDetector).
...
Muy muy fácil como véis.
🔁 Translating through the i18next library
The use of this library is very simple, as I commented at the beginning of the article. Also, thanks to the fact that it has full support for hooks, starting to translate texts is practically immediate. For example, suppose we want to translate the title of our page. A code similar to the following will suffice for this:

In line 6 we will use the hook useTranslation
to obtain the function t which allows us to translate texts specifying the key of that translation. In our case, since we are typing t('title')
what we will get will be “Welcome to React” (remember that in the previous step we chose Spanish as the initial language).
Nesting translations
In the definition of translations we can also nest the keys so that we can group the translations associated with a certain view or concept of our application:

If we use this technique, when we use the function t
, we will access the translation for “title” as follows:
t('welcome.title')
🔡 Interpolation
Of course we can not only specify plain texts in our translations, but we can also add variables to them that the library will later interpolate by means of the function t
from the hook useTranslation
.
For example, suppose we want to add the person’s name to the initial greeting. In our configuration file we will specify the variable surrounding it in double brackets as it happens on lines 12 and 17 of the following code:

And then, when we are going to use the function t
, we will pass the value of name
as follows:

🔛 Access and modify the current language
The hook useTranslation
not only provides us with the translation function t
belonging to the i18next library, but it also gives us access to the i18n
object.
const {t, i18n} = useTranslation();
This object has two basic characteristics:
- Its
language
property, which allows us to obtain the current language (i18n.language
) - Its
changeLanguage
method that allows us to modify the current language (that is, it is the method that we will use for the typical language selector). And yes, this will cause a rerender of the interface so that the moment we invoke it we will see how the language of all the texts that are being printed by means of thet
function is modified.
🗂 Moving translations to files
This is all very well, but as the number of texts to translate grows, it is not sustainable to add them to the resources
property of the object that we pass to the init
method. First for readability (imagine the size it could reach) and second for optimization, since probably many of the translations that we would initially be loading we would not use and yet they would be taking up space.
To solve this, the i18next library allows us to separate the translations into different json files which are considered “namespaces”.
The first thing we will do is install the i18next http backend library:
yarn add i18next-http-backend
This library allows us to access our translation files transparently through the Fetch API so that:
- Initially, only those files that we request in the first render will be loaded.
- As the user navigates through the application, the library will request them transparently.
Next, we will modify the file where the i18next library configuration was located to use this plugin through the use
method (line 10):

We only have three more steps left:
- Add the translation files into the
public
folder. - Import the namespaces defined by the translation files into the
useTransalation
hook. - Add the
<Suspense>
component for asynchronous loading of these files.
We will see each step.
Translation files
In the public
folder of the project we will create a folder called locales
where there will be as many folders as there are languages in our application. In our case, within the locales
the folders es
and en
will be found. Inside it, we will create JSON files that will house the translations of our application (remember that we can nest the translations in the same way that we did in the resources
object that we passed to the init
method) and whose name will represent the namespace that we will need to specify so that the i18next plugin -http-backend can load it.
Continuing with our example, we will have a file public/locales/es/welcome.json
:
{
"title": "Bienvenido {{ name }}"
}
and other file public/locales/en/welcome.json
:
{
"title": "Welcome {{ name }}"
}
Passing namespaces to useTranslation
And now, instead of using the hook useTranslation
without arguments, what we will do is invoke it as follows:

That is, we will pass an array with all the namespaces that we want to load, which will automagically make the plugin i18next-http-backend make the appropriate calls to obtain those files, load the translations into the library and allow us to separate the texts of our translations to optimize the performance of the application.
Suspense
Finally, and since in order for us to use the hook useTranslation
it is necessary that the translations are loaded (which we are now doing asynchronously thanks to the i18next http backend plugin) we will have to wrap our application with the <Suspense>
component to show the status “ loading “while json files with translations are retrieved:

And now yes, we already have our application fully working with translations.
Repository
I leave you a link to the repository that I have prepared on this article so that you can see in operation what I have commented on in this article:
Conclusions
This article is just an introduction to the i18next library and its adaptation for React. However, it has numerous features in addition to those I have mentioned, so I recommend that you visit its documentation (which unfortunately is not as well structured as it should be, which is its weakest point) to discover everything it can offer you.
For me it is the best library to incorporate translations into applications due to its simplicity when using it and the options it offers.
Do you want to read more articles like this?
If you liked this article I encourage you to subscribe to the newsletter that I send every Sunday with similar publications to this and more recommended content: 👇👇👇