為了應(yīng)對(duì)多語言開發(fā),之前弄了一個(gè)腳本,根據(jù)項(xiàng)目文件里被標(biāo)記詞語(如lang[xxx]),跑一下就生成json文件,然后交付給翻譯同事
最懶的前端多語言策略(一)
開發(fā)久了,發(fā)現(xiàn)懶得連跑腳本都不想跑了,想全自動(dòng)生成,無意中看到umi文檔插件部分,看到有個(gè)api

umi 事件類 API
生成邏輯在上一篇的基礎(chǔ)上基本一樣,把它放在onDevCompileDone里面就行了
export default (api, {
entry = './src',
output,
increment = true,
word = 'lang'
} = {}) => {
api.onStart(() => {
if (!output) {
throw new Error('output必填')
}
})
api.onDevCompileDone(() => {
const fs = require('fs')
const readline = require('readline')
const path = require('path')
const reg = /(trans\(.*\))/gi
const dispose = /\/\//
const obj = {}
const separator = `${word}[` // 分隔符
const suffix = ['.js', '.jsx'] // 后綴白名單
let readNum = 0 // 計(jì)數(shù)還剩未讀的文件數(shù)
console.log('-----start-----')
function readFileToObj(fReadName, value, callback) {
var fRead = fs.createReadStream(fReadName)
var objReadline = readline.createInterface({
input: fRead,
});
objReadline.on('line', line => {
// 注釋的忽略
if (line.includes('//') || line.includes('*')) {
return
}
if (line) {
const arr = line.split(separator)
if (arr.length > 1) {
const bb = arr.slice(1)
for (let i in bb) {
const v0 = bb[i].split(']')[0]
const v = v0.substr(1, v0.length - 2)
if (!v) {
// 空輸出提示
console.warn(`空行為:${line}`)
continue
}
// 增量就不覆蓋了
if (increment && value && value[v]) {
obj[v] = value[v]
} else {
obj[v] = v
}
}
}
}
})
objReadline.on('close', () => {
// 文件都讀過了,寫進(jìn)生成文件
if (--readNum === 0) {
let result = JSON.stringify(obj, null, 2)
fs.writeFile(output, result, err => {
if (err) {
console.warn(err)
}
})
callback && callback()
}
})
}
const filePath = path.resolve(entry)
// 遞歸執(zhí)行,直到判斷是文件就執(zhí)行readFileToObj
function fileDisplay(filePath, value, callback) {
fs.readdir(filePath, (err, files) => {
let count = 0
function checkEnd() {
if (++count === files.length && callback) {
callback()
}
}
if (err) {
console.warn(err)
} else {
files.forEach(filename => {
var fileDir = path.join(filePath, filename)
fs.stat(fileDir, (err2, status) => {
if (err2) {
console.warn(err2)
} else {
if (status.isDirectory()) {
return fileDisplay(fileDir, value, checkEnd)
}
else if (status.isFile()) {
// 后綴不符合的跳過,并計(jì)數(shù)加一
if (suffix.includes(path.extname(fileDir))) {
readNum++
readFileToObj(fileDir, value)
}
}
checkEnd()
}
})
})
}
})
}
// 開始邏輯
function run() {
new Promise((resolve, reject) => {
fs.exists(output, exists => {
// 存在且增量生成
if (exists && increment) {
console.log('增量更新')
fs.readFile(output, 'utf-8', (err, data) => {
if (err) {
console.warn(err)
} else {
try {
// 舊文件已存在的json
const json = JSON.parse(data)
resolve(json)
} catch (e) {
// 翻車
console.warn(e)
}
}
})
} else {
console.log('全量更新')
resolve()
}
})
}).then(value => {
let startTime = Date.now()
fileDisplay(filePath, value, function (value) {
console.log('finish:', Date.now() - startTime)
})
})
}
run()
});
};
.umirc.js
...
export default {
plugins: [
['umi-plugin-gtj', {
entry: './src',
output: './src/lang/en.json',
increment: true, // 是否增量
word: 'lang', // 生成標(biāo)記
}]
]
...
}

效果