React i18next Backend-Path 在本地和生产环境中不同

IT技术 reactjs react-i18next
2021-05-12 21:12:33

我正在使用 react 应用程序react-i18next并加载翻译i18next-xhr-backend

i18n
  .use(Backend) 
  .use(initReactI18next) // passes i18n down to react-i18next
  .init({
    lng: "de",
    backend: {
      loadPath: '/static/locales/{{lng}}/{{ns}}.json'
    }        
  });

如果我在本地运行我的应用程序 http://localhost:3000/

并且翻译文件也很好地加载(src 位于public/statuc/locales/http://localhost:3000/static/locales/de/translation.json

我现在面临的问题是,在生产中,应用程序不是从 root 提供的,而是通过子文件夹提供构建的文件。因此,我改变了我的packages.json并添加了homepage

{
  "name": "myapp",
  "version": "0.1.0",
  "homepage": "/static/app/",
  ...
}

构建应用程序并将其部署到 prod 后,它仍然可以正确加载,但找不到翻译文件。

http://production.tld/static/app/index.html

react应用程序文件正确加载http://production.tld/static/app/static/js/main *.js

但翻译文件仍由http://production.tld/static/locales/de/translation.json获取,该文件不再可用(而不是http://production.tld/static/app/static/locales/de/ translation.json是正确的)

我可以通过更改 i18n 配置来修复它

 backend: {
     loadPath: '/static/app/static(locales/{{lng}}/{{ns}}.json'
 }  

然后它在生产中工作,但不再在本地工作:-/

我不确定如何避免这种情况?

3个回答

您可以loadPath作为函数传递

backend: {
  loadPath: () => {
    // check the domain
    const host = window.location.host;
    return (host === 'production.ltd' ? '/static/app':'') + '/static/app/static/locales/{{lng}}/{{ns}}.json';
  },
},

另一种解决方案是使用环境变量。只有条件不同并且没有函数,这个想法就像@felixmosh 的解决方案。

一个使用create-react-app的例子,在这里你可以使用环境变量 'NODE_ENV' 作为条件。

i18n.use(XHR)
.use(initReactI18next)
.init({
    backend: {
        loadPath:
            process.env.NODE_ENV !== "production"
                ? `./locales/{{lng}}/{{ns}}.json`
                : ` /static/app/static/locales/{{lng}}/{{ns}}.json`,
    },
    lng: "de",
    fallbackLng: "de",
    load: "languageOnly",
    debug: true,
    react: {
        transSupportBasicHtmlNodes: true,
        transKeepBasicHtmlNodesFor: ["br", "strong", "i", "sub", "sup", "li"],
    },
});

这里是 create-react-app https://create-react-app.dev/docs/adding-custom-environment-variables的文档

这是一个后续问题,可能值得提出自己的顶级问题:

看来,如果您的语言环境目录的名称中有破折号(例如locales/en-us/translation.json),那么事情就行不通了。我们应该如何解决这个问题?我偶然发现了这个答案,因为我想也许我可以做一些类似的事情:

loadPath: (lng, ns) => { return `/locales/{{lng.replace(/-/g,'')/{{ns}}.json` }

但是在我最初的测试中,这不起作用。