国际化(Internationalization, i18n)本身是一个很大的话题,通常来说,就是将 UI 翻译成不同的语言。本地化(Localization, l10n)更具体一点,描述的是如何将 UI 与适配到某一个具体的地区(locale)。不同的地区可能有相同的语言,但是会有不同的时间格式或者尺寸单位等。

在 Webpack 中,我们可以使用动态加载的方式来实现国际化。

添加不同语言的翻译文件

translations/en.json

{ "hello": "Hello world" }
1

translations/zh.json

{ "hello": "你好" }
1

配置 Webpack

我们复用一些前面章节中定义的配置。

webpack.i18n.js

const path = require('path');
const { MiniHtmlWebpackPlugin } = require('mini-html-webpack-plugin');
const APP_SOURCE = path.join(__dirname, 'src');

module.exports = {
  mode: 'production',
  entry: { index: path.join(APP_SOURCE, 'i18n.js') },
  module: {
    rules: [
      {
        test: /\.js$/,
        include: APP_SOURCE,
        use: 'babel-loader',
      },
    ],
  },
  plugins: [new MiniHtmlWebpackPlugin()],
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

.babelrc

{
  "presets": [
    ["@babel/preset-env", { "modules": false }],
    "@babel/preset-react"
  ]
}
1
2
3
4
5
6

package.json

{
  "scripts": {
    "build:i18n": "wp --config webpack.i18n.js"
  }
}
1
2
3
4
5

在应用中使用国际化

我们用 React 来演示这个应用,同时用 import 来加载国际化。

src/i18n.js

import 'regenerator-runtime/runtime';
import React, { useEffect, useState } from 'react';
import ReactDOM from 'react-dom';

const App = () => {
  const [language, setLanguage] = useState('en');
  const [hello, setHello] = useState('');

  const changeLanguage = () => setLanguage(language === 'en' ? 'fi' : 'en');

  useEffect(() => {
    translate(language, 'hello').then(setHello).catch(console.error);
  }, [language]);

  return (
    <div>
      <button onClick={changeLanguage}>Change language</button>
      <div>{hello}</div>
    </div>
  );
};

function translate(locale, text) {
  return getLocaleData(locale).then((messages) => messages[text]);
}

async function getLocaleData(locale) {
  return import(`../messages/${locale}.json`);
}

const root = document.createElement('div');

root.setAttribute('id', 'app');
document.body.appendChild(root);

ReactDOM.render(<App />, root);
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
28
29
30
31
32
33
34
35
36

此时执行 npm run build:i18n,然后启动应用 npx serve dist,我们可以看到随着按钮点击,应用使用了不同的翻译资源。

如果要去除应用开头的 regenerator-runtime/runtime,我们需要使用 Babel 的 useBuiltIns,可以在加载 JavaScript 一章中了解具体的使用方法。

总结

Webpack 支持多种 i18n 和 l10n 的方式。本文提供了一种入门方案,使用 import 动态加载国际化资源。

关注微信公众号,获取最新推送~