React i18next 和更改语言的正确方法
React i18next and correct way of changing language
我正在使用 React、i18next
和 i18next-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"
我是 "cheating",而且我没有按应有的方式使用语言检测。
根据 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();
Is this the correct way of doing it?
所以,不,不是。让插件完成它的工作。 :)
@firstdoit:
关于自动浏览器语言检测的好答案。但是,您不认为,让用户同时使用自动和手动配置是一种更好的方法。
例如,如果将浏览器设置为英语,这对于您根据文档建议的自动方法来说是可以的。如果用户将页面语言从英语更改为法语,这不会影响浏览器语言,因此只保留英语站点,因为配置设置为自动检测浏览器语言。
我依次优先当前页面语言:
- 通过参数传递 (/george.php?lang=fr 或 /fr_FR/george.php)
这将作为道具传递给我的代码,如下所示
- var lang = this.props.lang || this.services.languageDetector.detect() || "en";
你怎么看?
我觉得你很亲近。您最初可以使用后备语言设置 i18n
。然后在为 localstorage 或 localforage 或任何存储加载保存的语言信息后,调用 i18nInstance.changeLanguage(lng)
.
希望这对以后的人有所帮助。该文档并没有为您提供有关如何设置检测的完整信息,然后我发现了一个 closed Github issue where several people were asking a reasonable question, and the maintainers were kinda rude in their responses but also happened to supply a link 应该在文档中的内容 - 但绝对没有在 Github 之外的任何地方引用评论。该示例通过对当前文档说明的内容进行一些小的调整,解决了我的问题。
然后我能够在我的 url 中使用 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
为此浪费了很多时间,但幸运的是 taco_friday saved my day with his 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
最后在我的localStorage中一个resourceBundle的结构如下:
{
value:{
translation:{
key: "value",
....
}
}
}
translation
是默认命名空间,因此无需在 .init
中定义它
我正在使用 React、i18next
和 i18next-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"
我是 "cheating",而且我没有按应有的方式使用语言检测。
根据 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();
Is this the correct way of doing it?
所以,不,不是。让插件完成它的工作。 :)
@firstdoit:
关于自动浏览器语言检测的好答案。但是,您不认为,让用户同时使用自动和手动配置是一种更好的方法。
例如,如果将浏览器设置为英语,这对于您根据文档建议的自动方法来说是可以的。如果用户将页面语言从英语更改为法语,这不会影响浏览器语言,因此只保留英语站点,因为配置设置为自动检测浏览器语言。
我依次优先当前页面语言:
- 通过参数传递 (/george.php?lang=fr 或 /fr_FR/george.php)
这将作为道具传递给我的代码,如下所示
- var lang = this.props.lang || this.services.languageDetector.detect() || "en";
你怎么看?
我觉得你很亲近。您最初可以使用后备语言设置 i18n
。然后在为 localstorage 或 localforage 或任何存储加载保存的语言信息后,调用 i18nInstance.changeLanguage(lng)
.
希望这对以后的人有所帮助。该文档并没有为您提供有关如何设置检测的完整信息,然后我发现了一个 closed Github issue where several people were asking a reasonable question, and the maintainers were kinda rude in their responses but also happened to supply a link 应该在文档中的内容 - 但绝对没有在 Github 之外的任何地方引用评论。该示例通过对当前文档说明的内容进行一些小的调整,解决了我的问题。
然后我能够在我的 url 中使用 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
为此浪费了很多时间,但幸运的是 taco_friday saved my day with his 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
最后在我的localStorage中一个resourceBundle的结构如下:
{
value:{
translation:{
key: "value",
....
}
}
}
translation
是默认命名空间,因此无需在 .init