初次用bable遍历vue项目下的中文

利用 babel 找到 AST 中的中文

// vite-plugin-babel-transform.js
const parser = require('@babel/parser')
const traverse = require('@babel/traverse').default
// const types = require('@babel/types')
// const generate = require('@babel/generator').default
const fs = require('fs-extra')
const path = require('path')let textArr = []
let jsonData = {}
let repeatList = []
// 判断文件是否存在
if (!fs.existsSync('./src/lang/zh.json')) {fs.createFileSync('./src/lang/zh.json')
} else {fs.outputJSONSync('./src/lang/zh.json', jsonData, {spaces: 2})
}export default function vitePluginBabelTransform() {return {name: 'vite-plugin-babel-transform',async transform(code, id) {if (!id.endsWith('.js') &&!id.endsWith('.ts') &&!id.endsWith('.json') &&!id.endsWith('.vue'))return null // 只处理该后缀文件// console.log('id', id)const ast = parser.parse(code, {sourceType: 'module',plugins: ['jsx', 'decorators-legacy'] // 如果你的代码中有 JSX 语法,也需要添加这个插件// 'decorators' 'decorators-legacy'})/*** 分类-js文件 json文件 vue目录分类 public-公共资源,中文出现过两次以上的*/let prefix = ''if (id.endsWith('.js') || id.endsWith('.ts')) {prefix = 'js'} else if (id.endsWith('.json')) {prefix = 'json'} else if (id.endsWith('.vue')) {if (id.indexOf('src/views/') > -1 &&id.split('src/views/')[1].split('/').length > 1) {prefix = id.split('src/views/')[1].split('/')[0]} else if (id.indexOf('src/components/') > -1) {prefix = 'components'} else if (id.indexOf('src/layout/') > -1) {prefix = 'layout'} else {prefix = path.parse(id).name}}// console.log('prefix', prefix)textArr = []traverse(ast, pluginReplaceConsoleLog(prefix))writeTextFile(prefix)// 生成新的代码// const output = generate(ast)// return {//   code: output.code,//   map: output.map // 如果需要source map// }return code}}
}function pluginReplaceConsoleLog(prefix) {return {FunctionDeclaration(path) {// console.log('FunctionDeclaration', path.node.id.name)},StringLiteral(path) {// console.log('StringLiteral', path.node.value)// 获取父节点,检查它是否为一个调用表达式const parent = path.parentif (parent.type === 'CallExpression' &&parent.callee.type === 'Identifier' &&parent.callee.name === 'alert') {// 如果字符串在 alert 中,则不做任何操作return}if (parent.type === 'CallExpression' &&parent.callee.type === 'MemberExpression' &&parent.callee.object.name === 'console') {// 如果字符串在 console 中,则不做任何操作return}if (!path.node.value.includes('iotchannel-console-4G')) {let match = path.node.value.match(/(\S*[\u4e00-\u9fa5]+\S*)/g)if (match) {textArr = textArr.concat(match)}}},IfStatement(path) {// console.log('IfStatement', path.node)},CallExpression(path) {// console.log('CallExpression', path.node)}}
}function getAllValues(obj, prefix) {for (let key in obj) {if (obj.hasOwnProperty(key)) {if (key !== prefix) {let value = obj[key]if (typeof value === 'object' &&value !== null &&!Array.isArray(value)) {// 如果值是对象(但不是数组),则递归调用getAllValues(value, prefix)} else {// 如果值既不是对象也不是数组,直接添加值// 添加重复的数据if (textArr.includes(value)) {delete obj[key]repeatList.push(value)}}}}}
}function writeTextFile(prefix) {// 读取原数据jsonData = fs.readJSONSync('./src/lang/zh.json')// 获取重复的数据放到public下getAllValues(jsonData, prefix)if (jsonData['public']) {repeatList = repeatList.concat(Object.values(jsonData['public']))}// 重复数据去重并添加到对象中jsonData['public'] = [...new Set(repeatList)].sort().reduce((prev, cur, index, arr) => {prev[index] = curreturn prev}, {})// 将新的数据添加到对象中textArr = textArr.filter(item => {return !repeatList.includes(item)})if (jsonData[prefix]) {textArr = textArr.concat(Object.values(jsonData[prefix]))}// 去重textArr = [...new Set(textArr)]// 排序let data = textArr.sort().reduce((prev, cur, index, arr) => {prev[index] = curreturn prev}, {})jsonData[prefix] = datajsonData = Object.keys(jsonData).sort().reduce((prev, cur, index, arr) => {prev[cur] = jsonData[cur]return prev}, {})// console.log('textArr', textArr)fs.outputJSONSync('./src/lang/zh.json', jsonData, {spaces: 2})
}

在 vite.config.js 中的使用

import vitePluginBabelTransform from './vite-plugin-babel-transform'//  https://cn.vitejs.dev/config
export default defineConfig(({ mode }) => {return {plugins: [vitePluginBabelTransform()]}
})
  • 最终会在 src/lang/zh.json 中生成语言包
  • 可利用通义千问对键进行驼峰命名,对值进行翻译
  • 话术:将以上的键做驼峰命名,值做英文翻译

在这里插入图片描述

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

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

相关文章

【Unity2D 2022:NPC】制作任务系统

一、接受任务 1. 编辑NPC对话脚本: (1)创建静态布尔变量用来判断ruby是否接受到任务 public class NPCDialog : MonoBehaviour {// 创建全局变量用来判断ruby是否接到任务public static bool receiveTask false; } (2&#xff…

python学习-错误与异常

代码是人的逻辑思维的具体体现,因为没有一个人的逻辑思维是完美无缺的,所以人在编写代码时必然会出现各种错误。既然错误或多或少都会发生,那么如何捕捉错误,并且捕捉到错误后要如何处理,就显得很重要。 语法错误 Py…

SPI通信协议和W25Q64

前言: STM32中的通信接口: UART 单总线 IIC SPI CAN 1. SPI FLASH W25Q64的关系 SPI:一种通信接口,可以用于和搭载SPI接口的设备通信 FLASH:是一种掉电不丢失的存储 -- 手机8256G的256 单片机 64K512K的512 芯片内部flash&…

STM32 GPIO的工作原理

STM32的GPIO管脚有下面8种可能的配置:(4输入 2 输出 2 复用输出) (1)浮空输入_IN_FLOATING 在上图上,阴影的部分处于不工作状态,尤其是下半部分的输出电路,实际上是与端口处于隔离状态。黄色的高亮部分显示…

响应式布局下关于gird栅格布局的一些构思

1、传列数,根据列数计算元素容器宽度 好处是子元素可以写百分比宽度,不用固定某一种宽度,反正知道列数通过计算间距就能得到外层容器的宽度。 举个简单的例子: (ps:以下用例皆在html中去模拟,就不另外起r…

python7:装饰器

目录 1.调用外部程序os.system-阻塞式调用subprocess-python中的模块 2.装饰器前戏作用域(1)全局和局部-就近原则(2)嵌套作用域(3)内置作用域、变量 高阶函数:函数是最高级的对象(1&…

海外媒体投稿:5个软文代发经典案例,教大家获得突破

随着互联网的飞速发展,软文代发成为一种高效的推广方法。下面我们就详细介绍五个成功软文代发推广实例,致力于帮助读者把握有关方法,完成突破。 第一实例:社交网络散播在如今社交媒体时代,软文代发能够通过社交平台迅速…

nodejs实现:支付宝订单查询

nodejs实现:支付宝订单查询; 原生http请求,不使用三方库; 代码如下: const https require(https); const crypto require(crypto); const querystring require(querystring);// 支付宝公共参数 const PRIVATE_KE…

[C++] 轻熟类和对象

类的定义 格式规范 class为定义类的关键字,后有类名,类的主体存于{}中;类定义结束时后面的分号不能省略;类体的内容成为类的成员,类中的变量成为成员变量,函数成为方法或成员函数;C兼容C语言的…

SpringBoot配置flyway

背景 目前我们的项目代码都会交由Git、SVN等版本管理工具进行管理,但是我们的sql脚本,尤其是各类ddl脚本并没有进行版本的管理(python的web框架Django默认就提供了类似的工具,从一开始就鼓励开发者通过版本管理的方式进行数据库的…

C++中的多重继承和虚继承:横向继承、纵向继承和联合继承;虚继承

多重继承 A.横向多重继承: B.纵向多重继承: C.联合多重继承: 因为 single 和 waiter 都继承了一个 worker 组件,因此 SingingWaiter 将包含两个 worker 组件,那么将派生类对象的地址赋给基类指针将出现二义性 那么如何…

idea http client插件上传文件,并忽略https证书验证

上传文件 ### 传临时素材 图片 POST https://qyapi.weixin.qq.com/cgi-bin/media/upload?access_token{{access_token}}&typeimage Content-Type: multipart/form-data; boundary----WebKitFormBoundarywKUX3Xj6aL5Wssnb------WebKitFormBoundarywKUX3Xj6aL5Wssnb Conten…

从Helm到 Operator:Kubernetes应用管理的进化

🧰Helm 的作用 在开始前需要先对 kubernetes Operator 有个简单的认识。 以为我们在编写部署一些简单 Deployment 的时候只需要自己编写一个 yaml 文件然后 kubectl apply 即可。 apiVersion: apps/v1 kind: Deployment metadata: labels: app: k8s-combat …

去水印小程序源码修复版-前端后端内置接口+第三方接口

去水印小程序源码,前端后端,内置接口第三方接口, 修复数据库账号密码错误问题,内置接口支持替换第三方接口, 文件挺全的,可以添加流量主代码,搭建需要准备一台服务器,备案域名和http…

农牧行业CRM洞察:打造营、销、服一体化数字营销平台

01、行业应用背景 保持企业活力,支撑业务单元协调发展,稳定核心产品竞争力,将成为农牧行业企业数字化、数智化建设的指导方向。 积极发挥数据在生产、流通、消费各个环节的决策支撑,为农牧企业特别是多业态集团型企业&#xff0…

JVM:类的生命周期

文章目录 一、介绍二、加载阶段三、连接阶段1、验证阶段2、准备阶段3、解析阶段 四、初始化阶段 一、介绍 类的生命周期描述了一个类加载、连接(验证、准备和解析)、初始化、使用、卸载的整个过程。 二、加载阶段 加载(Loading&#xff09…

全栈业务开发入门——登录业务接口

业务已上传则资源 实现登录业务的前后端联调,前端点击登录按钮向后端发送一个请求,后端调用接口向前端响应结果 效果如下: 设计环境:springbootmybatisvue3axios 一.前端设计 1.基于vue3脚手架创建项目,搭建项目结构…

LAZYNVIM学习使用笔记

文章目录 1. 前言VIM的模式快捷键参考 1. 前言 习惯使用vscode进行代码编辑,无意中刷到lazynvim,感觉功能强大,于是下载、安装,学习使用一下,本篇主要记录学习使用lazynvim的一些要点,防止遗忘。 持续更新…

帝特(DTECH)USB转RS485/422串口线在Ubuntu系统中的安装

因为测试需要,买了一根帝特(DTECH)USB转RS485/422串口线,今天测试了一下在Ubuntu 22.04系统上的使用。帝特的网站上提供了驱动程序,下载以后发现接口芯片是CP2102,厂商只提供了Linux内核2.6和3.x版本的驱动…

游戏AI的创造思路-技术基础-情感计算(2)

上一篇我们介绍了情感计算的基本支持,本篇将呈现情感计算在游戏AI中的使用实例~~~ 目录 7. 情感计算在游戏AI中的运用实例 7.1. RPG游戏中的运用实例 7.1.1. 实例背景 7.1.2. AI情感计算系统 7.1.3. 引导用户执行任务 7.1.4. 推动游戏剧情发展 7.1.5. 实例效…