---
title: "How do I change the language in react-i18next?"
description: "Call `i18n.changeLanguage('de')` on the `i18n` object that `useTranslation` returns. It returns a promise and every component using the hook re-renders. Persist the choice with i18next-browser-languagedetector or your own storage."
category: react
date: 2026-10-09
canonical: https://localizely.com/i18n-questions/react/how-do-i-change-the-language-in-react-i18next/
---

# How do I change the language in react-i18next?

Take the instance from the hook and call `changeLanguage`:

```jsx
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`](https://www.i18next.com/overview/api#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](https://github.com/i18next/i18next-browser-languageDetector) does both detection and persistence:

```javascript
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?](/i18n-questions/react/where-to-save-preferred-language-in-react-app/) covers that trade-off.

i18next does not touch the DOM, so set the [`lang`](https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Global_attributes/lang) and [`dir`](https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Global_attributes/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:

```javascript
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?](/i18n-questions/react/how-to-add-a-language-switcher-in-a-react-app/).

Source: https://localizely.com/i18n-questions/react/how-do-i-change-the-language-in-react-i18next/
