ikonuk
ikonuk

Reputation: 652

i18next translations not working for imported components from a design system library

I am using a design system built with Storybook, React, TypeScript, and Material UI v5 for various applications. The design system, bundled as a library, has its own set of translations managed by i18next. In my host application, I also use the same technology stack and i18next for translations.

However, I am experiencing an issue where the translations in the imported design system components do not display correctly when used in the host application. Instead of displaying the translated text, I am only seeing the translation keys. The translations within the host application work perfectly fine, and even the design system translations that are manually imported and used in the host application work as expected. The issue arises specifically with the encapsulated components from the design system.

Here is a simplified version of the setup for clarity:

Design System i18n instance:

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

const resources = {
  en: {
    translation: enTranslation,
  },
  de: {
    translation: deTranslation,
  },
};

i18n.use(initReactI18next).init({
  resources,
  lng: "en",
  fallbackLng: "en",
  interpolation: {
    escapeValue: false,
  },
});

export default i18n;

Design System Component:

import { useTranslation } from "react-i18next";

const DesignSystemComponent = () => {
  const { t } = useTranslation();

  return( <div>{t('design_system.translation.key')}</div> );
}

Host App i18n instance:

import i18n from "i18next";
import LanguageDetector from "i18next-browser-languagedetector";
import { initReactI18next } from "react-i18next";
import en from "./localization/locales/en/en.json";
import de from "./localization/locales/de/de.json";

const detectionOptions = {
  order: ["htmlTag"],
};

export type SupportedLanguage = "en" | "de";
const fallbackLng: SupportedLanguage = "en";

i18n
  .use(initReactI18next)
  .use(LanguageDetector)
  .init({
    resources: {
      en: { translation: en },
      de: { translation: de },
    },
    fallbackLng,
    debug: false,
    interpolation: {
      escapeValue: false,
    },
    detection: detectionOptions,
  });

export default i18n;

Host App Component:

import { useTranslation } from "react-i18next";
import { DesignSystemComponent } from "design-system";

const HostAppComponent = () => {
  const { t } = useTranslation();
  
  return(
    <>
      <div>{t('host_app.translation.key')}</div> // Translation works
      <DesignSystemComponent/> // Translation doesn't work
    </>
  );
}

I have already tried importing the design system translations into the host application's i18n instance but to no avail.

How can I resolve this issue to ensure that the translations within the imported design system components display correctly in the host application? Alternatively, how should I implement translations/localisation within the design system to make it production-ready and independent from the host system?

Upvotes: 3

Views: 1532

Answers (1)

Gerard Parareda
Gerard Parareda

Reputation: 77

Which bundler are you using (Webpack, Rollup, ...) ? I had the same problem as you and I found these interesting github issues:

I was getting this warning in the browser console:

react-i18next:: You will need pass in an i18next instance by using i18nextReactModule

So you should check for yourself if it is the same issue.

I found that for myself, in order to get the i18n instance from the App to the component library, it was necessary to set both i18n and react-18next as an external and peerDependency in the component library. Like so:

package.json (use any version of the packages you need)

{
  ...,
  "dependencies": {
    ...,
  },
  "devDependencies": {
    ...,
  },
  "peerDependencies": {
    "i18next": "^23.7.8",
    "react-i18next": "^13.2.2"
  },
}

vite.config.ts

export default defineConfig({
  ...,
  rollupOptions: {
    external: [
      "react-i18next",
      "i18next"
    ]
  }
});

After doing this, building (in my case, with ViteJS and Typescript tsc --noEmit && vite build), uploading the /dist folder to my repository and installing my components library via npm i [email protected]:your-name/repo-name.git; I get translations from the App in the App with the library components.

You can also try if it already works for you using the npm link tool, which worked for me before declaring the dependencies as peer and external.

Feel free to ask anything else, I'll try to answer as well as I can.

Upvotes: 2

Related Questions