大厂技术  高级前端  Node进阶

点击上方 程序员成长指北,关注公众号
回复1,加入高级Node交流群

效果展示

完整流程

由于 gif 图有大小限制,这里录了两个。

01

a16be1cb80c0dd6e469c7476b3192c04.gif

02

5548265057bd53c5525768eeb509a7ba.gif

删除某个中文和检测本地文件是否已经存在

64f9cf6b3dd6767525e2e9fa6375e80f.gif

  1. 这里如果不想对某个中文做国际化,可以手动给删掉。

  2. 如果本地已经对当前中文做过国际化,就不会再去翻译了,而是直接把对应的key取出来,直接替换代码。

增加国际化语言类型

39fb85f36b44e02f53be8db783bb122d.gif

 这里新增了一个国际化类型,翻译的时候多了一个繁体中文,保存的时候,也会检测本地文件是否存在如果不存在,会自动创建该类型文件。添加国际化语言时冒号前面是百度翻译支持的类型,后面是文件名,如果一样可以只写一个。

下面是百度翻译常用语种和对应代码。

名称 代码 名称 代码
自动检测 auto 中文 zh
英语 en 粤语 yue
文言文 wyw 日语 jp
韩语 kor 法语 fra
西班牙语 spa 泰语 th
阿拉伯语 ara 俄语 ru
葡萄牙语 pt 德语 de
意大利语 it 希腊语 el
荷兰语 nl 波兰语 pl
保加利亚语 bul 爱沙尼亚语 est
丹麦语 dan 芬兰语 fin
捷克语 cs 罗马尼亚语 rom
斯洛文尼亚语 slo 瑞典语 swe
匈牙利语 hu 繁体中文 cht
越南语 vie

react代码中出现中文的几种方式

53ef343d91acf2b8695bc464f2291c6e.gif

 利用抽象语法树,能够精准的获取代码中的中文。

插件功能介绍

  1. 到vscode插件市场搜索easy-i18n-helper然后安装,作者是dbfu321,别安装错了。也可以访问这个 在线地址https://marketplace.visualstudio.com/items?itemName=dbfu321.easy-i18n-helper) 去安装。

  2. 首先在百度翻译平台开通通用文本服务,得到APP ID和密钥,然后在vscode配置中设置easy-i18n-helper.Baidu App Id和easy-i18n-helper.Baidu App Token后,就能使用该插件了。开通百度翻译服务教程在下面。

  3. 在react代码文件中右键,然后点击翻译当前页面,会自动获取当前页面的中文,然后展示出来,这里如果你不想对某个中文做国际化,你可以给删除。

  4. 点击名称,可以跳到对应编辑器中并选中当前中文,可以让你快速知道当前中文在代码中的位置,然后决定是否删除。

  5. 点击翻译会调百度翻译公共接口去翻译,这里会检测本地是否已经存在要做国际化的中文,如果存在,则不会去调翻译接口,直接用本地的。

  6. 点击翻译按钮过后,会在翻译结果页面看到哪些是新增的,哪些是直接取本地的。

  7. 点击保存后,会自动检测当前文件是否引入了国际化方法,如果没有引入,会自动引入,这个导入代码可以在配置里自定义。

  8. 把新增的国际化内容保存到本地文件中,如果本地文件不存在,则自动创建。

  9. 用国际化方法覆盖掉代码中的中文

  10. 自定义语种。到vscode配置中搜索easy-i18n-helper.languages,然后添加一个语种,百度翻译支持的语种上面已经发过了。

  11. 自定义导入国际化方法语句。到vscode配置中搜索easy-i18n-helper.Import Codes,然后改成自己想要的。

  12. 自定义存放本地国际化文件的文件夹地址。到vscode配置中搜索easy-i18n-helper.Locales Path,然后改成自己的。

  13. 自定义国际化文件后缀。有的项目可能没有用ts,所以这里支持去修改成js。到vscode配置中搜索easy-i18n-helper.File Type,然后改成其他的。

  14. 自定义国际化方法名。有的项目可能不叫t,到vscode配置中搜索easy-i18n-helper.Method Name,然后改成其他的。

  15. mac快捷键:command+shift+t

  16. win快捷键:ctrl+shift+t

开通百度翻译翻译服务和获取 app id 和 密钥

