基于AST实现一键自动提取替换国际化文案
背景:在调研 @formatjs/cli 使用(使用 @formatjs/cli 进行国际化文案自动提取 )过程中,发现有以下需求@formatjs/cli 无法满足:
id 需要一定的语义化;
defaultMessage
和Id不能直接hash转换;需要直接从中文转换为
formatMessage
;需要显式注入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 阶段
-
根据
path
和ignoreFile
得到所有目标文件 -
对于每个文件,读取文件内容,将代码转换为AST
-
遍历AST节点,若是
StringLiteral
或者JSXText
,判断是否符合要求(包含中文且不属于default Message),如果是则记录下来 -
过滤得到所有新增文案并生成id
-
将新增文案导出到目标文件
replace 阶段
-
根据
path
和ignoreFile
得到所有目标文件 -
获取所有文案对;
-
对于每个文件,读取文件内容,将代码转换为AST
-
遍历AST节点,若是
StringLiteral
或者JSXText
,判断是否符合要求(包含中文且不属于default Message),如果是则替换当前AST节点; -
使用
prettier
进行格式化; -
根据AST生成代码写入文件路径;
依赖的npm包
babel
-
@babel/core:负责整个编译过程的调度和控制;
-
@babel/parser:用于将 JavaScript 源代码解析成抽象语法树(AST);
-
@babel/traverse:用于遍历和修改 AST 的工具;
-
@babel/types:用于创建、检查和修改 AST 节点
cli相关
-
commander:解析命令行参数和生成帮助信息;
-
inquirer:交互式命令行工具,用于收集用户输入;
-
glob:匹配文件路径
-
lodash:工具库
-
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
相关文章:

基于AST实现一键自动提取替换国际化文案
背景:在调研 formatjs/cli 使用(使用 formatjs/cli 进行国际化文案自动提取 )过程中,发现有以下需求formatjs/cli 无法满足: id 需要一定的语义化; defaultMessage和Id不能直接hash转换; 需要…...
嵌入式硬件工程师与嵌入式软件工程师
嵌入式硬件工程师与嵌入式软件工程师 纯硬件设备与嵌入式设备 纯硬件设备是指内部不包含微处理器,无需烧写软件就能够运行的电子设备。如天线、老式收音机、老式电视机、老式洗衣机等。这类设备通常功能简单,易于操作,用户通常只需要打开电…...

【华为云】云上两地三中心实践实操
写在前面 应用上云之后,如何进行数据可靠性以及业务连续性的保障是非常关键的,通过华为云云上两地三中心方案了解相关方案认证地址:https://connect.huaweicloud.com/courses/learn/course-v1:HuaweiXCBUCNXI057Self-paced/about当前内容为华…...

Linux大集合
Linux Linux是什么? Linux是一套免费使用和自由传播的类Unix操作系统,是一个基于POSIX和UNIX的多用户、多任务、 支持多线程和多CPU的操作系统。它能运行主要的UNIX工具软件、应用程序和网络协议。它支持32位和 64位硬件。 Linux内核 是一个Linux系统…...

深入解析 Spring 事务机制
当构建复杂的企业级应用程序时,数据一致性和可靠性是至关重要的。Spring 框架提供了强大而灵活的事务管理机制,成为开发者处理事务的首选工具。本文将深入探讨 Spring 事务的使用和原理,为大家提供全面的了解和实际应用的指导。 本文概览 首…...

第9章 安全漏洞、威胁和对策(9.11-9.16)
9.11 专用设备 专用设备王国疆域辽阔,而且仍在不断扩张。 专用设备是指为某一特定目的而设计,供某一特定类型机构使用或执行某一特定功能的任何设备。 它们可被看作DCS、物联网、智能设备、端点设备或边缘计算系统的一个类型。 医疗设备、智能汽车、…...

