利用 babel 找到 AST 中的中文
const parser = require('@babel/parser')
const traverse = require('@babel/traverse').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 const ast = parser.parse(code, {sourceType: 'module',plugins: ['jsx', 'decorators-legacy'] })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}}textArr = []traverse(ast, pluginReplaceConsoleLog(prefix))writeTextFile(prefix)return code}}
}function pluginReplaceConsoleLog(prefix) {return {FunctionDeclaration(path) {},StringLiteral(path) {const parent = path.parentif (parent.type === 'CallExpression' &&parent.callee.type === 'Identifier' &&parent.callee.name === 'alert') {return}if (parent.type === 'CallExpression' &&parent.callee.type === 'MemberExpression' &&parent.callee.object.name === '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) {},CallExpression(path) {}}
}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')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}, {})fs.outputJSONSync('./src/lang/zh.json', jsonData, {spaces: 2})
}
在 vite.config.js 中的使用
import vitePluginBabelTransform from './vite-plugin-babel-transform'
export default defineConfig(({ mode }) => {return {plugins: [vitePluginBabelTransform()]}
})
- 最终会在 src/lang/zh.json 中生成语言包
- 可利用通义千问对键进行驼峰命名,对值进行翻译
- 话术:将以上的键做驼峰命名,值做英文翻译