开通这个服务还是很简单的,整个流程大概只需要几分钟。百度翻译每个月有100w字符的免费(良心企业啊),如果个人使用,基本可以放心的使用。这里提醒一下,如果超出100w字符,是会扣费的,所以大家要保护好自己的app id和密钥。

01 进入百度翻译网站,登录百度账号

02 点击下面的通用文本翻译的查看详情

72ea4923ba852a231dc54f4bb0e3c5d4.jpeg

点击立即使用

795bdbf8e5fe91046927f5926ca98708.jpeg

选个人开发者,填写信息

2dc38af02f820757969c5260f2289653.jpeg

实名认证,可开通高级版

e0dc1ccc3f3925f6efa45a3e90eebb87.jpeg

开通文本翻译服务

a4370c030383b2f8f53238332ddcf09c.jpeg

选通用文本翻译

88dac73adfc4ebb9d4920385ad701cb6.jpeg

开通高级版

c27b833b747cf05eda7a1527a0ec69e2.jpeg

写应用名(随意),其他可不填,提交申请,秒通过

7223ec4450105147f8be7a8d72f12342.jpeg

总览下方,可得到 app id 和 密钥,配置到 vscode 中,即可用当前插件

737a4129b2e112322d7e6e9b4acc05af.jpeg

插件代码实现思路

  1. 获取并检查用户配置,并把获取到的用户配置存到全局。

  2. 获取当前内容ast

  3. 通过ast获取所有中文

  4. 使用vscode webview显示中文列表页面,并在页面中实现删除功能。

  5. 监听webview消息事件

  6. 当监听到webview传输open类型的事件时:使用vscode api实现选中当前中文。

  7. 使用ast检测用户当前本地项目中有没有对应的中文

  8. 根据用户配置的语言列表,把本地没有做过国际化的中文,借助百度翻译api翻译成对应的语言。

  9. 使用webiew展示翻译结果

  10. 保存,把新增的国际化存到本地,然后使用国际化生成的key和封装的国际化方法替换掉当前文本。

插件中用到的主要技术

抽象语法树

项目里主要使用了babel把文件内容转换成抽象语法树,然后通过遍历语法树获取中文。

@babel/parser 使用这个库把代码转换成抽象语法树

@babel/traverse 使用这个库遍历语法树,获取代码中的中文

@babel/generator 使用这个库把处理过的ast转换成代码

private getAst(): ParseResult<t.File> | undefined {
    try {
      this.ast = parse(this.fileContent, {
        sourceType: "module",
        plugins: [
          "jsx",
          "flow",
          ["decorators", { "decoratorsBeforeExport": true }],
        ],
      });
      return this.ast;
    } catch (error) {
      console.log(error);
    }
  }
private getChineseWordsByAst(ast: ParseResult<t.File>) {
    const words: Words[] = [];
    traverse(ast, {
      ["StringLiteral"]: (path: any) => {
        if (/[\u4e00-\u9fa5]/.test(path.node.value)) {
          words.push({
            value: path.node.value,
            loc: path.node.loc,
            isJsxAttr: path.parent.type === "JSXAttribute",
            id: getId(),
          });
        }
      },
      ["JSXText"]: (path: any) => {
        if (/[\u4e00-\u9fa5]/.test(path.node.value)) {
          const val = path.node.value.replace(/\n/g, '').trim();
          words.push({
            id: getId(),
            value: val,
            loc: path.node.loc,
            isJsxAttr: true,
            isJsxText: true,
            rawValue: path.node.value,
          });
        }
      },
      ["TemplateElement"]: (path: any) => {
        if (/[\u4e00-\u9fa5]/.test(path.node.value.raw)) {
          const val = path.node.value.raw.replace(/\n/g, '').trim();
          words.push({
            id: getId(),
            value: val,
            loc: path.node.loc,
            isTemplate: true,
          });
        }
      }
    });
    return words;
  }
    const ast = parse(fileContent, { sourceType: "module" });


    const visitor: any = {
      // eslint-disable-next-line @typescript-eslint/naming-convention
      ObjectExpression(nodePath: any) {
        const { node } = nodePath;


        node.properties.push(
          ...newWords.map((word) => {
            return t.objectProperty(
              t.stringLiteral(word.key),
              t.stringLiteral(word.value),
            );
          })
        );
      },
    };


    traverse(ast, visitor);


    const newContent = generator(ast, {
      jsescOption: { minimal: true },
    }).code;

