反应i18next和改变语言的正确方法

时间:2016-03-01 16:47:57

标签: javascript reactjs translation i18next

我正在使用React,i18nexti18next-browser-languagedetector开发多语言应用程序。

我通过以下方式初始化i18next:

i18n
  .use(LanguageDetector)
  .init({
    lng: localStorage.getItem(I18N_LANGUAGE) || "pt",
    fallbackLng: "pt",
    resources: {
      en: stringsEn,
      pt: stringsPt
    },
    detection: {
      order: ["localStorage", "navigator"],
      lookupQuerystring: "lng",
      lookupLocalStorage: I18N_LANGUAGE,
      caches: ["localStorage"]
    }
  });

export default i18n;

我已经实现了一个语言选择器,只是将localStorage中的值更改为用户选择的值。

这是正确的做法吗?

我问,因为虽然这有效,但我觉得我是在欺骗"通过设置localStorage.getItem(I18N_LANGUAGE) || "pt"并且我没有使用语言检测。

5 个答案:

答案 0 :(得分:4)

根据documentation,您不应该自己指定语言:

import i18next from 'i18next';
import LngDetector from 'i18next-browser-languagedetector';

i18next
  .use(LngDetector)
  .init({
    detection: options
  });

根据i18next中的this piece of source,它确实使用了插件的检测功能:

if (!lng && this.services.languageDetector) lng = this.services.languageDetector.detect();

  

这是正确的做法吗?

所以,不,它不是。让插件做它的工作。 :)

答案 1 :(得分:0)

@firstdoit:

关于自动浏览器语言检测的良好答案。但是,您不认为这是一种更好的方法,可以同时使用自动和手动配置。

例如,如果将浏览器设置为英语,则可以根据文档建议自动方法。如果用户将页面语言从英语更改为法语,这不会影响浏览器语言,因此只能将网站保留为英文,因为配置设置为自动检测浏览器语言。

反过来,我将优先考虑当前的页面语言:

  • 通过参数传递(/george.php?lang=fr或/fr_FR/george.php)

这将作为道具传递给我的代码作为一个优先级如下

  • var lang = this.props.lang || this.services.languageDetector.detect() || “恩”;

你有什么看法?

答案 2 :(得分:0)

我认为你很亲密。您最初可以使用后备语言设置i18n。然后在加载localstorage或localforage或任何存储的已保存语言信息后,请致电i18nInstance.changeLanguage(lng)

答案 3 :(得分:0)

希望这对以后的人有所帮助。该文档并没有完全为您提供有关如何设置检测的全部信息,然后我发现一个closed Github issue,那里有几个人在问一个合理的问题,维护人员的回答有些粗鲁,但也碰巧提供应该在文档中的link-但在Github注释之外的地方绝对没有引用。该示例通过对当前文档指出的内容进行了一些小的调整来解决了我的问题。

然后,我可以使用https:www.domain.com?lng=es在我的网址中进行语言检测,并且可以使用浏览器扩展程序来更改浏览器语言。

这里有我的i18n.ts工作文件:

import i18n from 'i18next'
import LanguageDetector from 'i18next-browser-languagedetector'
import { initReactI18next } from 'react-i18next'
import XHR from "i18next-http-backend" // <---- add this

import commonDe from './locales/de/common.json'
import commonEn from './locales/en/common.json'
import commonEs from './locales/es/common.json'
import commonFr from './locales/fr/common.json'

const resources = {
  de: { common: commonDe },
  en: { common: commonEn },
  es: { common: commonEs },
  fr: { common: commonFr }
}

const options = {
  order: ['querystring', 'navigator'],
  lookupQuerystring: 'lng'
}

i18n
  .use(XHR) // <---- add this
  .use(LanguageDetector)
  .use(initReactI18next)
  .init({
    // lng: 'en' // <--- turn off for detection to work
    detection: options,
    resources,
    ns: ['common'],
    defaultNS: 'common',
    fallbackLng: 'en',
    supportedLngs: ['de', 'en', 'es', 'fr'],
    interpolation: {
      escapeValue: false,
    },
    debug: false,
  })

export default i18n

(额外的帮助-如果有人在此部分卡住)

我正在一个Next.js项目中,并且上面的文件像这样被加载到project-root/pages/_app.tsx文件中:

import React from 'react'
import { AppProps } from 'next/app'
import '../i18n/i18n'

import '../public/styles.css'

const TacoFridayApp = ({ Component, pageProps}: AppProps): JSX.Element => {
  
  return <Component {...pageProps} />
}

export default TacoFridayApp

答案 4 :(得分:0)

为此浪费了很多时间,但幸运的是 taco_friday 用他的 answer 挽救了我的一天。在这里加上我的两分钱:

我基本上尝试将数据从我的 localStorage 加载到 i18-next。有一个名为 i18next-localstorage-backend 的插件应该可以促进这一点,但我没有设法让它运行。

但是在 taco-friday 分享的内容中找到灵感后,我可以相应地调整我的 i18n.ts

import i18n from 'i18next'
import LanguageDetector from 'i18next-browser-languagedetector'
import { initReactI18next } from 'react-i18next'
import BrowserStorageManager from './services/browserStorageManager'
import loadTranslations from './services/loadTranslations'

const service = new BrowserStorageManager()
loadTranslations()

const resources = {
    'de-CH': service.getItem<any>('de-CH')?.value,
}

i18n.use(LanguageDetector)
    .use(initReactI18next)
    .init({
        debug: false,
        fallbackLng: 'deCH',
        resources,
        interpolation: {
            escapeValue: false, // not needed for react!!
        },
    }) 

browserStorageManager.ts 的内容是:

import logSymbols from 'log-symbols'

class BrowserStorageManager {
    public setItem(key: string, value: any): void {
        localStorage.setItem(key, JSON.stringify({ value }))
    }

    public getItem<T>(key: string): T | null {
        const data: string | null = localStorage.getItem(key)
        if (data !== null) {
            return JSON.parse(data)
        }
        console.log(logSymbols.error, ` ${key}-key is empty - aborting ...`)
        return null
    }
}

export default BrowserStorageManager

最后一个resourceBundle在我的localStorage中的结构如下:

{
    value:{
        translation:{
            key: "value",
            ....
        }
    }
} 

translation 是默认命名空间,因此无需在 .init

中定义它