前端国际化文件拆分

前端对于静态显示的内容如标题,弹框文本等,有时需要做国际化。随着国际化的内容增多,单个文件下进行维护就显得不怎么方便。这时我们需要按照功能等拆分为多个JSON或者JS文件,这样维护性上便会提高。

拆分后的JSON文件我们希望是这样
image

如何实现呢,继续看。

环境

这里贴下,我实现时的环境

  • React v16.4.2
  • React-intl v^2.7.2
  • Webpack v4.17.1

安装 merge-jsons-webpack-plugin插件

1
yarn add  merge-jsons-webpack-plugin --dev

Webpack配置

1
2
3
4
5
6
7
8
9
10
const MergeJsonWebpackPlugin = require('merge-jsons-webpack-plugin');

new MergeJsonWebpackPlugin({
output: {
groupBy: [
{pattern: "./src/main/webapp/i18n/en/*.json", fileName: "./i18n/en.json"}
// jhipster-needle-i18n-language-webpack - JHipster will add/remove languages in this array
]
}
})

APP中加载

以下为react程序加载code,angular,vue等类似。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
export const getLocale = lang => axios.get(`/i18n/${lang}.json`);


setupAxiosInterceptors(() => (location.href = '/#/login'));
const rootEl = document.getElementById('root');
const messages = {};
const locale = 'en';
const render = () =>
ReactDOM.render(
<AppContainer>
<IntlProvider locale={locale} messages={messages[locale]}>
{
// @ts-ignore
<Provider store={store}>
<AppComponent />
</Provider>
}
</IntlProvider>
</AppContainer>,
rootEl
);

getLocale(locale).then(res => {
messages[locale] = res.data;
render();
});

原理

原理简单,但还是啰嗦下,Webpack作为构建工具,将N个JSON文件合并为一个,移动到特定的路径下,而我们WEB请求了合并后的文件,从而对外是一个文件,而在维护编写层面却可以是多个。中间的构建合并交给了Webpack解决。

合并后的文件缓存问题

都知道,前端其实会有缓存机制,对于不变的前端资源,比如图片视频,国际化等,假如我们增加了部分翻译,但是用户访问的还是缓存化的文件,怎么办呢。这时我们就要想办法,让浏览器不使用缓存文件而走新的。

解决办法

请求增加时间戳参数,利用增加参数改变了请求地址,自然就不会走缓存了。
效果即是,前端构建打包新版,用户就会走新的i18n文件,否则走缓存。

1
2
3
4
5
6
7
export const getLocale = lang =>
axios.get(`/i18n/${lang}.json`, {
params: {
buildTimestamp: process.env.BUILD_TIMESTAMP
}
});

最佳方案是?

上面的办法可以解决,但再想想。

严谨来说 构建时间跟i18n变化不变化其实是必要条件而非充分必要条件,最好的方案是假如i18n文件内容发生变化,则请求就走新的,否则走缓存,这就完美了。

能不能做到呢?肯定是可以的。不都是代码嘛。假如要做到,应该是MergeJsonWebpackPlugin合并json文件时增加哈希指纹【就像JS打包一样】,进而请求文件地方,打上合并后的文件名即可。可惜目前插件不支持,等着咱们开发呢,不是吗。

结语

到这里,应该完了。目前没新坑发现。
问题虽小,但却基础。bye!