Реагируй i18следующий и правильный способ смены языка
Я разрабатываю мультиязычное приложение с использованием 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"
и что я не использую определение языка, как я должен.
5 ответов
Согласно документации, вам не нужно указывать язык самостоятельно:
import i18next from 'i18next';
import LngDetector from 'i18next-browser-languagedetector';
i18next
.use(LngDetector)
.init({
detection: options
});
И согласно этому куску источника в i18next
, он действительно использует возможности обнаружения плагина:
if (!lng && this.services.languageDetector) lng = this.services.languageDetector.detect();
Это правильный способ сделать это?
Так что нет, это не так. Позвольте плагину делать свою работу.:)
Надеюсь, это поможет кому-то в будущем. Документация точно не дает вам полной картины того, как настроить обнаружение, а затем я обнаружил закрытую проблему Github, в которой несколько человек задавали разумный вопрос, а сопровождающие были грубо в своих ответах, но также предоставили ссылка, которая должна была быть в документации, но не упоминается абсолютно нигде за пределами этого комментария 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
Я думаю, что вы очень близки. Вы можете просто установить i18n
с запасным языком изначально. А затем после загрузки сохраненной языковой информации для локального хранилища или локального хранилища или любого другого хранилища, позвоните i18nInstance.changeLanguage(lng)
,
@firstdoit:
Хороший ответ в отношении автоматического определения языка браузера. Однако вы не думаете, что это лучший подход, когда пользователю предоставляется автоматическая и ручная конфигурация.
Например, если у вас установлен браузер на английский, это подойдет для автоматического подхода, который вы предлагаете, основываясь на документации. Если пользователь меняет язык страницы с английского на французский, это не влияет на язык браузера, поэтому сайт остается только на английском, потому что настройки настроены на автоматическое определение языка браузера.
Я, в свою очередь, буду отдавать приоритет текущему языку страницы:
- Либо передается через параметры (/george.php?lang=fr или /fr_FR/george.php)
Это будет передано как реквизиты для моего кода, как правило, как следует
- var lang = this.props.lang || this.services.languageDetector.detect () || "Ан";
Что вы берете?
тратил на это много времени, но, к счастью, спас мне день своим taco_friday . Добавляем сюда мои два цента:
Я в основном пытался загрузить данные из моего локального хранилища в i18-next. Есть плагин под названием i18next-localstorage-backend, который должен облегчить это, но мне не удалось его запустить.
Но найдя вдохновение в том, чем поделились тако-пятница, я смог адаптировать свой
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