利用 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 中生成语言包 可利用通义千问对键进行驼峰命名,对值进行翻译 话术:将以上的键做驼峰命名,值做英文翻译