0

I am facing one strange issue in react/Javascript My below file calls the data from backend API and assign it for translation.

import i18next from 'i18next';
import apiDelegate from '../src/components/Utils/Common/api.js';
const LanguageDetector = require('i18next-browser-languagedetector');
const initReactI18next = require('react-i18next');

var output;
//API call
apiDelegate.getTranslations().then((result) => {
 output = JSON.stringify(result);
 const tr_fr = 'translation: ' +JSON.parse(output) ;
alert(tr_fr);
  i18next
    .use(LanguageDetector)
    .use(initReactI18next)
    .init({
      resources: {
        en: tr_fr,
      },
      fallbackLng: 'fr',
    });
  i18next.changeLanguage(navigator.language);
});

export default i18next;

Below lines is used for calling backedn API. apiDelegate.getTranslations() it returns data in the form of key value. for ex {name:"Mahima",company:"Infosys",address:"Bangalore India"} and I use these properties in my react componenet using below line.

i18n.t("name");

i18n.t("company") etc

Is it possible that these values are getting read in my component before apiDelegate() finished its execution.I mean is there a possibility code is using i18 file before its execution finished. because its not refelecting the values. instead of API if I use static files then it works perfectly.

Please help me , I am badly struggling to understand this. can it be resolved?

Shruti sharma
  • 199
  • 6
  • 21
  • 67
  • Everything in the .then block happens at some point in the future. Which means the initial export happens before the .changeLanguage. – windowsill Jan 23 '22 at 06:12
  • actually API returns data in key value pairs. so I need to use something likr i18("key") .as per below answser will await work without async? – Shruti sharma Jan 23 '22 at 12:04
  • Does this answer your question? [how to incorporate API data in i18next instead of static file](https://stackoverflow.com/questions/70589040/how-to-incorporate-api-data-in-i18next-instead-of-static-file) – adrai Jan 24 '22 at 13:14

2 Answers2

1

If you need your consumers to wait until the language has been setup, you could return a promise from this module instead. Something like:

let ready = false;

const start = () => {
  return new Promise((res) => {
    if (ready) return res(i18next);

    apiDelegate.getTranslations().then((result) => {
      output = JSON.stringify(result);
      const tr_fr = 'translation: ' + JSON.parse(output);
       i18next
         .use(LanguageDetector)
         .use(initReactI18next)
         .init({
           resources: {
             en: tr_fr,
           },
           fallbackLng: 'fr',
         });
       i18next.changeLanguage(navigator.language);
     });

     ready = true;
     return res(i18next);
  });
};

export default start;

Update: This is how I would probably use it.

export const useLanguage = () => {
  const [l, setL] = useState({i18next});

  useEffect(() => {
    apiDelegate.getTranslations().then((result) => {
      // ...
    i18next.changeLanguage(navigator.language);
    setL({i18next});
    });
  }, []);

  return l;
};
windowsill
  • 3,599
  • 1
  • 9
  • 14
  • thank you so so much @windowsill . do I need to change, how I have to use this file in other component? I am using like this as of now . i18n.t("company") – Shruti sharma Jan 23 '22 at 06:30
  • 1
    Yes, it's wrapped in a function which returns a promise, so you use it like `import geti18n from "./whatever"; (await geti18n()).t("company");`. – windowsill Jan 23 '22 at 06:51
  • 1
    If instead you need to access it synchronously, you could serve the i18n object from a react context. Then all the consumer components would react to the language change. – windowsill Jan 23 '22 at 06:52
  • do you have any link or any resource which I can go through to understand second option? – Shruti sharma Jan 23 '22 at 06:53
  • Hello @Windowsill I am getting error await is a reserve word. Module build failed: SyntaxError: C:/freshnew1/frontend/src/i18.js: await is a reserved word (34:6) – Shruti sharma Jan 23 '22 at 09:26
  • Please dont mind..I am asking more question bcoz I am new and not able to resolve. where is geti18n() defined? also can we use await without async? instead of geti18n() should I use something else to call? – Shruti sharma Jan 23 '22 at 09:41
1

This seems to be a duplicate of:

You may want to use i18next-http-backend: how to incorporate API data in i18next instead of static file

adrai
  • 2,495
  • 1
  • 15
  • 18
  • Ofcourse its duplicate. I put so many question but did not get required answer. even put bounty on questions. LoadPath is for filepath not for API call...can you help with proper answer? – Shruti sharma Jan 23 '22 at 10:21
  • In my anwer on that link there I put also 2 alternatives… the one with custom request function is probably the best option for you. https://github.com/i18next/i18next-http-backend/issues/34#issuecomment-729908814 – adrai Jan 23 '22 at 12:25