超实用!一个命令搞定 Web 国际化( 二 )


方案 2 - AST我们希望只匹配我们想要的词条 。比如下如下代码,我们预期匹配你好(注释和 console.log 的里的都不需要),如果有个方式只给到我们你好,然后我再判断它是不是包含中文,再包裹就再好不过了 。
// 这是一段注释const word = '你好';console.log('世界');有没有这样的好事?答案是还真有 。是时候上这张神图了

超实用!一个命令搞定 Web 国际化

文章插图
 
Babel 的工作流程主要分为以下 3 个阶段:
  1. Parse阶段:词法分析 & 语法分析
  2. Transform阶段:生成AST,抽象语法树
  3. Generate阶段:生成代码
这里我们着重说下Transform阶段,AST 处理的核心要素:
  • babel-core 通过 transform 将代码字符串转换为 AST 树;
  • babel-types 一个强大的用于处理 AST 节点的工具库,它包含了构造、验证以及变换 AST 节点的方法;
  • visitor 当 Babel 处理 Node 时,以访问者的形式获取节点信息,并进行相关操作 。这种方式是通过一个 visitor 对象来完成,在 visitor 对象中定义了对于各种节点类型函数,我们可以通过不同类型节点做出相应处理 。
通过上述要素,我们既可以完成对 AST 的修改 。下面我们看下这里的核心代码:
return {visitor: {StringLiteral(path: NodePath<tt.StringLiteral>) {let { value } = path.node;value = https://www.isolves.com/it/cxkf/bk/2021-08-26/replaceLineBreak(value);if (needWrap(wrapCharacter, value)) {let newNode = t.CallExpression(t.Identifier(T_WRAppER), [combine(value),]);path.replaceWith(newNode);}},CallExpression(path: NodePath) {switch (path.node.callee.type) {case 'MemberExpression': {const excludeFuncName = i18nConf.parsedExcludeWrapperFuncName;if (excludeFuncName.length > 0) {const names: string[] = [];const me = path.node.callee as tt.MemberExpression;getName(me, names);const MEName = names.reverse().join('.');if (excludeFuncName.includes(MEName)) {path.skip();}}break;}default:break;}},}针对上面我们诉求的例子,当我们得到 AST 后
  • // 这是一段注释 - 实际上会被解析成 CommentLine 类型,我们的代码不处理,所以该什么样还是什么样
  • const word = '你好' - 你好被解析为StringLiteral,判断是中文,这时候我们再重新构造一个新的节点,替换老的及完成了包裹
  • console.log('世界') - console.log被解析为CallExpression,我们可以通过在配置文件中配置需要忽略的包裹的方法,如果解析到的方法名在配置中,则忽略掉,这样就不会出来这里的世界
至此,我们即可完成我们的诉求,完美的对符合我们需要的词条就行包裹 。
题外话 - 如何编写自己的 babel 插件通过上面 AST 的方案,我们可以看得出这里的功能很强大,业界eslint,prettier,webpack等等都是通过对源码进行分析,转换,生成实现各种各样的功能 。
我们可以开发自己的插件,去做各种有意思的事情,比如说代码埋点,国际化方案等等 。看到这里我想大家一定会有个问题:
  1. 上面说的代码转 AST 时的各种类型,我们怎么知道转成什么类型了呢?
答:https://astexplorer.net/
超实用!一个命令搞定 Web 国际化

文章插图
 
2.另外这些类型如何构造新的节点?
答:https://babeljs.io/docs/en/babel-types
超实用!一个命令搞定 Web 国际化

文章插图
 
如何使用 i18n-helper-cli实例请参考 example
安装注意:请确保 Nodejs 版本大于 14!!!
# npm 安装npm install i18n-helper-cli -D# yarn 安装yarn add i18n-helper-cli —dev快捷使用
  1. 在项目根目录下生成 i18n.config.json 文件
# 交互式命令行i18n-helper init# 生成默认配置文件,具体参见【配置说明】( 推荐大家用这个哈,交互方式的的后面加了不少配置还没来得及补齐)i18n-helper init -y
  1. 包裹 & 提取 & 翻译 & 统计
# 包裹 & 提取 & 翻译 & 统计 i18n.config.json 中 srcPath 文件中的中文词条i18n-helper scan -wetc
  1. 切换 Cli 语言
# cli 默认为中文,支持语言切换,目前支持zh & eni18n-helper switch en命令详情# 包裹 & 提取 & 翻译 & 统计 i18n.config.json 中 srcPath 文件中的中文词条# w:wrap e:extract t:translate tm: translate machine c:count# l:language# 这 5 个操作可以随意组合 e.g. i18n-helper scan -we 则只会翻译 & 提取i18n-helper scan -wetci18n-helper scan -we -tm -c# 包裹 & 提取 & 翻译 & 统计 指定路径,指定语言内符合规则的词条# e.g i18n-helper scan -wetc -l en ./src/test/index.jsi18n-helper scan -wetc -l [language] [filepath]i18n-helper scan -we -tm -c -l [language] [filepath]# 包裹 i18n.config.json 中 srcPath 文件中的中文词条i18n-helper wrapi18n-helper scan -w# 包裹指定文件中的中文词条i18n-helper wrap [filepath]i18n-helper scan -w [filepath]# 提取 i18n.config.json 中 srcPath 文件中的中文词条到所有配置语言文件i18n-helper extracti18n-helper scan -e# 提取指定文件中文词条到指定语言文件# e.g i18n-helper extract -l en ./src/test/index.jsi18n-helper extract -l [language] [filepath]i18n-helper scan -e -l [language] [filepath]# 翻译 i18n.config.json 中配置翻译文件词条,-m 腾讯翻译君机器翻译# 从翻译源文件文件中翻译i18n-helper translatei18n-helper scan -t# 腾讯翻译君自动翻译i18n-helper translate -mi18n-helper scan -tm# 翻译指定语言# 从翻译源文件文件中翻译i18n-helper translate [language]i18n-helper scan -t -l [language]# 腾讯翻译君自动翻译指定语言文件i18n-helper translate -m [language]i18n-helper scan -tm -l [language]# 统计 i18n.config.json 中翻译文件的翻译情况i18n-helper counti18n-helper scan -c# 统计指定语言翻译文件的翻译情况,多个语言用,分隔i18n-helper count [language]i18n-helper scan -c -l [language]


推荐阅读