Mysql-数据库压力测试
安装软件 官方软件 安装插件提供了更多的监听器选项 数据库驱动 数据库测试 配置 这里以一个简单的案例进行,进行连接池为10,20,30的梯度压测: select * from tb_order_item where id 1410932957404114945;新建一个线程组 新增一个连接池配置 新建一…...
CI/CD总结
bitbucket deployment: Bitbucket Cloud resources | Bitbucket Cloud | Atlassian Support Jenkins:...

【CSS】margin塌陷和margin合并及其解决方案
【CSS】margin塌陷和margin合并及其解决方案 一、解决margin塌陷的问题二、避免外边距margin重叠(margin合并) 一、解决margin塌陷的问题 问题:当父元素包裹着一个子元素且父元素没有边框的时候,当给子元素设置margin-top:100px&…...
Python并发
Python是运行在解释器中的语言,查找资料知道,python中有一个全局锁(GIL),在使用多线程(Thread)的情况下,不能发挥多核的优势。而使用多进程(Multiprocess),则可以发挥多核的优势真正地提高效率。…...
2024-02-04(hive)
1.Hive中的分区表 可以选择字段作为表分区。 分区其实就是HDFS上的不同文件夹。 分区表可以极大的提高特定场景下Hive的操作性能。 2.分区语法 create table tablename(...) partitioned by (分区列 列类型, ...) row format delimited fields terminated by ; 3.Hive中的…...
P9420 [蓝桥杯 2023 国 B] 子 2023 / 双子数--2024冲刺蓝桥杯省一
点击跳转例题 子2023思路:dp。最开始想着枚举,但是超时,想着优化以下,但是还是不行。 那么切换算法,应该是dp: 1.f [i] 表示当前字符串 以 2023 为第 i 位的数量方案:如f [0] 表示 前i个字符串…...

The Back-And-Forth Method (BFM) for Wasserstein Gradient Flows windows安装
本文记录了BFM算法代码在windows上的安装过程。 算法原网站:https://wasserstein-gradient-flows.netlify.app/ github:https://github.com/wonjunee/wgfBFMcodes 文章目录 FFTWwgfBFMcodesMATLABpython注 FFTW 官网/下载路径:https://ww…...

【GAMES101】Lecture 19 透镜
目录 理想的薄透镜 模糊 利用透镜模型做光线追踪 景深(Depth of Field) 理想的薄透镜 在实际的相机中都是用的一组透镜来作为这个镜头 这个因为真实的棱镜无法将光线真正聚焦到一个点上,它只能聚在一堆上 所以方便研究提出了一种理想化的…...

防范恶意勒索攻击!亚信安全发布《勒索家族和勒索事件监控报告》
本周态势快速感知 本周全球共监测到勒索事件81起,事件数量有所下降,比上月降低20%。 lockbit3.0仍然是影响最严重的勒索家族;akira和incransom也是两个活动频繁的恶意家族,需要注意防范。 本周alphv勒索组织窃取MBC法律专业公司…...

AR人脸106240点位检测解决方案
美摄科技针对企业需求推出了AR人脸106/240点位检测解决方案,为企业提供高效、精准的人脸识别服务,采用先进的人脸识别算法和机器学习技术,通过高精度、高速度的检测设备,对人脸进行快速、准确地定位和识别。该方案适用于各种应用场…...

数字图像处理实验记录八(图像压缩实验)
前言:做这个实验的时候很忙,就都是你抄我我抄你了 一、基础知识 1.为什么要进行图像压缩: 图像的数据量巨大,对计算机的处理速度、存储容量要求高。传输信道带宽、通信链路容量一定,需要减少传输数据量&a…...

navigator.mediaDevices.getUserMedia获取本地音频/麦克权限并提示用户
navigator.mediaDevices.getUserMedia获取本地音频/麦克权限并提示用户 效果获取权限NotFoundErrorNotAllowedError 代码 效果 获取权限 NotFoundError NotAllowedError 代码 // 调用 captureLocalMedia()// 方法 function captureLocalMedia() {console.warn(Requesting lo…...

