基于AST实现一键自动提取替换国际化文案

背景:在调研 @formatjs/cli 使用(使用 @formatjs/cli 进行国际化文案自动提取 )过程中,发现有以下需求@formatjs/cli 无法满足:

  1. id 需要一定的语义化;

  2. defaultMessage和Id不能直接hash转换;

  3. 需要直接从中文转换为formatMessage

  4. 需要显式注入ID(个人觉得编译时注入还是反直觉了一点);

另外也是希望借助这个机会好好学一下AST相关知识,所以决定自己写一个AST转换工具。

*注意:工具无法满足脱离中文文案和文件名的语义化ID需求。

实现效果

如何使用

https://www.npmjs.com/package/core-i18n-cli?activeTab=readme

安装

npm i -g core-i18n-cli

CLI 参数

corei18n -i, --init

初始化项目,生成配置文件 corei18n.config.json,方便根据你的项目需求进行配置。

默认配置包括以下参数:

export type ProjectConfig = {/** corei18n文件根目录,用于放置提取的langs文件 */corei18nDir: string;/** 导出的新增文案目录 */tempLangFile: string;/** 需要做国际化的文件目录 */path: string;/** 已有文案入口,用于过滤已经存在id的文案,支持js、ts、json */localLangFile?: string;/** 忽略的文件 string | string[],参考GlobOptions.ignore */ignoreFile?: GlobOptions["ignore"];/** 生成id的方式,默认为translate,需要提供baiduApiKey */idType: "translate" | "hash";/** 百度翻译开放平台配置,参考 https://fanyi-api.baidu.com/product/113 */baiduApiKey?: {appId: string;appKey: string;};/** 生成id前缀,会以.拼接在id前面 */idSuffix?: string;/** 替换后是否保留DefaultMessage,默认为false */keepDefaultMessage?: boolean;/** 格式化代码的选项,参考prettier.options */prettierOptions?: Options;
};

例子:

{"corei18nDir": "./.corei18n","tempLangFile": "./.corei18n/tempLang.json","path": "src/pages/**/*.{ts,js,jsx,tsx}","localLangFile": "src/locales/zh-CN.ts","ignoreFile": "src/pages/**/*.d.ts","baiduApiKey": {"appId": "","appKey": ""},"keepDefaultMessage": false,"idType": "hash","idSuffix": "tools","prettierOptions": {"parser": "typescript","printWidth": 80,"singleQuote": true,"trailingComma": "all","proseWrap": "never"}
}

corei18n -s, --scan

一键扫描指定文件夹下的所有中文文案,新增文案会存放至tempLangFile

corei18n -r, --replace

一键替换指定文件夹下的所有中文文案


实现过程

关于AST

AST explorer:https://astexplorer.net/

AST(抽象语法树)是源代码的抽象表示形式,它捕捉了代码的结构,而不关心具体的字符格式。AST是在编译器设计和解析源代码时常见的一种数据结构。

在编程语言的编译过程中,源代码首先被解析器解析成一种称为AST的中间表示。AST反映了代码的语法结构,每个节点代表代码中的一个结构元素,如表达式、语句、函数、变量等。这种树状结构使得程序的结构和语法可以被更容易地分析和处理。

操作流程

暂时无法在飞书文档外展示此内容

scan 阶段

  1. 根据pathignoreFile得到所有目标文件

  2. 对于每个文件,读取文件内容,将代码转换为AST

  3. 遍历AST节点,若是StringLiteral或者JSXText,判断是否符合要求(包含中文且不属于default Message),如果是则记录下来

  4. 过滤得到所有新增文案并生成id

  5. 将新增文案导出到目标文件

replace 阶段

  1. 根据pathignoreFile得到所有目标文件

  2. 获取所有文案对;

  3. 对于每个文件,读取文件内容,将代码转换为AST

  4. 遍历AST节点,若是StringLiteral或者JSXText,判断是否符合要求(包含中文且不属于default Message),如果是则替换当前AST节点;

  5. 使用prettier进行格式化;

  6. 根据AST生成代码写入文件路径;

依赖的npm包

babel

  1. @babel/core:负责整个编译过程的调度和控制;

  2. @babel/parser:用于将 JavaScript 源代码解析成抽象语法树(AST);

  3. @babel/traverse:用于遍历和修改 AST 的工具;

  4. @babel/types:用于创建、检查和修改 AST 节点

cli相关

  1. commander:解析命令行参数和生成帮助信息;

  2. inquirer:交互式命令行工具,用于收集用户输入;

  3. glob:匹配文件路径

  4. lodash:工具库

  5. prettier:代码格式化

遇到的问题

解决babel/generater生成中文等特殊字符被转义为Unicode编码

