Adding Multi-Lingual Support in React
Source: Dev.to
To add multi‑language support to a React project we’ll use react‑i18next, which is built on top of i18next.
The library provides components that automatically render translated content when the language changes and can be used with any UI framework (Angular, Vue, etc.).
Documentation:
1. Install the required packages
npm install i18next react-i18next i18next-browser-languagedetector i18next-xhr-backend
2. Create the i18n configuration file
Create a file named i18n.js in the src folder and paste the following code:
// src/i18n.js
import i18n from "i18next";
import LanguageDetector from "i18next-browser-languagedetector";
import Backend from "i18next-xhr-backend";
import { initReactI18next } from "react-i18next";
const fallbackLng = ["en"]; // default language
i18n
.use(Backend) // loads translation files
.use(LanguageDetector) // detects the user language
.use(initReactI18next) // passes i18n instance to react-i18next
.init({
fallbackLng,
detection: {
checkWhitelist: true,
},
debug: false,
interpolation: {
escapeValue: false, // React already escapes values
},
// If you store translations somewhere else, configure the path here:
// backend: {
// loadPath: "/assets/locale/{{lng}}/translation.json",
// },
});
export default i18n;
Note: In
App.js(or the root component) import the configuration so it runs once:
import "./i18n";
3. Folder structure for translation files
public/
└─ locale/
├─ en/
│ └─ translation.json
└─ fr/
└─ translation.json
public/locale/en/translation.json
{
"hello": "Hello",
"cancel": "Cancel",
"continue": "Continue"
}
public/locale/fr/translation.json
{
"hello": "Salut",
"cancel": "Annuler",
"continue": "Continuez"
}
If you prefer a different location (e.g., assets/locale), adjust the backend.loadPath option in i18n.js:
backend: {
loadPath: "/assets/locale/{{lng}}/translation.json",
},
4. Using translations in components
The useTranslation hook gives you:
t– a function to retrieve a translation by its key.i18n– the i18next instance, which provideschangeLanguage().
Example: Language selector component
// src/components/LanguageSelector.tsx
import { Fragment } from "react";
import { Menu, Transition } from "@headlessui/react";
import { GlobeAltIcon } from "@heroicons/react/24/outline";
import { useTranslation } from "react-i18next";
function classNames(...classes: string[]) {
return classes.filter(Boolean).join(" ");
}
const countries = [
{ code: "fr", name: "Français", country_code: "fr" },
{ code: "en", name: "English", country_code: "gb" },
];
export const LanguageSelector = () => {
const { t, i18n } = useTranslation();
return (
<Menu as="div" className="relative inline-block text-left">
{/* ... UI markup ... */}
{countries.map((lng) => (
<Menu.Item key={lng.code}>
{({ active }) => (
<button
className={classNames(
active ? "bg-gray-100" : "",
"block w-full text-left px-4 py-2 text-sm"
)}
onClick={() => i18n.changeLanguage(lng.code)}
>
{/* You could add a flag icon using lng.country_code here */}
{lng.name}
</button>
)}
</Menu.Item>
))}
</Menu>
);
};
Now you can use the t function anywhere in your UI:
import { useTranslation } from "react-i18next";
export const Greeting = () => {
const { t } = useTranslation();
return <h1>{t("hello")}!</h1>;
};
Switching the language via the selector will instantly re‑render all components that use t.
5. Recap
- Install i18next, react‑i18next, and the helper plugins.
- Initialise i18next in
i18n.jsand import it once (e.g., inApp.js). - Store translation files under
public/locale/<lng>/translation.json. - Use
useTranslationto fetch translations (t) and change the language (i18n.changeLanguage).
You now have a fully functional, multi‑language React application! 🚀
Language Selector Component (alternative implementation)
import { Menu, Transition } from "@headlessui/react";
import { Fragment } from "react";
import { useTranslation } from "react-i18next";
const LanguageSelector = () => {
const { i18n } = useTranslation();
const languages = [
{ code: "en", name: "English", country_code: "gb" },
{ code: "fr", name: "Français", country_code: "fr" },
// add more languages as needed
];
return (
<>
<Menu as="div" className="relative inline-block text-left">
{/* ... UI markup ... */}
{languages.map((lng) => (
<Menu.Item key={lng.code}>
{({ active }) => (
<button
className={active ? "bg-gray-100" : ""}
onClick={() => i18n.changeLanguage(lng.code)}
disabled={i18n.language === lng.code}
>
{lng.name}
</button>
)}
</Menu.Item>
))}
</Menu>
</>
);
};
export default LanguageSelector;
How It Works
The dropdown displays language options together with their country flags. When a user selects a language, i18n.changeLanguage(languageCode) is called, updating the language across the entire application.

Sample Form Component
Below is a simple component that renders localized labels using the t function from react‑i18next.
import ModuleContainer from "components/shared/moduleContainer/ModuleContainer";
import { useTranslation } from "react-i18next";
function SampleForm() {
const { t } = useTranslation();
return (
<ModuleContainer>
<label>{t("hello")}</label>
<button>{t("cancel")}</button>
</ModuleContainer>
);
}
export default SampleForm;


When a language is selected via the LanguageSelector, the t function automatically returns the appropriate translation for each key ("hello", "cancel", etc.). This approach lets you render labels and messages in any supported language throughout your React application.
If you found this helpful, feel free to subscribe, clap, like, and share. Cheers!