React and i18next
This is a simple example of how to use this tool with i18next
in React.
Note that you can also use any other i18n library or framework of your choice.
Let's start by installing all the necessary dependencies.
npm i i18next react-i18next
npm i i18n-collector --save-dev
Let's take a closer look at each of these dependencies.
- i18next is a core library for i18n.
- react-i18next is a library for using
i18next
with React. i18n-collector
is a tool that simplifies the management of multiple translation files in your application.
1. Configure i18next
Let's assume that our app needs to support two languages: 🇬🇧 English
and 🇩🇪 German
.
/src/i18n.js
import i18n from "i18next";
import en from "./locales/en.json";
import de from "./locales/de.json";
i18n.use(initReactI18next).init({
resources: {
en,
de,
},
lng: "en",
fallbackLng: "en",
interpolation: {
escapeValue: false,
},
});
We've created a configuration file for i18next and imported ./locales/en.json
and ./locales/de.json
files.
These files will be generated by i18n-collector later, and it is important that you do not create them manually.
The configuration we've provided for i18next is a simple one that may not meet all of your needs. You may need to configure i18next differently depending on your specific requirements. For more information about i18next configuration options, please refer to the official i18next documentation.
2. Add new scripts to package.json
{
"scripts": {
"i18n:compile": "npx i18n-collector run locales --input src --clear",
"i18n:watch": "npx i18n-collector run locales --input src --clear --watch"
}
}
Let's take a closer look at each of these scripts.
i18n:compile
- compiles translation files into the./locales
directoryi18n:watch
- compiles translation files and watches for changes (useful for development).
3. Add ./locales
to your .gitignore
file.
If you are working with a team, it is recommended that you do not commit your compiled translation files to the repository, as they can lead to merge conflicts.
.gitignore
# other files
locales
4. Create a new component
Let's say we need to create a Product
component to display a product card. To get started, let's create a directory for our component and add a file for its translations
src
└── components
└── Product
├── Product.jsx
└── Product.locale.json
As you can see, we've created a Product.locale.json
file next to our Product.jsx
file.
This file will contain translations for our Product
component.
Now, let's prepare some translations for our Product component.
/src/components/Product/Product.locale.json
{
"en": {
"name": "Product name",
"description": "Description",
"price": "Price",
"buy": "Add to cart"
},
"de": {
"name": "Produktname",
"description": "Beschreibung",
"price": "Preis",
"buy": "In den Warenkorb"
}
}
Let's write our component.
/src/components/Product/Product.jsx
import { useTranslation } from "react-i18next";
export default function Product({ product }) {
const { t } = useTranslation();
return (
<div>
<h1>
{t("Product:name")}: {product.name}
</h1>
<img src={product.image} alt={product.name} />
<p>
{t("Product:description")}: {product.description}
</p>
<p>
{t("Product:price")}: {product.price}
</p>
<button>{t("Product:buy")}</button>
</div>
);
}
As you can see, we've used the useTranslation
hook with our Product
namespace to access the translations for our component.
Note that you shouldn't import the Product.locale.json
file anywhere. It'll be found and handled automatically by i18n-collector.
5. Compile translations files
We've created a component and added translations for it.
Now we can use the i18n:compile
script to compile our translations files.
npm run i18n:compile
As a result, we now have two files in the ./locales
directory that were generated by the above script.
locales
├── en.json
└── de.json
Let's take a look at the en.json
file.
/locales/en.json
{
"Product": {
"name": "Product name",
"description": "Description",
"price": "Price",
"buy": "Add to cart"
}
}
Note that it is important to use the correct locale keys when using the useTranslation
hook in the React components, as they will match the keys defined in the translation files.
For example, if we have a key description
defined in the Product.locale.json
file, we will need to use the same key in the component when calling the t
function, like t('Product:productTitle')
.
The Product:
prefix (namespace) is added automatically by i18n-collector
based on the name of the file.
You can use the --watch
flag to automatically recompile your translation files when you make changes to them.
6. ⚡️ Add TypeScript
You can essentially improve your development experience by using TypeScript with i18next
and i18n-collector
.
i18n-collector
will collect all your translations and generate a single file for each language
and i18next
can use these files to infer types for all your translations.
Let's use official i18next
TypeScript example as a base.
i18n.ts
import "i18next";
import en from "./locales/en.json"; // import compiled file
// extend i18next's module declaration
declare module "i18next" {
interface CustomTypeOptions {
resources: {
[key in keyof typeof en]: (typeof en)[key];
};
}
}
// configure i18next
Now TypeScript will check your usage of t
function and will show you an error if you use a wrong namespace or key.
<button>{t("Product:buy")}</button> // ✅ correct
<button>{t("WrongNamespace:buy")}</button> // ❌ incorrect