i18next / react-i18next

Internationalization for react done right. Using the i18next i18n ecosystem.
https://react.i18next.com
MIT License
9.34k stars 1.03k forks source link

How to change language on the fly #700

Closed ShintaroNippon closed 5 years ago

ShintaroNippon commented 5 years ago

Hello, I'm using react with Next js and i have this configuration in i18n

import i18n from "i18next";
import LanguageDetector from 'i18next-browser-languagedetector';

import en from '../locales/en/landing.json';
import pt from '../locales/pt/landing.json';

const i18nInstance = i18n.createInstance();

i18nInstance
  .use(LanguageDetector)
  .init({
    fallbackLng: 'en',
    interpolation: {
      escapeValue: false
    },
    react: {
      wait: false,
      nsMode: 'default'
    },
    resources: {
      en: { translation: en },
      fr: { translation: pt }
    }
  }, err => {
    if (err) {
      console.error('Error loading translation files', err); // eslint-disable-line
      return;
    }
  });

export default i18nInstance;

then in my component i have:

import I18nInstance  from '../../lang/i18n';

  changeLanguage = e => {
    //i18n.setLng('pt')
    console.log(I18nInstance.language)
    I18nInstance.changeLanguage(I18nInstance.language === "pt" ? "en" : "pt");
    //location.reload();
  };

<div 
                  onClick={this.loginAccess}>
                <Fab
                  variant="extended"
                  size="medium"
                  color="primary"
                >
                {I18nInstance.t('tranlsation:login')}
                </Fab>
                </div>

but when I click in change language nonerror happens but the language doesn't change...

Does any help, please?

Thanks in advance

jamuhl commented 5 years ago

There is nothing triggering a rerender on language change -> use either withNamespaces (HOC) or the NamespacesConsumer (render prop) https://react.i18next.com/components/withnamespaces to bind a rerender onLanguageChange.

Also have a look at https://github.com/isaachinman/next-i18next for best practices using next.js with react-i18next

ShintaroNippon commented 5 years ago

I understand your point but I'm using like this

import React, { Component } from "react";
import { withI18n } from "react-i18next";

class MyComponent extends Component {
  render() {
    const { t } = this.props;

    return <h2>{t('Welcome to React')}</h2>;
  }
}
export default withI18n()(MyComponent);
ShintaroNippon commented 5 years ago

By the way, I'm using next js integration... I 'm not sure if server-side rendering as something to it thanks

jamuhl commented 5 years ago

did you read the warning of withI18n?!? https://react.i18next.com/components/withi18n

ShintaroNippon commented 5 years ago

ok ok. I will try with namespaces... Thanks for all. I will give feedback.

ShintaroNippon commented 5 years ago

I'm trying to implement with namespaces... but the change only happens if I change page... can I share with you my boilerplate and can you verify whats happen? it will really help me a lot... I will give you a feedback latter... can you help me on this.... sorry bother you, I don't want to abuse... thanks

jamuhl commented 5 years ago

i really suggest having a look at https://github.com/isaachinman/next-i18next as getting this right is not as simple as it seems. Even more you will get the needed support there.

I won't be able to help you with this...this just takes to much time - and i already gave enough of my lifetime to OSS.

If not getting anywhere - as a last resort there might be the option for payed support - but i really suggest giving next-i18next a try.

jamuhl commented 5 years ago

I hope you can understand that i can't support every project in my free time.

ShintaroNippon commented 5 years ago

ok, I understand... sorry for bothering... I will try thanks

jamuhl commented 5 years ago

please start adding changes related to the v9 version to the v9.x.x branch (master will be now for the upcoming v10 hooks)

--> https://github.com/i18next/react-i18next/tree/v9.x.x

ekiziltas commented 4 years ago

I think, you are looking for this:

import React, {useEffect, useRef, useState} from 'react';
import { IconButton} from '@material-ui/core';
import i18n from "i18next";
import {initReactI18next, useTranslation} from 'react-i18next';
.....
function switchLang(lang) {
        i18n.use(initReactI18next) // passes i18n down to react-i18next
            .init({lng: lang});
    }
.....
return (
<IconButton onClick={() => {switchLang("en")}}><IconFlagUS/></IconButton>
)
jamuhl commented 4 years ago

@ekiziltas nope...that's totally wrong...you can not init i18next on a Button...

just:

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

  return (
<IconButton onClick={() => {i18n.changeLanguage("en")}}><IconFlagUS/></IconButton>
)
}

every HOC, hook, render prop gives you the underlaying i18n instance where you can call changeLanguage

ekiziltas commented 4 years ago

@ekiziltas nope...that's totally wrong...you can not init i18next on a Button...

just:

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

  return (
<IconButton onClick={() => {i18n.changeLanguage("en")}}><IconFlagUS/></IconButton>
)
}

every HOC, hook, render prop gives you the underlaying i18n instance where you can call changeLanguage

@jamuhl I appreciate you reply, but if you say it's totally wrong then I would like to tell the truth about i18next. That is; YES you can init i18next on a Button, even IconButton. It works for ages :)

PS: Please don't insult anyone when you are trying to express yourself.

jamuhl commented 4 years ago

@ekiziltas it works !== it's the correct thing to do...if it works for you...ok...but adding it here as correct solution is just WRONG...leading people using the i18next API in the wrong way...

PS: I don't just express myself...I express the intention of the i18next API I created and maintain over 8 years now...

anyway...merry xmax