React i18next 后端路径在本地和生产环境中不同
React i18next Backend-Path different in local and production environment
我正在使用带有 react-i18next
的 React 应用程序并使用 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
我现在面临的问题是,在生产环境中,应用程序不是从根目录提供的,而是通过子文件夹提供构建的文件。因此,我更改了 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 which is not available anymore (instead http://production.tld/static/app/static/locales/de/translation.json 提取是正确的)
我可以通过更改 i18n 配置来修复它
backend: {
loadPath: '/static/app/static(locales/{{lng}}/{{ns}}.json'
}
然后它可以在生产中工作,但不再在本地工作了:-/
我不确定如何避免这种情况?
您可以将 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` }
但在我最初的测试中,这没有用。
我正在使用带有 react-i18next
的 React 应用程序并使用 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
我现在面临的问题是,在生产环境中,应用程序不是从根目录提供的,而是通过子文件夹提供构建的文件。因此,我更改了 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 which is not available anymore (instead http://production.tld/static/app/static/locales/de/translation.json 提取是正确的)
我可以通过更改 i18n 配置来修复它
backend: {
loadPath: '/static/app/static(locales/{{lng}}/{{ns}}.json'
}
然后它可以在生产中工作,但不再在本地工作了:-/
我不确定如何避免这种情况?
您可以将 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` }
但在我最初的测试中,这没有用。