【问题标题】:react-i18next: How to sync Browser and Express LanguageDetector?react-i18next:如何同步浏览器和 Express LanguageDetector?
【发布时间】:2018-07-12 15:30:45
【问题描述】:

在我的服务器路由中,我做了这样的事情(注意:i18next-express-middleware 已经在管道中,服务器端渲染运行良好):

export default function (req, res) {
  const lng = req.language.toUpperCase()

  console.log(lng) // Always display [EN]

  MyModel
    .findOne(query, { fieldEN: 1, fieldFR: 1 })
    .exec()
    .then(res => reply(res[`field${lng}`]))
    .catch(err => handle(err))
}

所以我尝试根据用户选择的语言返回正确版本的字段。

但是无论在浏览器端选择什么语言,在服务器端它总是设置为默认值,EN。

有没有办法让服务器端LanguageDetector知道浏览器端当前的语言?

这是我的客户i18n init

import i18n from 'i18next'
import Backend from 'i18next-xhr-backend'
import LanguageDetector from 'i18next-browser-languagedetector'

i18n
  .use(Backend)
  .use(LanguageDetector)
  .init({
    whitelist: ['en', 'fr'],
    fallbackLng: 'en',
    preload: ['en', 'fr'],

    // debug: true,

    interpolation: {
      escapeValue: false
    },

    ns: ['home', 'channel', 'common'],
    defaultNS: 'home',

    backend: {
      loadPath: '/locales/{{lng}}/{{ns}}.json'
    },

    react: {
      wait: true,
      bindI18n: 'languageChanged loaded',
      bindStore: 'added removed',
      nsMode: 'default'
    }
  })

export default i18n

这是我的服务器i18n init:

import i18n from 'i18next'
import Backend from 'i18next-node-fs-backend'
import { LanguageDetector } from 'i18next-express-middleware'

i18n
  .use(Backend)
  .use(LanguageDetector)
  .init({
    whitelist: ['en', 'fr'],
    fallbackLng: 'en',
    preload: ['en', 'fr'],

    // debug: true,

    interpolation: {
      escapeValue: false
    },

    ns: ['home', 'channel', 'common'],
    defaultNS: 'home',

    backend: {
      loadPath: `${__dirname}/public/locales/{{lng}}/{{ns}}.json`,
      jsonIndent: 2
    }
  })

export default i18n

【问题讨论】:

    标签: javascript i18next react-i18next


    【解决方案1】:

    事实上,问题不是我的i18n init 配置。

    在进行 SSR 时,我们必须记住,我们有两个不同的 i18next 实例,一个在服务器上运行,另一个在浏览器中。

    在您在服务器上创建的实例上,将根据您的配置检测当前语言。然后你将在服务器上渲染,如下所示:

    <I18nextProvider i18n={i18n_}>
        <StaticRouter location={req.url} context={{}}>
            <Route component={App} />
        </StaticRouter>
    </I18nextProvider>
    

    但是当您的浏览器应用启动时,它会使用从自己的配置中检测到的任何语言作为当前语言。

    首先要做的是使用来自服务器的i18n 信息初始化浏览器应用程序。所以在构建标记服务器端时,只需在窗口对象上创建两个属性来保存initialStoreinitialLanguage(注意:我使用hbs):

    window.__initialI18nStore__ = {{json initialI18nStore}}
    window.__initialLanguage__ = {{json initialLanguage}}
    

    然后在浏览器应用程序上,您将呈现如下内容:

    <I18nextProvider
        i18n={i18n}
        initialI18nStore={window.__initialI18nStore__}
        initialLanguage={window.__initialLanguage__}
      >
          <BrowserRouter>
              <Route component={App} />
          </BrowserRouter>
    </I18nextProvider>
    

    因此浏览器应用程序将使用相同的语言并从服务器存储。

    但是你还没有完成。使用相同语言初始化浏览器应用程序不会链接 i18next 的两个实例,如果您更改浏览器上的语言并按刷新,您仍将拥有来自服务器的先前语言,因为 i18next 的服务器实例是不知道您所做的更改。

    解决所有这些问题的是caches 设置,用于LanguageDetector。您必须在配置、浏览器和服务器上都指定它:

    detection: {
      caches: [..., 'cookie', ...]
    }
    

    例如当你使用cookie时,那么每次浏览器更改语言时,cookie都会更新,然后在服务器端,语言检测器的行为会发生改变,它会首先尝试获取cookie 中的当前语言,并将其设置为req.i18n.language。因此,两个实例现在将通过该 cookie 同步。

    也许你应该阅读react-i18next github repo 上的示例razzle-ssr,并查看这些链接以了解有关 LanguageDetector 选项的更多信息: for browserfor node

    【讨论】:

      【解决方案2】:

      github上的猜测问题https://github.com/i18next/react-i18next/issues/471给出了答案...

      而且没有stackoverflow...我不会再在这里写完整的回复;)

      使用粘贴在这里的代码它将/应该工作...但是阅读上面的问题 - 有一个缺失的部分 - 创建一个新实例(除了进入 req 的那个)并在那里设置语言 -> 如果依赖会导致不同步关于检测而不是设置 initialLanguage 正确...

      【讨论】:

      • 是的,我先在这里创建了questoin,然后我就去了github,因为这里没有答案。
      • @acmoune 不是因为你...在这里问也没关系 - 只是 stackoverflow 过度活跃的版主倾向于删除仅链接到另一个页面的回复...
      猜你喜欢
      • 2016-01-21
      • 2019-01-23
      • 1970-01-01
      • 2023-04-10
      • 2021-04-04
      • 2018-06-27
      • 1970-01-01
      • 1970-01-01
      • 2017-04-18
      相关资源
      最近更新 更多