利用 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.parent
if (
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] = cur
return 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] = cur
return prev
}, {})
jsonData[prefix] = data
jsonData = 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 中生成语言包
- 可利用通义千问对键进行驼峰命名,对值进行翻译
- 话术:将以上的键做驼峰命名,值做英文翻译