CTF-show WEB入门--web19
今晚web19也就顺便解决了 老样子我们先打开题目看看题目提示: 可以看到题目提示为: 密钥什么的,就不要放在前端了 然后我们打开题目链接: 然后我们查看网页源代码: 可以发现有用的内容全在网页源代码里。 前端验证…...
04 使用gRPC实现客户端和服务端通信
使用gRPC实现客户端和服务端通信 参考文档: 基于C#的GRPC 1 创建项目和文件夹 GrpcClientDemoGrpcServerDemoProtos解决方案和文件夹1.1 添加nuget依赖 客户端和服务器都要有依赖和gRPC_Objects文件夹 <ItemGroup><PackageReference Include"Google.Protobu…...
FFmpeg 低延迟同屏方案
引言 在实时互动需求激增的当下,无论是在线教育中的师生同屏演示、远程办公的屏幕共享协作,还是游戏直播的画面实时传输,低延迟同屏已成为保障用户体验的核心指标。FFmpeg 作为一款功能强大的多媒体框架,凭借其灵活的编解码、数据…...
【Java学习笔记】Arrays类
Arrays 类 1. 导入包:import java.util.Arrays 2. 常用方法一览表 方法描述Arrays.toString()返回数组的字符串形式Arrays.sort()排序(自然排序和定制排序)Arrays.binarySearch()通过二分搜索法进行查找(前提:数组是…...

8k长序列建模,蛋白质语言模型Prot42仅利用目标蛋白序列即可生成高亲和力结合剂
蛋白质结合剂(如抗体、抑制肽)在疾病诊断、成像分析及靶向药物递送等关键场景中发挥着不可替代的作用。传统上,高特异性蛋白质结合剂的开发高度依赖噬菌体展示、定向进化等实验技术,但这类方法普遍面临资源消耗巨大、研发周期冗长…...
什么是EULA和DPA
文章目录 EULA(End User License Agreement)DPA(Data Protection Agreement)一、定义与背景二、核心内容三、法律效力与责任四、实际应用与意义 EULA(End User License Agreement) 定义: EULA即…...

CMake 从 GitHub 下载第三方库并使用
有时我们希望直接使用 GitHub 上的开源库,而不想手动下载、编译和安装。 可以利用 CMake 提供的 FetchContent 模块来实现自动下载、构建和链接第三方库。 FetchContent 命令官方文档✅ 示例代码 我们将以 fmt 这个流行的格式化库为例,演示如何: 使用 FetchContent 从 GitH…...
MySQL用户和授权
开放MySQL白名单 可以通过iptables-save命令确认对应客户端ip是否可以访问MySQL服务: test: # iptables-save | grep 3306 -A mp_srv_whitelist -s 172.16.14.102/32 -p tcp -m tcp --dport 3306 -j ACCEPT -A mp_srv_whitelist -s 172.16.4.16/32 -p tcp -m tcp -…...
AspectJ 在 Android 中的完整使用指南
一、环境配置(Gradle 7.0 适配) 1. 项目级 build.gradle // 注意:沪江插件已停更,推荐官方兼容方案 buildscript {dependencies {classpath org.aspectj:aspectjtools:1.9.9.1 // AspectJ 工具} } 2. 模块级 build.gradle plu…...

深度学习习题2
1.如果增加神经网络的宽度,精确度会增加到一个特定阈值后,便开始降低。造成这一现象的可能原因是什么? A、即使增加卷积核的数量,只有少部分的核会被用作预测 B、当卷积核数量增加时,神经网络的预测能力会降低 C、当卷…...

10-Oracle 23 ai Vector Search 概述和参数
一、Oracle AI Vector Search 概述 企业和个人都在尝试各种AI,使用客户端或是内部自己搭建集成大模型的终端,加速与大型语言模型(LLM)的结合,同时使用检索增强生成(Retrieval Augmented Generation &#…...

JVM 内存结构 详解
内存结构 运行时数据区: Java虚拟机在运行Java程序过程中管理的内存区域。 程序计数器: 线程私有,程序控制流的指示器,分支、循环、跳转、异常处理、线程恢复等基础功能都依赖这个计数器完成。 每个线程都有一个程序计数…...