i18next

Last updated: February 26, 2024Author: Jakub Pomykała

i18next: changing translations in realtime

In this article, you will learn how to configure i18next to server-side translations using i18next-http-backend library. Additionally, you will learn you how to create translation keys automatically with default translation in translation editor.

Table of contents

Install dependencies

# Using NPM
npm install --save react-i18next i18next i18next-http-backend i18next-browser-languagedetector axios

Configure i18next

Create i18n.ts file with i18next-http-backend configuration. i18next-http-backend is responsible for:

  • fetching translations from a remote server,
  • creating new keys used in your project.
import i18n from 'i18next'
import Backend from 'i18next-http-backend'
import LanguageDetector from 'i18next-browser-languagedetector'
import {initReactI18next} from 'react-i18next'
import axios from "axios";

const isProductionCode = process.env.NODE_ENV === 'production';
const fallbackLanguage = 'en'

const projectToken = "XXXXXXXXXXXXXX"; // YOUR PROJECT TOKEN
const apiKey = "XXXXXXXXXXXXXX"; // YOUR API KEY

const apiBaseUrl = "https://api.simplelocalize.io/api";
const cdnBaseUrl = "https://cdn.simplelocalize.io";
const environment = "_latest"; // or "_production"
const loadPath = `${cdnBaseUrl}/${projectToken}/${environment}/{{lng}}`;
const loadPathWithNamespaces = `${cdnBaseUrl}/${projectToken}/${environment}/{{lng}}/{{ns}}`;
const configuration = {
    headers: {
        'X-SimpleLocalize-Token': apiKey
    }
};

const createTranslationKeys = async (requestBody) => axios.post(`${apiBaseUrl}/v1/translation-keys/bulk`, requestBody, configuration)
const updateTranslations = async (requestBody) => axios.patch(`${apiBaseUrl}/v2/translations/bulk`, requestBody, configuration)

const missing = [];
const saveMissing = async () => {
    if (missing.length === 0 || isProductionCode) {
        return;
    }
    console.info(`Saving ${missing.length} missing translation keys`);

    const translationKeys = missing.map((element) => ({
        key: element.translationKey,
        namespace: element.namespace,
    }));

    await createTranslationKeys({translationKeys})
        .catch((error) => console.error(`Error during creating translation keys: ${error}`));

    const translations = missing.map((element) => ({
        key: element.translationKey,
        namespace: element.namespace,
        language: element.language,
        text: element.fallbackValue,
    }));
    await updateTranslations({translations})
        .catch((error) => console.error(`Error during updating translations: ${error}`));
    missing.length = 0;
}

setInterval(async () => {
    await saveMissing();
}, 30_000); // decreasing this value may lead to the API rate limit

i18n
    .use(Backend)
    .use(LanguageDetector)
    .use(initReactI18next)
    .init({
        fallbackLng: fallbackLanguage,
        backend: {
            loadPath: loadPath, // or loadPathWithNamespaces if you use namespaces
        },
        saveMissing: !isProductionCode,
        defaultNS: "", // you can set default namespace here
        missingKeyHandler: async (languages, namespace, translationKey, fallbackValue) => {
            console.debug(`[${namespace}][${translationKey}] not available in Translation Hosting`);
            missing.push({
                translationKey: translationKey,
                namespace: namespace ?? "",
                language: languages[0] ?? fallbackLanguage,
                fallbackValue: fallbackValue ?? ""
            });
        }
    })


export default i18n;

Remember to provide your Project Token in projectToken variable and API Key in apiKey variable. You can find it in your SimpleLocalize project > Integrations > Project Credentials.

Import configuration

Import i18n.ts file in index.ts by adding import './i18n';.

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

ReactDOM.render (
  <React.StrictMode>
    <Suspense fallback={<div>Loading...</div>}>
        <App />
    </Suspense>
  </React.StrictMode>,
  document.getElementById('root')
);

Usage

i18next is now configured and ready to use. You can use it in your components like this:

import React from "react";
import { useTranslation } from "react-i18next";

function App() {
  const { t, i18n } = useTranslation();

  // uncomment if you use namespaces
  // const { t, i18n } = useTranslation('MY_NAMESPACE');

  const translatedMessage = t("USE_BUTTONS_BELOW");

  return (
        <div>
          <p>
            {translatedMessage}
          </p>
          <button onClick={() => i18n.changeLanguage("en")}>English</button>
          <button onClick={() => i18n.changeLanguage("es")}>Spanish</button>
        </div>
  );
}

export default App;

You can use t function to get translation for a given translation key and switch languages with i18n.changeLanguage(language) function, where language is a language key from SimpleLocalize.

Translate React application

Now you can translate your React application JSONs using the translation editor and publish changes.

Manage your translation strings in Translation Editor

If you want to translate your app in multiple languages fast, you can add new languages in the Languages tab, and use auto-translation features to speed up the process.

How to start auto-translation for many languages at once

After you finish translating your app, you can go to the 'Hosting' tab and click 'Publish' button to publish your translations to the app.

Troubleshooting

Forbidden error

If you get Forbidden error, please make sure that you provided a correct API Key in apiKey variable.

"Origin starts with 'https://'" error

The integration is configured to work only with http:// origins that are used in development mode by default. It's a safety mechanism to make sure that you are not pushing missing keys from the production environment, which exposes your API Key.

CORS error

If you get CORS error, please make your you don't send any custom headers in your Axios request in missingKeyHandler function. The other reason for CORS error might be triggering a rate-limiter due to many missing translation keys requests.

Please make sure that you don't have any infinite loops in your code that trigger missingKeyHandler function, which is responsible for sending missing translation keys to SimpleLocalize.

Please also make sure that you didn't deploy any other code, that sends requests to this endpoint that might trigger rate-limiter, as requests counted are counted per API Key.

i18next-http-backend load error

The error might be caused by the custom requestOptions settings in backend property. Please make sure that your configuration is the same as above.

Incorrect API Key

Incorrect API Key log in console means that your provided an incorrect API Key to your project. Here is how to get your API Key:

  1. Go to SimpleLocalize
  2. Click on your project
  3. Click on Integrations tab
  4. Open on Project Credentials tab from the left panel
  5. Copy your API Key and use in apiKey variable.

More resources: