Search code examples
reactjsinternationalizationlazy-loadingi18nextreact-i18next

react-i18next - How do I add a backend to i18n after it has been initialized?


I want my i18n to lazy load translation files and from the docs, it seems quite simple to do that - add .use(backend) and import backend from "i18next-http-backend".

The only issue is that the i18n instance I use in my provided has been already defined in my org's internal repo as a UI library (which I have to use) which exposes only one method to initialize an i18n instance for you - this doesn't have any provision for .use(backend) and now I'm stuck how to add that to the code.

Here's the library code -

...

export const getDefaultI18nextInstance = (resources) => {
  i18n
    .use(AlphaLanguageDetector)
    .use(initReactI18next)
    .init({
      fallbackLng: 'en',

      // have a common namespace used around the full app
      ns: [
        'translations',
        'common'
      ],
      nsMode: 'fallback',
      defaultNS: 'translations',

      // debug: (process.env.NODE_ENV && process.env.NODE_ENV === 'production') ? false : true,
      debug: true,

      interpolation: {
        escapeValue: false, // not needed for react!!
      },

      resources: resources || null,

      react: {
        wait: true
      }
    });
    Object.keys(translations).forEach(lang => {
      Object.keys(translations[lang]).forEach(namespace => {
        i18n.addResourceBundle(lang, namespace, translations[lang][namespace], true, true)
      })
    });
  return i18n;
}

export default {
  getDefaultI18nextInstance,
  translations,
  t
};
...

I tried using it something like this <I18nextProvider i18n={i18n.getDefaultI18nextInstance().use(backend)}> in my index.js file but then I get the error

i18next::backendConnector: No backend was added via i18next.use. Will not load resources.

FYI, I have my locales at projectRoot/locales/{lang}/translation.json.


Solution

  • You can use i18n.cloneInstance(options, callback) and pass your backend config as options, it will merge all the options that your ui lib has with yours, and return a new instance of i18next which will be able to fetch.

    import HttpApi from 'i18next-http-backend';
    
    const original = getDefaultI18nextInstance({});
    
    export const i18n = original
      .cloneInstance({
        backend: {
          loadPath: '/locales/{{lng}}/{{ns}}.json',
        },
      })
      .use(HttpApi);