大鹿
Jiann
Do not go gentle into that good night. 🏕️

前端国际化

国际化所面临的问题

  1. 语言翻译
    1. 静态文案翻译(前端静态模板文案)
    2. 动态文案翻译(server端下发的动态数据)
  2. 样式
    1. 不同语言文案长度不一样造成的样式错乱
    2. 图片的替换
  3. 第三方服务 依赖库的国际化
  4. 本地化
    1. 货币单位
    2. 货币汇率
    3. 时间格式

现有的库

// en.js 英文
const en_US = {
  'hello': "hello",
  'name': 'my name is {name}'
}
export default en_US;

// zh.js 英文
const zh_CN = {
  'hello': "你好",
  'name': 'my name is {name}'
}
export default zh_CN;

// app.js 导入对应的i18n配置文件
import { addLocaleData, FormattedMessage } from 'react-intl';
import enLocaleData from 'react-intl/locale-data/en';
import zhLocaleData from 'react-intl/locale-data/zh';
import zh from './zh.js';
import en from './en.js';

addLocaleData([...enLocaleData, ...zhLocaleData]);

let lang = 'zh'

<IntlProvider locale={lang} messages={lang === 'zh' ? zh : en}>
  <App>
    <div></div>
    <FormattedMessage id="hello"/>
  </App>
</IntlProvider>

优点:React组件化,format多样化。缺点:无法在普通js文件中使用

import intl from 'react-intl-universal';

const locales = {
  "en-US": require('./locales/en-US.js'),
  "zh-CN": require('./locales/zh-CN.js'),
};

intl.init({
  currentLocale: 'en-US', // TODO: determine locale here
  locales,
})
.then(() => {
  // After loading CLDR locale data, start to render
this.setState({initDone: true});
});

<div>
  {intl.get('SIMPLE')}
</div>

优点:react、原生js中可以统一使用函数获取的形形式获取文本
经过取舍后使用该方案

代码批量替换实现

手动替换代码中时间成本太大,使用脚本实现

方案一 实现babel插件,对ast中的中文文本进行处理

方案二 node脚本,正则匹配字符串进行处理

let dictionary = []; // 字典


async function parse(moduleName, filename, context) {
  // 处理jsx标签中 中文
  let res = await parseStrOfJsx(moduleName, filename, context);
  // 处理对象key值中 中文

  // 处理引号中 中文

  writeFile(moduleName, filename, res)
}


// 读取文件内容
function readFile(moduleName, filename) {
  fs.readFile(filename, { encoding: 'utf8' }).then(res => {
    parse(moduleName, filename, res);
  });
}

// 读取目录中所有js文件
function readPath(moduleName, modulePath) {
  glob(modulePath + '/*.?(jsx|js)', null, function(err, files) {
    files.forEach(f => readFile(moduleName, f));
  });
}

readPath('log', 'E:/cdn_console_v2/cdn_web/src/pages/Log');
  1. 针对各种字符串进行处理
//普通字符串
let a = '你好'; // let a = intl.get('hello');
let b = "你好"; // let b = intl.get("hello");

// jsx组件中文本
<Select placeholder="选择" /> // <Select placeholder={intl.get('select')} />
<Select placeholder={'选择'} /> // <Select placeholder={intl.get('select')} />
<Select placeholder={"选择"} /> // <Select placeholder={intl.get('select')} />
<View>查看</View> // <View>{intl.get('view')}</View>

// 对象key值,确定是否影响业务代码
{ '你好': '11'} => { [intl.get('hello')]: '11'}

// 需要忽略注释中文

  1. 匹配出中文文本后,使用google-translate-api翻译成对应的文本(接口可能无效,需使用百度翻译api)

  2. 替换中文文本为英文key值变量

  3. 生成对应语言的字典文件

具体实现参照script/auto-translation