const newCode = generator.default( ast, { retainLines: true, jsescOption: { minimal: true } }, // add this code ).code;

Error [ERR_REQUIRE_ESM]: require() of ES Module

// tsconfig { "compilerOptions": { "module": "esnext", "target": "esnext", "moduleResolution": "node", } }

// package.json { "type": "module" }

Error [ERR_MODULE_NOT_FOUND]: Cannot find module

https://github.com/microsoft/TypeScript/issues/16577

https://stackoverflow.com/questions/62619058/appending-js-extension-on-relative-import-statements-during-typescript-compilat

原因:tsc输出时不会添加文件拓展名,nodejs运行时不会自动匹配文件拓展名(居然是个久远的未解决的问题==)

尝试在文件首行添加 --experimental-specifier-resolution=node 无效

使用tsc-alias为导出文件添加js后缀后解决:

npm install --save-dev tsc-alias

// tsconfig.json { "compilerOptions": { ... }, "tsc-alias": { "resolveFullPaths": true, "verbose": false } }

"scripts": { "compile": "tsc && tsc-alias" }

参考

  • 小玩具:利用AST实现代码文案的自动翻译与替换 - 掘金

  • https://github.com/alibaba/kiwi/tree/master/kiwi-cli

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/254216.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

简化版SpringMVC

简化版SpringMVC web.xml xml version"1.0" encoding"UTF-8"?> <web-app version"2.5" xmlns"http://java.sun.com/xml/ns/javaee" xmlns:xsi"http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation&quo…

MySQL学习记录——칠 表操作

文章目录 1、了解2、创建和插入1、基本创建和插入2、插入并更新on duplicate3、插入并替换replace 3、Retrieve1、查询select2、条件查询where3、结果排序order by4、限制行数limit 4、更新Update5、删除delete6、去重7、聚合函数&#xff08;5个&#xff09;1、count2、sum3、…

第十六篇【传奇开心果系列】Python的OpenCV库技术点案例示例:图像质量评估

传奇开心果短博文系列 系列短博文目录Python的OpenCV库技术点案例示例短博文系列博文目录前言一、图像质量评估方法和相关函数的介绍二、均方误差示例代码三、峰值信噪比示例代码四、结构相似性指数示例代码五、视频质量评估示例代码六、OpenCV均方根误差计算示例代码七、OpenC…

Vivado开发FPGA使用流程、教程 verilog(建立工程、编译文件到最终烧录的全流程)

目录 一、概述 二、工程创建 三、添加设计文件并编译 四、线上仿真 五、布局布线 六、生成比特流文件 七、烧录 一、概述 vivado开发FPGA流程分为创建工程、添加设计文件、编译、线上仿真、布局布线&#xff08;添加约束文件&#xff09;、生成比特流文件、烧录等步骤&a…

05 06 Verilog基础语法与应用讲解

05. 1. 位操作 计数器实验升级&#xff0c;设计8个LED灯以每个0.5s的速率循环闪烁&#xff08;跑马灯&#xff09; 1.1 方法1&#xff1a;使用移位操作符<<来控制led灯的循环亮灭 设计代码 Verilog中&#xff0c;判断操作的时候不加位宽限定是可以的&#xff0c;比如i…

MySQL之体系结构

华子目录 MySQL简介MySQL的特性MySQL版本MySQL常见版本 数据库排名网站MySQL结构体系查看最大连接数查询缓存配置情况 一条SQL语句执行流程 MySQL简介 MySQL是一个小型关系数据库管理系统&#xff0c;开发者为瑞典MySQL AB公司。在2008年1月16号被sun公司10亿美金收购。2009年…

IntelliJ IDE 插件开发 | (六)内部模式的使用

系列文章 IntelliJ IDE 插件开发 |&#xff08;一&#xff09;快速入门IntelliJ IDE 插件开发 |&#xff08;二&#xff09;UI 界面与数据持久化IntelliJ IDE 插件开发 |&#xff08;三&#xff09;消息通知与事件监听IntelliJ IDE 插件开发 |&#xff08;四&#xff09;来查收…

Oracle systemstate、gdb、dbx介绍

当数据库出现严重的性能问题或者hang了的时候&#xff0c; 可能最常用的办法就是重启数据库&#xff0c;简单有效解决问题&#xff1b;但是重启后如何追踪问题的根本原因成了难题&#xff0c;很多信息随着重启也消失不见了&#xff0c;让追查问题变的十分棘手&#xff0c;这时就…

Spring第二天

一、第三方资源配置管理 说明&#xff1a;以管理DataSource连接池对象为例讲解第三方资源配置管理 1 管理DataSource连接池对象 问题导入 配置数据库连接参数时&#xff0c;注入驱动类名是用driverClassName还是driver&#xff1f; 1.1 管理Druid连接池【重点】 数据库准备…

Android 识别车牌信息

打开我们心爱的Android Studio 导入需要的资源 gradle //开源车牌识别安卓SDK库implementation("com.github.HyperInspire:hyperlpr3-android-sdk:1.0.3")button.setOnClickListener(v -> {Log.d("Test", "");try (InputStream file getAs…

#Z0458. 树的中心2

题目 代码 #include <bits/stdc.h> using namespace std; struct ff {int z,len; }; vector<ff> vec[300001]; int n,u,v,w,dp[300001][2],ans 1e9; void dfs(int x,int fa) {for(int i 0;i < vec[x].size();i){ff son vec[x][i];if(son.z ! fa){dfs(son.z,…

搭建macOS开发环境-1:准备工作

请记住&#xff1a; 最重要的准备工作永远是&#xff1a;备份数据 !!! 通过图形界面检查 Mac 的 CPU 类型&#xff1a; 在搭载 Apple 芯片的 Mac 电脑上&#xff0c;“关于本机”会显示一个标有“芯片”的项目并跟有相应芯片的名称&#xff1a; 通过命令行检查Mac的CPU类型 …

ASP.NET Core 预防开放式重定向攻击

写在前面 为预防钓鱼网站的常用套路&#xff0c;在进行 Web 应用程序的开发时&#xff0c;原则上应该将所有由用户提交的数据视为不可信。如果应用程序中包含了基于 URL 内容重定向的功能&#xff0c;需要确保这种类型的重定向操作只能在应用本地完成&#xff0c;或者明确判断…

构造回文数组

目录 原题描述&#xff1a; 题目描述 时间&#xff1a;1s 空间&#xff1a;256M 题目描述&#xff1a; 输入格式&#xff1a; 输出格式&#xff1a; 样例1输入&#xff1a; 样例1输出&#xff1a; 样例2输入&#xff1a; 样例2输出&#xff1a; 约定&#xff1a; 作…

《幻兽帕鲁》攻略:0基础入门及游戏基础操作 幻兽帕鲁基础设施 幻兽帕鲁基础攻击力 Mac苹果电脑玩幻兽帕鲁 幻兽帕鲁加班加点

今天就跟大家聊聊《幻兽帕鲁》攻略&#xff1a;0基础入门及游戏基础操作。 如果想在苹果电脑玩《幻兽帕鲁》记得安装CrossOver哦。 以下纯干货&#xff1a; CrossOver正版安装包&#xff08;免费试用&#xff09;&#xff1a;https://souurl.cn/Y1gDao 一、基础操作 二、界面…

(45)执行操作后的变量值

文章目录 每日一言题目解题思路代码结语 每日一言 与其临渊羡鱼&#xff0c;不如退而结网。——《史记汉书董仲舒传》 题目 题目链接&#xff1a;执行操作后的变量值 存在一种仅支持 4 种操作和 1 个变量 X 的编程语言&#xff1a; X 和 X 使变量 X 的值 加 1 –X 和 X-- 使…

Allegro如何把Symbols,shapes,vias,Clines,Cline segs等多种元素一起移动

Allegro如何把Symbols,shapes,vias,Clines,Cline segs等多种元素一起移动 在用Allegro进行PCB设计时,有时候需要同时移动某个区域的所有元素,如:Symbols,shapes,vias,Clines,Cline segs等元素。那么如何操作呢? 首先就是把Symbols,shapes,vias,Clines,Cline …

【机器学习笔记】机器学习基本概念

机器学习基本概念 文章目录 机器学习基本概念1 概述2 机器学习实验方法与原则2.1 平均指标 2.2 训练集、验证集与测试集2.3 随机重复实验2.4 K折交叉验证2.4 统计有效性检验 1 概述 什么是机器学习 —— 在某种任务上基于经验不断进步 T (Task)&#xff1a;需要解决什么任务 P(…

LLaMA 模型中的Transformer架构变化

目录 1. 前置层归一化&#xff08;Pre-normalization&#xff09; 2. RMSNorm 归一化函数 3. SwiGLU 激活函数 4. 旋转位置嵌入&#xff08;RoPE&#xff09; 5. 注意力机制优化 6. Group Query Attention 7. 模型规模和训练超参数 8. 分布式模型训练 前置归一化与后置…

改进神经网络

Improve NN 文章目录 Improve NNtrain/dev/test setBias/Variancebasic recipeRegularizationLogistic RegressionNeural networkother ways optimization problemNormalizing inputsvanishing/exploding gradientsweight initializegradient checkNumerical approximationgrad…