当前位置: 首页 > news >正文

基于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

相关文章:

基于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…...

srs linux

下载编译运行 git clone https:///ossrs/srs.git ./configure --h265on make 编译完成后即可启动SRS # 启动 ./objs/srs -c conf/srs.conf # 查看日志 tail -n 30 -f ./objs/srs.log 开放端口 默认RTMP接收推流端口是1935&#xff0c;SRS管理页面端口是8080&#xff0c;可…...

如何在网页里填写 PDF 表格?

有时候&#xff0c;你可能希望用户能在你的网站上填写 PDF 表单。然而&#xff0c;这件事并不简单&#xff0c;因为 PDF 并不是一种原生的网页格式。虽然浏览器可以显示 PDF 文件&#xff0c;但原生并不支持编辑或填写它们。更糟的是&#xff0c;如果你想收集表单数据&#xff…...

CVE-2020-17519源码分析与漏洞复现(Flink 任意文件读取)

漏洞概览 漏洞名称&#xff1a;Apache Flink REST API 任意文件读取漏洞CVE编号&#xff1a;CVE-2020-17519CVSS评分&#xff1a;7.5影响版本&#xff1a;Apache Flink 1.11.0、1.11.1、1.11.2修复版本&#xff1a;≥ 1.11.3 或 ≥ 1.12.0漏洞类型&#xff1a;路径遍历&#x…...

PAN/FPN

import torch import torch.nn as nn import torch.nn.functional as F import mathclass LowResQueryHighResKVAttention(nn.Module):"""方案 1: 低分辨率特征 (Query) 查询高分辨率特征 (Key, Value).输出分辨率与低分辨率输入相同。"""def __…...

解读《网络安全法》最新修订,把握网络安全新趋势

《网络安全法》自2017年施行以来&#xff0c;在维护网络空间安全方面发挥了重要作用。但随着网络环境的日益复杂&#xff0c;网络攻击、数据泄露等事件频发&#xff0c;现行法律已难以完全适应新的风险挑战。 2025年3月28日&#xff0c;国家网信办会同相关部门起草了《网络安全…...

Java并发编程实战 Day 11:并发设计模式

【Java并发编程实战 Day 11】并发设计模式 开篇 这是"Java并发编程实战"系列的第11天&#xff0c;今天我们聚焦于并发设计模式。并发设计模式是解决多线程环境下常见问题的经典解决方案&#xff0c;它们不仅提供了优雅的设计思路&#xff0c;还能显著提升系统的性能…...

shell脚本质数判断

shell脚本质数判断 shell输入一个正整数,判断是否为质数(素数&#xff09;shell求1-100内的质数shell求给定数组输出其中的质数 shell输入一个正整数,判断是否为质数(素数&#xff09; 思路&#xff1a; 1:1 2:1 2 3:1 2 3 4:1 2 3 4 5:1 2 3 4 5-------> 3:2 4:2 3 5:2 3…...

基于谷歌ADK的 智能产品推荐系统(2): 模块功能详解

在我的上一篇博客&#xff1a;基于谷歌ADK的 智能产品推荐系统(1): 功能简介-CSDN博客 中我们介绍了个性化购物 Agent 项目&#xff0c;该项目展示了一个强大的框架&#xff0c;旨在模拟和实现在线购物环境中的智能导购。它不仅仅是一个简单的聊天机器人&#xff0c;更是一个集…...

【AI News | 20250609】每日AI进展

AI Repos 1、OpenHands-Versa OpenHands-Versa 是一个通用型 AI 智能体&#xff0c;通过结合代码编辑与执行、网络搜索、多模态网络浏览和文件访问等通用工具&#xff0c;在软件工程、网络导航和工作流自动化等多个领域展现出卓越性能。它在 SWE-Bench Multimodal、GAIA 和 Th…...

React与原生事件:核心差异与性能对比解析

&#x1f49d;&#x1f49d;&#x1f49d;欢迎莅临我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐&#xff1a;「storms…...