smooth-i18n

An Internalization Solution for JavaScript/TypeScript project

Usage no npm install needed!

<script type="module">
  import smoothI18n from 'https://cdn.skypack.dev/smooth-i18n';
</script>

README

smooth-i18n

低成本国际化(i18n)方案

功能

  • CLI 脚本:
    • 批量替换代码中的静态、动态文本为翻译调用 (s18n())
    • 根据s18n()调用,导出翻译资源
  • 运行时:
    • 提供基本够用的翻译实现

开始

共 7 步

cd that-legacy-codebase

# 1 安装为项目依赖
npm install --save smooth-i18n # or: yarn add smooth-i18n

# 2. 备份当前项目代码(勇者可跳过)
git stash && git checkout -b i18n

# 3. 替换代码中的字符串为翻译方法调用:
#   '有中文的字符串'                    -->   s18n('有中文的字符串')
#   `有中文的Template${Literals}`       -->   s18n`有中文的Template${literals}` 
#   <div tip="jsx属性"/>jsx内容</div>   -->   <div tip={s18n('jsx属性')}/>{s18n('jsx内容')}</div>
#    (会自动补上 require/import)
./node_modules/.bin/s18n wrap . --write

# 4. 人肉检查一下有没有 错改/漏改 的,修复之
#   如有不希望脚本改的行,上面加注释 `// @s18n-ignore`
#   如整个文件都不用改,文件开始处加上 `/* @s18n-ignore-file */`

# 5. 根据代码中的翻译调用,导出为待翻译资源
#   默认导出JSON,会在./locales目录下生成 zh-CN.json, en.json
#   (可以通过--format参数,指定导出`JSON5`或`.js`,这两种格式会在注释中包含额外的上下文信息,便于翻译)
./node_modules/.bin/s18n extract . ./locales --locales zh-CN,en --format json
// 6. 将待翻译资源交付翻译,翻译好后的资源应该是类似下面的样子
//   (key是s18n工具加进去的, value是翻译人员提供的)

/*********** en.json **********/
{
  "这句话没有翻译": null,  // 没翻译,线上会fallback到备选语言或原始字符串

  "表格做的真好": "nufan is cool", // 静态文本
  "我是一个有ID的文本#some.id": "I have ID and you don't" // 有ID的静态文本,ID需要手动标注: s18n('我是一个有ID的文本', {_: 'some.id'})

  "%s是最棒的": "nufan is way better than %s", // 动态文本
}
// 7. **运行任何其他代码前,加载翻译资源,指定语言**  之后`s18n()`工具就能给出正确的翻译结果了
import s18n from 'smooth-i18n'

// 同步加载翻译资源
s18n.addLocaleResource('en-US', require('./en.json'))

// 设置要使用的语言
s18n.setLocale('en')

// Done. 在此之后,界面语言会根据资源文件提供的翻译展示
...other code...

开发计划

  • 加入 ICU messageformat 支持

Q & A

1. 命令行工具怎么使用,有哪些参数?

see: ./node_modules/.bin/s18n --help

2. 为什么必须在 所有其他代码运行前 载入翻译资源,并指定locale?

否则某些代码中的变量可能无法更新,造成展示不正确。

例如:

const s = s18n('apple')`  //  s = 'apple'

s18n.addLocaleResource('zh-CN', {apple: '苹果'})
s18n.setLocale('zh-CN')

console.log(s) // s = 'apple' , 而不是期望的'苹果'

3. 有哪些场景不适用这个工具,需要其他解决方案?

  • 后端返回的文本信息
  • 前端使用的第三方 UI 库
  • 其他可能呈现给用户的动态生成的文本
  • 日期、格式、货币的展示、转换(后期可能加入这些功能的支持,当前推荐使用 JavaScript 标准:Intl.*)