1

I'm currently working on internationalizing a system built with single-spa (microfrontends) with applications written on Angular and React. I started using i18next and it's going pretty well, however, I've found a problem when trying to share the i18next dependency between all the applications.

When two applications are mounted simultaneously on the view the one who loads last overrides the i18next instance and thus the translations for the first one are never found as they were not loaded on the latter.

Thanks in advance!

Oriol_IL
  • 120
  • 1
  • 14

1 Answers1

2

It is better that I18next will be initialized at the shell level with the shell namespaces, and each internal spa will add its namespaces to the shared instance.

This way you won't have duplication of instance & code.

You can use [i18next.addResourceBundle][1] in order to add translation resources that are related to the current inner app.


i18next.addResourceBundle('en', 'app1/namespace-1', {
// ----------------------------------^ nested namespace allow you to group namespace by inner apps, and avoid namespace collisions
  key: 'hello from namespace 1'
});

Pass the i18next instance as props to the inner app.

// root.application.js

import {i18n} from './i18n';
// ------^ shells i18next configured instance

singleSpa.registerApplication({
  name: 'app1',
  activeWhen,
  app,
  customProps: { i18n, lang: 'en' }
});
// app1.js

export function mount(props) {
  const {i18n, lang} = props;

  i18n.addResourceBundle(lang, 'app1/namespace-1', {
    key: 'hello from namespace 1',
  });
  return reactLifecycles.mount(props);
}

Hope that the idea is clear :] [1]: https://www.i18next.com/how-to/add-or-load-translations#add-after-init

felixmosh
  • 32,615
  • 9
  • 69
  • 88
  • I updated the question with other problem I found problem after following your answer. I am not passing i18next as props as I understand that it should work with the import (https://github.com/openmrs/openmrs-react-root-decorator/blob/3614572ee5aa5cb39cf550c051a200d4f8a67280/src/openmrs-react-root-decorator.js#L6). It is working correctly with one of the apps but it crashes on the next as it's shown as not initialized. I put the details on the question. – Oriol_IL Jun 24 '20 at 09:05
  • 1
    You've imported `i18next` from the lib, therefore, it is not initialize. you need to pass the shared (& configured) instance, pay attention, I've done it by passing it via single-spa props, in your case this is shell's `initTranslation` variable – felixmosh Jun 24 '20 at 09:12
  • I see. However, I'm confused as to how is it initialized on the other app and not in that one. – Oriol_IL Jun 24 '20 at 09:50
  • I used one of the other header applications I have and it worked correctly, so the problem must be in my app and has nothing to do with your or my solution. I'll be editing the post again and mark your answer as correct. Thank you! – Oriol_IL Jun 24 '20 at 10:48
  • I am using react-i18next in my individual micro app done using module federation. When I am navigating between micro app first time it calls i18n config for each app but when I navigate again it is loading previous app config. resulting in wrong translation. Am I doing it right ? – aman Nov 27 '21 at 14:20
  • Aman - you need to add if condition before the initialisation inside the child apps, use i18n.isIniitialized func and if it’s true just import using addresources bundle func. – OriEng Dec 02 '21 at 17:28