Localizely logo
  • Home
  • Getting started
  • How it works
  • Pricing
  • FAQ
Sign up

I18n questions · React

How do I change the language in react-i18next? 

Take the instance from the hook and call changeLanguage:

import { useTranslation } from 'react-i18next';

function LanguageSelect() {
  const { i18n } = useTranslation();

  return (
    <select
      value={i18n.resolvedLanguage}
      onChange={(e) => i18n.changeLanguage(e.target.value)}
    >
      <option value="en">English</option>
      <option value="de">Deutsch</option>
    </select>
  );
}

changeLanguage returns a promise that settles once the resources for that language are loaded, which matters when a backend plugin fetches them. Every component that uses useTranslation, Trans or withTranslation re-renders on its own, because react-i18next subscribes to the languageChanged event (the react.bindI18n option, default 'languageChanged'). No state, context or reload is needed; if text only updates after a refresh, it was read from t outside a component, for example into a module-level constant.

Two properties look alike: i18n.language is whatever was set or detected, such as en-US, while i18n.resolvedLanguage (i18next 21 and later) is the language actually used for lookups after supportedLngs, load and the fallback chain are applied. Use resolvedLanguage for the selected value of a switcher.

The choice is gone after a reload unless you store it. i18next-browser-languagedetector does both detection and persistence:

import i18n from 'i18next';
import LanguageDetector from 'i18next-browser-languagedetector';
import { initReactI18next } from 'react-i18next';

i18n
  .use(LanguageDetector)
  .use(initReactI18next)
  .init({
    supportedLngs: ['en', 'de'],
    fallbackLng: 'en',
    detection: {
      order: ['localStorage', 'navigator'],
      caches: ['localStorage'],
      lookupLocalStorage: 'i18nextLng',
    },
    interpolation: { escapeValue: false },
  });

Each changeLanguage call writes the code to every store listed in caches (localStorage by default, under the lookupLocalStorage key i18nextLng; cookie is the other option), and the next start reads it back in the configured order. Do not set lng in init next to the detector, because lng overrides detection. If the preference lives on your server, skip the detector and call i18n.changeLanguage(user.language) once after the profile is loaded; Where to save preferred language in React app? covers that trade-off.

i18next does not touch the DOM, so set the lang and dir attributes of <html> yourself; screen readers, hyphenation, CSS :lang() and right-to-left layout depend on them. i18n.dir(lng) returns 'rtl' or 'ltr'. Register the listener above the init call in the setup module, because init emits the event for the initial language as well:

i18n.on('languageChanged', (lng) => {
  document.documentElement.lang = lng;
  document.documentElement.dir = i18n.dir(lng);
});

For the react-intl version of the switcher UI see How to add a language switcher in a React app?.

Published Oct 9, 2026 · Markdown version

Related React internationalization questions:

React internationalization tutorial:

Learn about internationalization in React
Localizely logo
About
Free tools
Boring stuff
  • Privacy Policy
  • Terms of Service
  • Cookie Policy
Newsletter
Copyrights 2026 © Localizely