我可以使用 i18next-browser-languageDetector 检测首次检测到语言的时间吗?

Can I detect when a language is detected for the first time using i18next-browser-languageDetector?

我有一个反应应用程序,我已经翻译成多种语言,并且还包含一些日期格式化功能。例如,我想允许用户在 12 小时制和 24 小时制之间切换,但是当切换到德语时,会自动将该选项更改为 24 小时制(因为德国通常不使用 12 小时制)。

我仍然希望这个选项能够被用户更改,我也不希望每次重新加载页面时都将其重置为 24 小时。

我正在使用 i18nexti18next-browser-languageDetector 来检测浏览器语言,目前我有一个绑定到 i18next 的事件,用于当用户手动更改语言时,为了按语言设置这些默认设置,这非常有效:

i18n.on('languageChanged', lang => {
  // Language specific options
  if (lang === 'de') {
    store.setTimeFormat('24h');
  }
  if (lang === 'en') {
    store.setTimeFormat('12h');
  }
});

现在,唯一的问题是首次加载应用程序时不会触发此功能,即当浏览器检测器首次检测到用户的语言时。

如何确定 i18next-browser-languageDetector 最初检测语言的时间,即不是从本地存储加载,而是 lng=de 的查询字符串会触发它,以便我可以设置这些设置?

我设法解决了这个问题,方法是首先检查本地存储中是否保存了一种语言,将其添加到 i18next 选项对象,然后我可以稍后检查它以设置默认值。

import i18n from 'i18next';
import { initReactI18next } from 'react-i18next';
import LanguageDetector from 'i18next-browser-languagedetector';
import Backend from 'i18next-http-backend';

// Check the localstorage before i18next can
const storedLang = localStorage.getItem('i18nextLng');

i18n
  .use(LanguageDetector)
  .use(Backend)
  .use(initReactI18next)
  .init({
    fallbackLng: 'en',
    interpolation: {
      escapeValue: false,
    },
    backend: {
      loadPath: '/i18n/{{lng}}/{{ns}}.json',
    },
    storedLang, // Add it here
  });

export default i18n;

然后在我的组件中,我可以将以下内容放入函数中:

import { useTranslation } from 'react-i18next';
import { mySettingsStore } from 'stores';

const setDefaults = (lang, store) => {
  // Language specific options
  if (lang === 'de') {
    store.setTimeFormat('24h');
  }
  if (lang === 'en') {
    store.setTimeFormat('12h');
  }
  // etc...
};

const Component = () => {
  const store = mySettingsStore(); // zustand store
  const { i18n } = useTranslation();

  // If localstorage was empty: no language set
  if (!i18n.options.storedLang) {
    setDefaults(i18n.language, store);
    i18n.options.storedLang = i18n.language;
  }

  // Language changed manually
  i18n.on('languageChanged', lang => {
    setDefaults(lang, store);
  });

  return (...);
};

export default Component;

但是,如果语言是通过查询字符串设置的,则此方法不会更新选项,例如https://my.app?lng=de,如果本地存储中已经设置了语言。这可以通过以相同方式检查查询字符串参数来补救,但如果使用更多选项,维护起来很快就会变得麻烦,例如会话存储、cookie 等

对于第一个检测到的语言,您可能想尝试 onInitialized event。 然后根据需要勾选i18next.language or i18next.languages

编辑:从 v21.0.0 开始还有 i18next.resolvedLanguage

非常感谢我在第一次渲染访问时遇到了问题,因为 i18n.language 是“es-ES”或“en-EN”并将其保存在本地存储中... 我用 switch case 语句解决了它:

if (!i18n.options.storedLang) {
    switch(i18n.language){
       case "es-ES":
         setDefaults("es", store)
         i18n.options.storedLang = "es"
         //and this for other uses, for example vars to use in <ReactCountryFlag countryCode={"GB"} svg />
         break
      case: "en-EN":
         setDefault("en",store)
         i18n.options.storedLang = "es"
         //and this for other uses, for example vars to use in <ReactCountryFlag countryCode={"ES"} svg />
         break
      default: break
  }
}