React i18next Backend-Path different in local and production environment

青春壹個敷衍的年華 提交于 2021-02-10 06:56:12

问题


I'm using a react app with react-i18next and loading the translation with i18next-xhr-backend

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

If I run it locally my app is served over http://localhost:3000/

and the translation file is also loading nicely (src is located in public/statuc/locales/ ) http://localhost:3000/static/locales/de/translation.json

I'm now facing the issue that in production the app is not served from root, instead the builded files are served over a subfolder. Because of that I changed my packages.json and added homepage

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

After building the application and deploying it on prod, it still loads correctly, but the translation files are not found.

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

react app files are loaded correctly http://production.tld/static/app/static/js/main*.js

but the translation file is still fetched by http://production.tld/static/locales/de/translation.json which is not available anymore (instead http://production.tld/static/app/static/locales/de/translation.json would be correct)

I could fix it by changing the i18n config

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

then it works in production, but not locally anymore :-/

I'm not sure how to avoid this situation ?


回答1:


You can pass loadPath as function.

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



回答2:


Another solution would be to work with environment variables. Only the condition would be different and without a function, the idea is like @felixmosh's solution.

An example with create-react-app, here you can use the environment variable 'NODE_ENV' for the condition.

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"],
    },
});

Here the documentation of create-react-app https://create-react-app.dev/docs/adding-custom-environment-variables




回答3:


Here's a follow-along question that may deserve its own top-level question:

it appears that if your locales directories have dashes in the name (e.g. locales/en-us/translation.json), then things don't work. How are we supposed to get around that? I stumbled on this answer because I thought perhaps I could do something along the lines of:

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

But during my initial testing, that didn't work.



来源:https://stackoverflow.com/questions/59774175/react-i18next-backend-path-different-in-local-and-production-environment

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!