Home > OS >  React internalisation SPA using i18next
React internalisation SPA using i18next

Time:10-18

I need to translate my app, but i don't knomw how to use useTranslation() in the top-level files (i store there some consts which contain some text). One of this file is

import { useTranslation } from "react-i18next";

const {t} = useTranslation()

    export const selectThemeOptions = [
      { value: "choose", text: "Choose theme" },
      { value: "Algebra", text: "Algebra" },
      { value: "Geometry", text: "Geomerty" },
      { value: "Programming", text: "Programming" },
      { value: "Logic", text: "Logic" },
    ];

so in this case i have an error: src\Configs\ThemesOfProblems.js Line 3:13: React Hook "useTranslation" cannot be called at the top level. React Hooks must be called in a React function component or a custom React Hook function react-hooks/rules-of-hooks

I need this array in my component, and it use in the next fragment :

<Form.Group as={Col} controlId="problemTheme">
                                <Form.Label>{t("userprofile.theme")}</Form.Label>
                                <Form.Select
                                    name="theme"
                                    value={values.theme}
                                    onChange={handleChange}
                                    isValid={touched.theme && !errors.theme}
                                    isInvalid={!!errors.theme}
                                    onBlur={handleBlur}
                                >
                                    {selectThemeOptions.map((el, index) => {
                                        return <option key={index} value={el.value}> {el.text} </option>
                                    })}
                                </Form.Select>
                            </Form.Group>

And i've got a lot of such situations, i don't have any ideas how to do it

CodePudding user response:

Basically it says it has to be called in a react component. It could be called in a functional component where you return your jsx or a class component that has a render method in it. If you call the function outside of one of these, then you will get this error.

CodePudding user response:

You called const {t} = useTranslation(); outside of a React component, your selectThemeOptions file seems to be a regular JavaScript due to the absence of JSX or a returning statement with your HTML.

Here is the correct way to do it:

/* Everything above this point is considered top-level, hence using your `useTranslation()` hook here would cause an error */

const Component = (props) => {
  const { t } = useTranslation();
}

export default Component;

Here is a way to organise your translations:

• Your src folder should contain an i18n.js file with the following code:

import i18n from "i18next";
import { initReactI18next } from "react-i18next";
import en from "../locales/en.json";
import ru from "../locales/ru.json";

const isReturningUser = "lang" in localStorage; // Returns true if user already used the website.
const savedLanguage = JSON.parse(localStorage.getItem("lang")); // Gets persisted language from previous visit.

// Get previously used language in case of returning user or set language to Russian by default.
const language = isReturningUser ? savedLanguage : "ru";

const resources = {
  en: {
    translation: en,
  },
  ru: {
    translation: ru,
  },
};

i18n.use(initReactI18next).init({
  resources,
  lng: language,
  keyseparator: false,
  interpolation: {
    escapeValue: false,
  },
});

export default i18n;
  • Your src folder should contain a locales folder with json files of the languages your application uses. Example: ru.json and en.json:
{
  "choose": "Выбрать",
  "chooseATheme": "Выбрать тему",
  "algebra": "Алгебра",
  "geometry": "Геометрия",
  "programming": "Программирование",
  "logic": "Логика",
}

  • Your component should look like this – note that the translations are in json files instead of your React component – :
import React from "react";
import { useTranslation } from "react-i18next";

const Component = (props) => {
  const { t } = useTranslation();

const selectThemeOptions = [
      { value: t("choose"), text: t("chooseATheme") },
      { value: t("algebra"), text: t("algebra") },
      { value: t("geometry"), text: t("geometry") },
      { value: t("programming"), text: t("programming") },
      { value: t("logic"), text: t("logic") },
    ];

return( //Your UI )
   
}

export default Component;

This way, your translations wouldn't be hard-coded on your selectThemeOptions and will adapt to whichever translation your json locales contain.

Please tell me if this works.

Edit: If you want a concrete example of implementation of my solution here it is: https://github.com/YHADJRABIA/ecommerce/tree/main/src

Edit2: There might be a better solution of doing this, this is merely what worked for me.

Edit3: Following Nikita's comment, here's a solution to use the translation function outside of a react component —How to use react-i18next inside BASIC function (not component)?

P.S. Since you are from Belarus I assume that you want your translation to be made in Russian since Belarusian isn't as widely spoken.

  • Related