Skip to content

Change localization directory base on local storage item

In a particular step in the React stepper component, I have to change the directory based on a steps language. Unfortunately in one of the steps, the text is hardcoded into the images which requires me to make this change. The app uses i18next for localization.

Currently, all images for this step are rendered with this code:

return sectionItems.map((el, i) => {
      const disabled =
        el.meta === null || !el.meta.disabled ? false : el.meta.disabled;
      return {
        item: {
          img:
            el.resource !== null ? require(`../../assets${el.resource}`) : logo,
          label: i18next.t(el.name),
          disabled,
        },
      };
    });

There is an item in window.localStorage.i18nextLng that returns the “es” key for Spanish.

I tried creating a conditional statement that would read this key and then return the directory based on language:

const getImages = (sectionItems) => {
  debugger;
  if (window.localStorage.getItem.i18nextLng === 'es') {
    return sectionItems.map((el, i) => {
      const disabled =
        el.meta === null || !el.meta.disabled ? false : el.meta.disabled;
      return {
        item: {
          img:
            el.resource !== null &&
            window.localStorage.getItem.i8nextLng === 'en'
              ? require(`../../assets/en${el.resource}`)
              : logo,
          label: i18next.t(el.name),
          disabled,
        },
      };
    });
  } else {
    return sectionItems.map((el, i) => {
      const disabled =
        el.meta === null || !el.meta.disabled ? false : el.meta.disabled;
      return {
        item: {
          img:
            el.resource !== null ? require(`../../assets${el.resource}`) : logo,
          label: i18next.t(el.name),
          disabled,
        },
      };
    });
  }
};

All of the other steps are rendering correctly with the current structure. However, I can’t get the images from the es folder to map.

src
  |_assets
      |_images
      |_ en
        |_images

How can I change my directory based on this key or is there a way to concatenate the folder location in the path of the original code that would allow flexibility for more than one language? Is there a better way this scenario can be handled with i18next? Thanks in advance for any help.

Answer

I am afraid Webpack by default (and in CRA) will not allow creating dynamic import path. Moreover, you should not mix CommonJS and ES6 (use import instead of require).

You will need to explicitly define these resources. You may use lazy evaluation to lower the size of whole bundle (so one bundle does not contain all languages data).

const resources = {
  en: {
    Logo: () => import('../../assets/en/Logo'),
  },
  es: {
    Logo: () => import('../../assets/es/Logo'),
  },
};

You can also create modules that contain components / assets for specific language and import those modules dynamically.

assets/en.js

import Logo from './en/Logo';

export default {
  Logo,
};

assets/es.js

import Logo from './es/Logo';

export default {
  Logo,
};

LocalComponentsProvider.js

const resources = {
  en: () => import('../../assets/en'),
  es: () => import('../../assets/es'),
};