5

Overview

React application in which internationalization is required, using i18next to achieve this.

Problem

In project structure there is constants.js (Plain JS) where I am trying to get i18next.t() for translation. Please find the relevant code.

index.js

import React,{Suspense} from "react";
import ReactDOM from "react-dom";
import "./style/index.scss";
import App from "./app";
import createSagaMiddleware from "redux-saga";
import { createStore, applyMiddleware } from "redux";
import { Provider } from "react-redux";
import rootReducer from "./reducers";
import rootSaga from "./sagas";
import './i18n';

const sagaMiddleware = createSagaMiddleware();
const store = createStore(rootReducer, applyMiddleware(sagaMiddleware));
sagaMiddleware.run(rootSaga);

ReactDOM.render(<Provider store={store}>

    <App store={store} />

</Provider>,
    document.getElementById("root")
);

App.js

import React from "react";
import "./App.scss";
import MyOrders from "../component/my-orders";
import { toast } from "react-toastify";
import "react-toastify/dist/ReactToastify.css";
import i18n from 'i18next'

toast.configure({ autoClose: 5000 });

const changeLanguage = (lng) => {
    i18n.changeLanguage(lng);
};


const App = () => {


    return (
        <div className="App">
            <div align="left">
                <button className="btn btn-group-sm" onClick={() => changeLanguage('de')}>German</button>
                <button className="btn btn-group-sm" onClick={() => changeLanguage('en')}>English</button>
            </div>
            <MyOrders />
        </div>
    );
};

export default App;

i18n.js

import i18n from "i18next";
import detector from "i18next-browser-languagedetector";
import { reactI18nextModule } from "react-i18next";

import translationEN from '../public/locales/en/translation.json';
import translationDE from '../public/locales/de/translation.json';

// the translations
const resources = {
  en: {
    translation: translationEN
  },
  de: {
    translation: translationDE
  }
};

i18n
  .use(detector)
  .use(reactI18nextModule) // passes i18n down to react-i18next
  .init({
    resources,
    lng: "en",
    fallbackLng: "en", // use en if detected lng is not available

    interpolation: {
      escapeValue: false // react already safes from xss
    }
  });

export default i18n;

Question Updates with progress so far

constants.js (Plain JavaScript file, exporting multiple constant objects)

import i18n from "../../i18n";
import { withNamespaces } from "react-i18next";

function parentFunction(){
   let constantsMap = new Map();
   constantsMap.set("constant1", valueOfConstant1);
   ....
}
export default withNamespaces()(parentFunction)

translation.js (de)

{
"MODAL": {
    "CANCEL": "Stornieren",
    "UPDATE": "Aktualisieren",
    "SAVE": "Speichern",
    "CANCEL_BOD": "Ja, Abbrechen BOD",
    "KEEP_BOD": "Nein, behalte BOD",
    "NEXT": "Nächster"
}, .....

I tried the following solution with no luck: Solution

Zain Ul Abideen
  • 1,617
  • 1
  • 11
  • 25

2 Answers2

12

You can import i18n instance from your i18n.js file, it contains t on it.

import i18n from '../i18n';

i18n.t // <- use it.
felixmosh
  • 32,615
  • 9
  • 69
  • 88
  • Thanks for the answer, still having an issue, I am able to get `i18n.t()` in the constants file but it's not translating content as per defined in translation.js file instead it does not seem to do anything at all. I've updated the question with some of the content of the translation file. – Zain Ul Abideen Feb 11 '20 at 08:49
  • 1
    You probably need to define the `namespace` && `language`, which doesn't make sense to do directly in constants file. Consider to convert those constants to functions that gets `t` (from react) and returns a translated value. – felixmosh Feb 11 '20 at 09:26
  • I am trying it as per directives from you, hope it should work. – Zain Ul Abideen Feb 11 '20 at 09:48
  • I've tried to convert constants to a function called `parentFunction` (updated question with progress so far) and then exported it to where I wanna use but exporting with name spaces doesn't seem to work. I get an error where I am getting value of Map: > constantsMap.get("constant1") is not a function When I am exporting it without namespaces it exported correctly with no error, but unable to translate because I am not exporting with namespaces. – Zain Ul Abideen Feb 12 '20 at 07:16
  • I ment something much simpler, assume that constants export a constant variable X, instead of that export function getX, that accepts t from outside (react) and returns the translated value. – felixmosh Feb 12 '20 at 07:35
  • I tried this, I am importing i18n in one of my constants.js file. It's a simple plain JS file with contant strings and objects. In my case it properly load the default language and get the correct value from translation file. But when I change the language it doesn't reflect. Changing language works well everywhere else – Affan Shahab Feb 12 '20 at 12:15
  • Sure, it won't work on language change. Can u explain what are those constants strings that you have in it? And what do u want to translate? – felixmosh Feb 12 '20 at 12:30
  • So for example some basic array to populate some drop down. It's been used multiple times so kept them in a central location for reuseability. – Affan Shahab Feb 12 '20 at 13:02
  • 3
    Ha, so invert the dependencies, constants will hold the keys, and each user will import it and pass to translation. – felixmosh Feb 12 '20 at 15:52
  • I didn't get the part "invert the dependencies". However I ended up putting keys in constants.js and used t function inside components and it worked as expected – Affan Shahab Feb 13 '20 at 08:01
  • That what I've meant by "invert dependencies" :] – felixmosh Feb 13 '20 at 08:05
  • 1
    @felixmosh, Thanks for the help buddy, it was a good discussion. – Zain Ul Abideen Feb 14 '20 at 07:09
  • I use `i18next-scanner` and so I have also set up an `N_()` function that I use to mark the constants for translation. At the callers, we can use the `t()` function to actually get the translation. This is how I implemented the "invert dependencies" discussed above. – snasirca Oct 05 '20 at 16:06
5

I used it this way on redux saga

import i18n from "i18next";
      toast.error(i18n.t('thereWasAnErrorUpdating'), {
            position: toast.POSITION.TOP_CENTER,
            autoClose: NOTIFICATION_TIME,
            toastId: 'settingInformationFailure'
        });
Ali Bulut
  • 194
  • 1
  • 8