Isn't it great when you visit a website and you find the flag of a country somewhere on the page🚩, a dropdown with languages or a little globe icon? These are symbols typically used to indicate that the website provides its content in more than one language. This concept is known as internationalization or i18n for short. In case you're wondering, the number 18 in the contraction i18n represents the number of letters between the first and last letters, i and n from the original word. That's a fun fact😎 but also, developers are very lazy people.
Internationalization refers to how accessible a digital product is to people from different countries, who speak other languages, or who may have difficulties comprehending content in the default language. In most cases, it is English. Providing tools that allow users to translate the text on a website is another way of improving accessibility, boosting worldwide user engagement, and being transparent to people from around the world.
In this article, we'll be walking through how one can setup this translation feature for their website. We'll be going over a React example in this article using JavaScript and the following npm packages: i18next, i18next-browser-languagedetector, i18next-http-backend, and react-i18next. The steps below work for both new websites as well as existing ones allowing you to integrate this into a production environment.
I will be implementing translations for English, Shona, and French because they are: the most spoken language in the world, my mother tongue, and a language I just love the sound of respectively.
Package Installation
To start things off, we need to install the necessary packages using NPM.
npm install i18next i18next-browser-languagedetector i18next-http-backend react-i18next
You need to have Node.js installed on the working machine for the command above to work. There also exist other ways to do this installation such as Yarn.
Configuration
Next, we need to navigate into the src directory of the React application. Most React projects have this folder regardless if it was created with Vite or Create React App. If there exists another folder structure for a React application different to this then ensure that this is done in the same place as the index.js file where the render() method is typically called.
Create a file and call it i18n.js and include the following code:
import i18n from 'i18next';
import { initReactI18next } from 'react-i18next';
import LanguageDetector from 'i18next-browser-languagedetector';
import Backend from 'i18next-http-backend';
i18n
.use(Backend)
.use(LanguageDetector)
.use(initReactI18next)
.init({
debug: true,
fallbackLng: 'en',
});
export default i18n;
What this does is chain i18next with the use function to load additional plugins to i18next. The default of the i18next module is an i18next instance ready to be initialized by calling init. In this case, our default language is English ('en') and it will be used in cases where translations for a different language haven't been specified.
The next thing to do is ensure that this module is available throughout the application by importing it. We can do so in the entry point of the React application which is the index.js file:
import './i18n';
That's all you have to do. You also need to ensure that the path points to the location of the i18n.js file we created.
Adding Translations
The next step is to create JSON files that contain our translations. Inside the public directory where you would typically have the index.html file, manifest.json or favicon.ico, create a folder called locales.
Then, create another folder called en inside the locales folder which should contain a file named translation.json. We need to do this for all the languages we wish to include in our project. So, here is the folder structure:
/**
* public:
* __locales:
* ____en:
* ______translation.json
* ____sh:
* ______translation.json
* ____fr:
* ______translation.json
*/
Here, en stands for English, sh stands for Shona, and fr stands for French. I hope you can see the pattern here. If you wanted to use a different language such as Italian, you would use the respective code which is it.
This is the easy part, we only need to write to these JSON files and the translations will be automatically included in the application. For this to work, the property names need to be consistent. Inside the en/translation.json file, let's add some text since this is the default language of our application.
{
"Hello": "Hello",
"The quick big brown fox jumped over the lazy dog.": "The quick big brown fox jumped over the lazy dog.",
"My name is Tawanda": "My name is Tawanda"
}
Let's do the same for our sh/translation.json:
{
"Hello": "Mhoro",
"The quick big brown fox jumped over the lazy dog.": "Gava zihombe rebrown rakasvetuka pamusoro pembwa ine nungo.",
"My name is Tawanda": "Ini ndinonzi Tawanda"
}
Lastly, let's do the same for romantic French💘 inside the fr/translation.json:
{
"Hello": "Bonjour",
"The quick big brown fox jumped over the lazy dog.": "Le grand renard brun rapide a sauté par-dessus le chien paresseux.",
"My name is Tawanda": "Je m'appelle Tawanda"
}


Sorry, I couldn't resist but what is more French than croissants and the Eiffel Tower😊?
The useTranslation Hook
The react-i18next package includes a very useful hook called useTranslation. Remember, all utility functions in React start with 'use' e.g. useState.
This hook allows us to do many things like translate the text on a web page, dynamically change text, and determine the writing direction of the website. If you are aware of languages such as Arabic, you know that they are written from right to left as opposed to most languages which are left to right like English.
We can make use of this inside our React components. Let's go into our App.js file and import it.
import { useTranslation } from "react-i18next";
function App(){
const { i18n, t } = useTranslation();
document.body.dir = i18n.dir();
const handleLanguageChange = (e) => {
const language = e.target.value;
i18n.changeLanguage(language);
document.body.dir = i18n.dir();
}
return (
<>
<main>
<select
value={i18n.resolvedLanguage}
onChange={handleLanguageChange}
>
<option value="en">English</option>
<option value="sh">Shona</option>
<option value="fr">French</option>
</select>
<div>
<h1>{t("Hello")}</h1>
<p>{t("The quick big brown fox jumped over the lazy dog.")}</p>
<p>{t("My name is Tawanda")}</p>
<p>This text is not translated.</p>
</div>
</main>
</>
)
}
This is a simple use case but I'm sure it is evident how this could scale to accommodate all the text for a much larger website.
The useTranslation allows us to:
- Determine the writing direction by the use of
i18n.dir(). - Instantly change the language using
i18n.changeLanguage(). - Determine the currently activated language with
i18n.resolvedLanguage. - Translate text using the t() function e.g.
t("Hello").
Notice how every time we call the t() function, we pass the property names from the JSON files we created previously. The best part is that the web page is translated immediately with no need to reload the browser window.
By the way, these translations persist within the browser across page refreshes, tab changes, or window closure.
Conclusion
Adding translations to a website is something you ought to do especially if you plan to have a global presence🌍. Some people appreciate the initiative to include their preferred language on your website🙏. This even puts a message across to the user that you are a transparent organization with no cultural biases.
I've found myself involved more and more in building accessible websites and it is something I've become fond of doing in a lot of projects.
Hopefully, this article was helpful and you could always read the official documentation for more details. Thanks for you reading and happy coding 👍!
