DEV Community

CHIMDI
CHIMDI

Posted on

Creating Multilingual React Apps with i18n: A Step-by-Step Guide to Internationalisation

With over 20 languages having more than 80 million speakers, if you are building software or a website for the global market and want it to be widely accepted, giving the users an opportunity to use the product in their native language would definitely lead to a better user experience. I18next is an internationalisation framework that can help with internationalising/localising your app.

What is internationalisation?

Internationalisation is a way of preparing and writing your apps so that they can be adapted to support certain local languages, cultures and regions. It enables localisation which is the adaptation of a product, application or document content to meet the language, cultural and other requirements of a specific target market (a locale). (https://www.w3.org/International/questions/qa-i18n)

In this article, we will go over how to perform internationalisation in our react app using the i18next framework.
I18next is an internationalisation framework written in JavaScript. It comes with everything you need to localise your web, desktop or mobile product such as user language detection, loading and caching translations, and file conversion etc More features can be found in their documentation. (https://www.i18next.com/)

Now let us proceed to use i18n in our react application.

Step1 - Initialise the Project

First let us create our React project using Vite. Open your terminal and run the following command to create a new react project using Vite.

yarn create vite my-i18n-app --template react
Enter fullscreen mode Exit fullscreen mode

Change your current directory to that of the new project using

cd my-i18n-app
Enter fullscreen mode Exit fullscreen mode

Proceed to open the newly created project in any code editor of your choice.

Step2 - Install dependencies

Add i18next to the project using the command below

yarn add i18next react-i18next

Enter fullscreen mode Exit fullscreen mode

Start the react project to make sure that everything is working fine

yarn run dev

Enter fullscreen mode Exit fullscreen mode

Initial app
You should have the above when you navigate to your projects url.

Step3 - Change App content

Lets go ahead and replace the entire app.jsx with the following code:

import './App.css'

function App() {
  return (
    <div className="App">
      <h1>Welcome to my i18n project</h1>
      <h1>How is your day going?</h1>

    </div>
  )
}

export default App
Enter fullscreen mode Exit fullscreen mode

Now our project should look like this:

Initial project look

Step4 - Add Translations

In order to maintain organisation in our code, let’s create translation files for each language in a translation folder. Our project will now have the following structure:

Folder structure

Now, add language jsons to the translation files.
For English.json:

{
    "line1":"Welcome to my i18n project",
    "line2":"How is your day going?"
}

Enter fullscreen mode Exit fullscreen mode

For Italian.json:

{
    "line1":"Benvenuti nel mio progetto i18n",
    "line2":"Come sta andando la tua giornata?"
}
Enter fullscreen mode Exit fullscreen mode

Step4 - Add i18next

Now let’s import i18next into our project and configure it.
In the root of the project, create an i18next.jsx file and write the following code:

import i18next from "i18next";
import { initReactI18next } from "react-i18next";

//Import all translation files
import English from "./Translation/English.json";
import Italian from "./Translation/Italian.json";

const resources = {
    en: {
        translation: English,
    },
    it: {
        translation: Italian,
    },
}

i18next.use(initReactI18next)
.init({
  resources,
  lng:"en", //default language
});

export default i18next;
Enter fullscreen mode Exit fullscreen mode

In the code above, we are setting up and initialising i18n in our project. We provide the sources of the translations and also set english as the default language. Note that the ISO 639–1 standard language codes should be used when identifying/choosing languages.

Next, we import this i18n.jsx file inside our main.jsx file to connect it with our react app, It should look like this now:

import React from 'react'
import ReactDOM from 'react-dom/client'
import App from './App'
import './index.css'

import './i18n'

ReactDOM.createRoot(document.getElementById('root')).render(
  <React.StrictMode>
    <App />
  </React.StrictMode>,
)

Enter fullscreen mode Exit fullscreen mode

Step5 - Create context for languages

Next step is to create a language context that we will use to provide our i18n functionality all through our app.

Create a new folder and a languageContext.jsx file in it, put the following code in the file:

import React, {
  createContext,
  useContext,
} from "react";
import { useTranslation } from "react-i18next";


export const LanguageContext = createContext(undefined);

export const LanguageContextProvider = ({ children }) => {
  const languages = {
    en: { nativeName: "English" },
    It: { nativeName: “Italian” },
  };
  const { t, i18n } = useTranslation();

  const onClickLanguageChange = (e) => {
    const language = e.target.value;
    i18n.changeLanguage(language); //change the language
  };

  return (
    <LanguageContext.Provider
      value={{ t, i18n, onClickLanguageChange, languages }}
    >
      {children}
    </LanguageContext.Provider>
  );
};

export const useLanguageContext = () => useContext(LanguageContext);

Enter fullscreen mode Exit fullscreen mode

Let’s go through the code above

import React, {
  createContext,
  useContext,
} from "react";
import { useTranslation } from "react-i18next";
Enter fullscreen mode Exit fullscreen mode

Here we import the necessary dependencies, createContext and useContext are used for context while the useTranslation is a hook from react-18next which provides us with the t function used to translate text in our app and the i8n instance that will be used to change language.

export const LanguageContext = createContext(undefined);

Enter fullscreen mode Exit fullscreen mode

This line creates the language context

const languages = {
    en: { nativeName: "English" },
    It: { nativeName: “Italian” },
  };
Enter fullscreen mode Exit fullscreen mode

Here we are creating a languages object containing our supported languages, it will be used in our languageSelect component.

const { t, i18n } = useTranslation();

Enter fullscreen mode Exit fullscreen mode

Extracting t function and i18n instance with object destructuring

const onClickLanguageChange = (e) => {
    const language = e.target.value;
    i18n.changeLanguage(language); //change the language
  };
Enter fullscreen mode Exit fullscreen mode

We create an Event handler to change the current language.

return (
    <LanguageContext.Provider
      value={{ t, i18n, onClickLanguageChange, languages }}
    >
      {children}
    </LanguageContext.Provider>)
Enter fullscreen mode Exit fullscreen mode

Returning the language context provider and passing the necessary values

Now, go ahead and wrap the entire app with the language context provider in main.jsx

import React from "react";
import ReactDOM from "react-dom/client";
import App from "./App";
import "./index.css";
import { LanguageContextProvider } from "./context/LanguageContext";

import "./i18n";

ReactDOM.createRoot(document.getElementById("root")).render(
  <React.StrictMode>
    <LanguageContextProvider>
      <App />
    </LanguageContextProvider>
  </React.StrictMode>
);
Enter fullscreen mode Exit fullscreen mode

Let’s check that this is working by using it in the app.jsx file

import "./App.css";

import { useLanguageContext } from "./context/LanguageContext";
function App() {
  const { t } = useLanguageContext();
  return (
    <div className="App">
      <h1>{t("line1")}</h1>
      <h1>{t("line2")}</h1>
    </div>
  );
}

export default App;
Enter fullscreen mode Exit fullscreen mode

If you followed all the steps, there should be no change in the UI and this means that everything is working perfectly.

Finally, let us create a LanguageSelect component that we can use to switch between languages.

Create a LanguageSelect.jsx file and add the following code to it.

import { useLanguageContext } from "./context/LanguageContext";
const LanguageSelect = () => {
  const { languages, onClickLanguageChange } = useLanguageContext();
  return (
    <select
      style={{
        width: 200,
        position: "absolute",
        top: 10,
        left: 10,
        height: "40px",
      }}
      onChange={onClickLanguageChange}
    >
      {Object.keys(languages).map((lng) => (
        <option key={languages[lng].nativeName} value={lng}>
          {languages[lng].nativeName}
        </option>
      ))}
    </select>
  );
};

export default LanguageSelect;
Enter fullscreen mode Exit fullscreen mode

In the code above we are getting the languages from the language context and mapping over them to create a select component that will trigger the onClickLanguageChange when its current value is changed.

Go ahead and include the LanguageSelect component in our main.js file so it’s available throughout our app

import React from "react";
import ReactDOM from "react-dom/client";
import App from "./App";
import "./index.css";
import { LanguageContextProvider } from "./context/LanguageContext";

import "./i18n";
import LanguageSelect from "./LanguageSelect";

ReactDOM.createRoot(document.getElementById("root")).render(
  <React.StrictMode>
    <LanguageContextProvider>
      <LanguageSelect/>
      <App />
    </LanguageContextProvider>
  </React.StrictMode>
);
Enter fullscreen mode Exit fullscreen mode

Now our project should look like this

Final Application

There you have it! You have successfully added internationalisation (i18n) functionality to your React app using i18next. Your app is now able to display text in different languages based on the user's preference.

By following the steps outlined in this tutorial, you have learned how to:

  1. Install and configure i18next in a React app
  2. Create translation files for multiple languages
  3. Use the useTranslation hook to translate text in your app
  4. Create a language context to provide i18n functionality throughout your app
  5. Use the LanguageContextProvider to wrap your app with the language context
  6. Create a LanguageSelect component to allow users to switch between languages

Remember that i18n is an ongoing process, and there may be more text that needs to be translated as your app grows. With i18next, you can easily add new translations and update existing ones as needed.

Thanks for following along, and happy internationalisation!

Top comments (0)