skip to Main Content

I am working on a React project where I have implemented language switching using i18next. The language switcher works correctly and changes the language with requiring a page reload. However i want it to work withour reload and after changing my language switch to work without reload I am facing an issue where the dynamically translated content in my components does not update when the language changes. The static content translated with useTranslation updates correctly, but the dynamically generated content in my components does not.

So i have LanguageSwtich is working correct with reload.

export default function LanguageSwitch() {
  const { i18n } = useTranslation();
  const [language, setLanguage] = useState(localStorage.getItem('lang') ?? 'en');

  function handleLangChange(lang: Key) {
    localStorage.setItem('lang', lang.toString())
    window.onload = function() {
      i18n.changeLanguage(lang.toString())
        .then(() => {
          setLanguage(lang.toString());
        })
        .catch((error) => {
          console.error('Error changing language:', error);
        });
    };
    window.location.reload();
  }

  return (
    <Dropdown aria-label='Language change switch'
              className={'language-switch'}
              onSelectionChange={handleLangChange}
              defaultSelectedKey={language}
              items={SUPPORTED_LANGUAGES}>
      {item =>
        <Item key={item.code}>{item.name}</Item>
      }
    </Dropdown>
  )
}

I changed method of handle to not relaod page and my dynamic data not translating now

function handleLangChange(lang: Key) {
    localStorage.setItem('lang', lang.toString())
    i18n.changeLanguage(lang.toString())
      .then(() => {
        setLanguage(lang.toString());
      })
      .catch((error) => {
        console.error('Error changing language:', error);
      });
  }

Here is the example of code

const Configurations = () => {
  const { t } = useTranslation();
  const [language, setLanguage] = useState(localStorage.getItem('lang') || 'en');
  const [configurations, setConfigurations] = useState([]);

  // Simulated API call to fetch configurations
  useEffect(() => {
    // Simulated configurations data
    const data = [
      { id: 1, type: 'foo' },
      { id: 2, type: 'bar' },
    ];
    setConfigurations(data);
  }, [language]); // Trigger fetch data when language changes

  return (
    <div>
      <h1>{t('Welcome')}</h1> - static data is translated correctly without reload
      <ul>
        {configurations.map((config) => (
          <li key={config.id}>
            {config.id}: {t(`TYPE_${config.type.toUpperCase()}.text`)} - dynamic data from the backend and using in the method are not translated without reload.
          </li>
        ))}
      </ul>
    </div>
  );
};

export default Configurations;

NOTE: LanguageSwitch is a part of another Header component which is using in every component as a button in header

I am thinking of rendering app without reloading, but I am not sure how to achieve this

2

Answers


  1. You just need to use signal to have variable with updated state between components

    export const languageChanged = signal(false);
    

    and then update method

    function handleLangChange(lang: Key) {
      localStorage.setItem('lang', lang.toString());
      i18n.changeLanguage(lang.toString())
        .then(() => {
          setLanguage(lang.toString());
          languageChanged.value = !languageChanged;
        })
        .catch((error) => {
          console.error('Error changing language:', error);
        });
    }
    
    Login or Signup to reply.
  2. I think what you want is a ContextProvider

    The provider will look something like this

    export const LanguageContext = createContext<LanguageContextType>({
       language: localStorage.getItem('lang'),
       onChangeLanguage: () => localStorage.getItem('lang'),
    });
    
    export const LanguageProvider: React.FC<{ children?: React.ReactNode }> = ({children}) => {
       const [language, setLanguage] = useState(localStorage.getItem('lang'));
    
       function onChangeLanguage(l: string): void {
           setLanguage(l)
       }
    
       return (
           <LanguageContext.Provider value={{ language, onChangeLanguage }}>
               {children}
           </LanguageContext.Provider>
       );
    };
    

    Then wrap your App into the provider

    <LanguageProvider>
          <YourApp />
    </LanguageProvider>
    

    And within your Header you can call useContext

    const { language, onChangeLanguage } = useContext(LanguageContext);
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search