13

This is my code.

import React, { Suspense } from 'react';
import { useTranslation } from 'react-i18next';

function Page() {
  const { t, i18n } = useTranslation();

  const changeLanguage = lng => {
    i18n.changeLanguage(lng);
  };

  return (
    <div className="App">
      <div className="App-header">
        <button onClick={() => changeLanguage('de')}>de</button>
        <button onClick={() => changeLanguage('en')}>en</button>
      </div>
      <div>{t('test')}</div>
    </div>
  );
}

export default function App() {
  return (
    <Suspense fallback={<div>loading...</div>}>
      <Page />
    </Suspense>
  );
}

when I click on the de en button. I get this error. TypeError: i18n.changeLanguage is not a function.How to fix?

5 Answers5

22

Looks like you haven't configured i18next.

You will need to create a file i18n.js containing the following content:

import i18n from 'i18next';
import { initReactI18next } from 'react-i18next';

import Backend from 'i18next-xhr-backend';
import LanguageDetector from 'i18next-browser-languagedetector';


i18n
  .use(Backend)
  .use(LanguageDetector)
  .use(initReactI18next)
  .init({
    fallbackLng: 'en',
    debug: true,

    interpolation: {
      escapeValue: false,
    }
  });
export default i18n;

Then import it in your index.js:

import React, { Component } from "react";
import ReactDOM from "react-dom";
import App from './App';

import './i18n';

ReactDOM.render(
  <App />,
  document.getElementById("root")
);

source

Hamza El Aoutar
  • 5,292
  • 2
  • 17
  • 23
  • It seems I did everything right but it doesn't work.https://codesandbox.io/s/stupefied-snow-rsf86 –  Oct 01 '19 at 10:18
  • It is working, the function `changeLanguage ` is now available and you can call it. – Hamza El Aoutar Oct 01 '19 at 11:40
  • 1
    I do not understand.I showed my broken code.Are you saying that it works? can show on my code how should i use changeLanguage ? –  Oct 01 '19 at 12:29
  • I get a warning .i18next: languageChanged ru ..i18next::translator: missingKey ru translation test test . –  Oct 01 '19 at 14:15
  • 1
    That's because you need to add a translation file, or set up your backend so that it provides you with the translation, check this: https://react.i18next.com/guides/quick-start – Hamza El Aoutar Oct 01 '19 at 14:42
4

a) move changeLanguage like in the code above - but also import i18n from '../i18n'; or where you defined your i18n instance.

import i18n from 'i18n';

// define the function outside of component scope
const changeLanguage = (lng) => {
  i18n.changeLanguage(lng);
};

b) Or following steps:

import React, { Suspense } from 'react';
import { useTranslation } from 'react-i18next';

function Page() {
  const { t, i18n } = useTranslation();

  const toggle = lng => i18n.changeLanguage(lng); 
  if (this.props.event){

   return (
    <div className="App">
      <div className="App-header">
        <button onClick={() => toggle(this.props.event)}>de</button>
        <button onClick={() => toggle(this.props.event)}>en</button>
      </div>
      <div>{t('test')}</div>
    </div>
   );
  }
 }
Fausta
  • 72
  • 2
4

I had same error. Unfortunately the i18n documentation is not very good.

We need to create the i18n provider (I18nextProvider) and pass it an i18n object after calling the init function. Of course, we have to wrap our App in I18nextProvider

i18n.js

import i18n from 'i18next';
import { initReactI18next } from 'react-i18next';
import en from './en.json';
import de from './de.json';

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

export default i18n;

index.js

import React from 'react';
import { useTranslation, I18nextProvider } from 'react-i18next';
import i18n from './i18n';

function Page() {
  const { t, i18n } = useTranslation();

  const changeLanguage = lng => {
    i18n.changeLanguage(lng);
  };

  return (
    <div className="App">
      <div className="App-header">
        <button onClick={() => changeLanguage('de')}>de</button>
        <button onClick={() => changeLanguage('en')}>en</button>
      </div>
      <div>{t('test')}</div>
    </div>
  );
}

export default function App() {
  return (
    <I18nextProvider i18n={i18n}>
      <Page />
    </I18nextProvider>
  );
}
Igor Zvyagin
  • 454
  • 3
  • 13
  • 1
    i had the same error and found myself here. The solution for me: I accidentally commented out the import in index.js and it didn't work. Now it's working without the Provider and without the export default. just had to import the i18n.js for it's side-effects in index.js. (https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/import#import_a_module_for_its_side_effects_only) from the i18next docs: "You will only need to use the provider if you need to support multiple i18next instances " https://react.i18next.com/latest/i18nextprovider#when-to-use – TomerBu Aug 17 '22 at 07:26
0

It was not a config problem. What you need to do was to add

import "./util/i18n";

in your App.tsx and rebuild your project, ie run npm run start again.

Erik Man
  • 824
  • 4
  • 17
Taiwan No.1
  • 91
  • 1
  • 1
  • 7
-2

Try to use inside your onClick input events

() => changeLanguage('en').bind(this)

This could resolve your problem.