这里只简单的介绍一下,后面会开单篇详细介绍babel。

vscode插件开发

webview 和 vscode 通信

vscode中创建webview后,可以使用onDidReceiveMessage这个方法监听webview中js发送过来的消息。

this.webviewPanel = window.createWebviewPanel(
  'translate',
  "中文列表",
  columnToShowIn || ViewColumn.Active,
  {
    retainContextWhenHidden: true,
    enableScripts: true
  }
);
this.webviewPanel.webview.onDidReceiveMessage((e) => this.didReceiveMessageHandle(e));

webview script中可以通过acquireVsCodeApi这个方法得到vscodeAPI对象,然后使用postMessage给vscode发送消息。

<script>
 const vscode = acquireVsCodeApi();
 vscode.postMessage({
   data: window.words,
   type: "save",
 });
</script>

webview 中获取 vscode 主题

为了让用户体验更好,插件可以根据用户主题自动改变颜色。

在css中可以使用body.vscode-lightbody.vscode-dark来定制webview中的主题。

body.vscode-light {
   color: #333;
}


body.vscode-dark {
  color: #eee;
}

使用--vscode-editor-font-size变量获取编辑器设置的字体大小

body,
table {
  font-size: var(--vscode-editor-font-size);
  word-break: break-word;
}

小结

后面也会开单篇介绍如何从零开发一个 vscode 插件

ejs html 模版引擎

官网地址

这个我用的也不多,因为要根据变量生成一些dom元素,不想用原生api一个个创建dom元素,就使用了这个市面上比较常用的html模版引擎。用了一下,感觉还挺方便。就遇到了一个问题,怎么把变量注入到window对象上。从网上搜了一些资料,他们给的方案是有点问题的。

网上的方案:

<script>
   window.words = <%= JSON.stringify(words) %>;
</script>

这样写在运行的时候会报错,因为<%= 会把内容转换成html,导致json中{会被转译掉,然后JSON.stringify就报错了。

正确用法:

<script>
   window.words = <%- JSON.stringify(words) %>;
</script>

使用<%-就行了。

  • <% '脚本' 标签,用于流程控制,无输出。

  • <%_ 删除其前面的空格符

  • <%= 输出数据到模板(输出是转义 HTML 标签)

  • <%- 输出非转义的数据到模板

  • <%# 注释标签,不执行、不输出内容

  • <%% 输出字符串 '<%'

  • %> 一般结束标签

  • -%> 删除紧随其后的换行符

  • _%> 将结束标签后面的空格符删除

总结

相信很多同学都不愿意做国际化,但是公司要求必须要做,只能很痛苦的去做。但是有了这款插件,开发的时候就不用关注国际化了,可以在开发完一个功能后,一键国际化。

我不知道别人的系统国际化是怎么做的,看了一些开源的框架,都是在本地文件中做,其实这样做有个不好的地方,很容易导致代码冲突,所以我们把本地存储迁移到了数据库。迁移到线上还有一个好处,如果业务对机翻的结果不满意,可以在线修改。

在公司内部我还写了一个插件,和这个区别是调系统接口把自动翻译的结果存储到数据库,而不是存储到本地。

因为我对 vue 不熟,所以现在插件只支持 react,哪位兄弟有时间提个 pr,把 vue 也支持一下吧。

代码中我写了个抽象类,写 vue 插件的时候继承一下这个类,只要实现获取中文,替换文本和导入国际化这三个抽象方法就行了,代码文件可以加在这个目录下。

38a870e29f130daacf2c2172d57d06d8.jpeg

作者:前端小付
链接:https://juejin.cn/post/7217248299924996133

Node 社群


 

我组建了一个氛围特别好的 Node.js 社群,里面有很多 Node.js小伙伴,如果你对Node.js学习感兴趣的话(后续有计划也可以),我们可以一起进行Node.js相关的交流、学习、共建。下方加 考拉 好友回复「Node」即可。

74bff5b8147c7f01ca29061716f02241.png

“分享、点赞、在看” 支持一下
Logo

腾讯云面向开发者汇聚海量精品云计算使用和开发经验,营造开放的云计算技术生态圈。

更多推荐