国际化一般都是使用 i18n 这个库,在开发过程中需要对中英文两个文件内容中添加对应中英文文本,业务代码中使用可读性差。通过下面的脚本可以实现1.业务代码可以直接写$t(中文)。2.不需要创建中英文件。最后只需要将最后生成的内容放在自己项目对应的国际化文件夹下并正确引入就可以了,每次提测前跑一边脚本既可。可以省去很多体力工作,解放双手
使用到的node内置库和方法
内置库:fs(操作文件) path(获取路径) crypto(加密解密)
fs.readdir 读取目录
fs.readFile 读取指定文件的内容
fs.stat 检测是文件还是目录
fs.writeFile 写入文件
fs.rmdir:删除目录
fs.mkdir:创建目录
fs.unlink:删除文件
新增tool/readFlie.js(目的是扫描所有业务层代码中的$t()包含的内容,输出成文件)
// fs.readdir 读取目录
// fs.readFile 读取指定文件的内容
// fs.stat 检测是文件还是目录
// fs.writeFile 写入文件
// fs.rmdir:删除目录
// fs.mkdir:创建目录
// fs.unlink:删除文件
// xxx.isDirectory();//检查目录是否存在的方法
const fs = require('fs');
// 加载 path 模块
const path = require('path');
// 给导出的对象key做转化
const { encrypt } = require('./cryptolalia');
// 默认读取整个业务层文件的位置
const filename = path.resolve(__dirname, '../src');
// 默认需要编译的文件类型
const fileType = ["vue", "js"];
// 存放查找到的所有文件路径
const fileList = [];
// 存放所有文案的集合
const texts = [];
/**
*
* 执行脚本
*
*/
createCatalogue();
/**
*
* 创建i18n目录
*
*/
function createCatalogue() {
const i18nPath = path.resolve(__dirname, '../src/i18n');
try {
//检查某个文件是否存在-不能拿到外面 因为开始没有这层目录statSync方法会抛异常
const stat = fs.statSync(i18nPath);
if (stat.isDirectory()) {
const filePath = path.resolve(__dirname, '../src/i18n/zh.js');
//如果可以执行到这里那么就表示存在了
// 存在此文件夹就删除
fs.unlink(filePath, (error) => {
if (error) {
console.log('删除文件失败');
}
console.log('删除文件成功');
// 写入的位置
const outputFilePath = path.resolve(__dirname, '../src/i18n/zh.js');
createFile(outputFilePath);
});
}
} catch (e) {
//捕获异常
console.log('检查i18n文件夹不存在,创建新的文件夹');
fs.mkdir(i18nPath, (err) => {
if (err) {
console.log('创建文件夹时出错')
} else {
console.log('创建文件成功')
// 写入的位置
const outputFilePath = path.resolve(__dirname, '../src/i18n/zh.js');
createFile(outputFilePath);
}
});
}
}
/**
*
* @param {输出位置} outputPath
* 执行生成文件
*
*/
function createFile(outputPath) {
readDirRecur(filename, function () {
const LENGTH = fileList.length;
fileList.forEach(file => {
// //读取指定文件夹下的VUE和JS文件
fs.readFile(file, "utf-8", function (err, data) {
if (err) {
throw err;
}
// 匹配$t() 包裹的内容
const rge = /\$t\(.*?\)/g
const array = data.match(rge);
// 需要把每个文件内扫描出符合规则的数组在合并到一个新数组中
getText(LENGTH, array, function () {
const obj = {};
texts.forEach(item => {
const firstIndex = item.indexOf("(");
const lastIndex = item.lastIndexOf(")");
let text = item.substring(firstIndex + 2, lastIndex - 1);
// 这里需要使用加密算法包裹,这里没有使用的时候自己加
const h = encrypt(text);
obj[h] = text;
})
// 写入文件
fs.writeFile(outputPath, JSON.stringify(obj), function (err) {
if (err) {
return console.log('文件写入失败!' + err.message);
}
console.log("生成文件成功!");
});
})
})
})
})
}
/**
*
* @param {*} fileList
* @param {*} array
* @param {*} callback
* 获取所有文案
*/
let count = 0;
function getText(LENGTH, array, callback) {
count++;
if (array) {
array.forEach(txt => {
texts.push(txt)
})
}
if (LENGTH === count) {
callback();
}
}
/**
*
* @param {目录位置} folder
* @param {所有文件查找成功的回调} callback
* 读取指定文件 路径,回调函数
*
*/
function readDirRecur(folder, callback) {
// 读取目录
fs.readdir(folder, function (err, files) {
let count = 0;
// 为了最后能执行回调函数成功获取到所有.*结尾的文件
let checkEnd = function () {
++count == files.length && callback()
}
files.forEach(function (file) {
const fullPath = path.resolve(__dirname, folder + '/' + file);
// 检测是文件还是目录
fs.stat(fullPath, function (err, stats) {
if (stats.isDirectory()) {
return readDirRecur(fullPath, checkEnd);
} else {
const suffix = file.split(".")[1];
if (fileType.includes(suffix)) {
fileList.push(fullPath)
}
checkEnd()
}
})
})
//为空时直接回调
files.length === 0 && callback()
})
}
新增tool/restore.js(目的是把生成好的中英文文件给转换成正常的中文key)
// fs.readdir 读取目录
// fs.readFile 读取指定文件的内容
// fs.stat 检测是文件还是目录
// fs.writeFile 写入文件
// fs.rmdir:删除目录
// fs.mkdir:创建目录
// fs.unlink:删除文件
// xxx.isDirectory();//检查目录是否存在的方法
const fs = require('fs');
// 加载 path 模块
const path = require('path');
// 给导出的对象key做转化
const { decrypt } = require('./cryptolalia');
/**
*
* 执行读取脚本
*
*/
restoreFile();
/**
*
* 读取文件内容并转化
*
*/
function restoreFile() {
const filePath = path.resolve(__dirname, '../src/i18n');
// 读取目录
fs.readdir(filePath, (err, files) => {
if (err) {
console.log('读取目录出现错误,请先执行npm run translate');
} else {
console.log('读取目录成功');
files.forEach(file => {
const fullPath = path.resolve(__dirname, filePath + '/' + file);
fs.readFile(fullPath, "utf-8", (err, data) => {
if (err) {
console.log('读取内容出现错误');
}
console.log('读取内容成功');
const object = JSON.parse(data);
const newObject = {};
for (const key in object) {
if (Object.hasOwnProperty.call(object, key)) {
const element = object[key];
const newKey = decrypt(key);
newObject[newKey] = element;
}
}
// 写入文件
fs.writeFile(fullPath, JSON.stringify(newObject), function (err) {
if (err) {
return console.log('文件写入失败!' + err.message);
}
console.log("更新文件成功!");
});
})
})
}
})
}
新增tool/cryptolalia.js(加密文件没什么好介绍的)
const CryptoJS = require("crypto");
// 加密
const encrypt = (content) => {
const nameBuffer = Buffer.from(content); // 等同于 Buffer.from(name, "utf-8")
const enecodedName = nameBuffer.toString("base64");
return enecodedName
}
// 解密
const decrypt = (content) => {
const decodeBuffer = Buffer.from(content, "base64"); // 第二个参数就不能省略了
const decodedName = decodeBuffer.toString("utf-8");
return decodedName
}
//暴露出去
module.exports = {
encrypt,
decrypt
};
脚本有了,使用方式如下
1.打开根目录下package.json,增加两行命令
"scripts": {
"translate": "node ./tool/readFlie.js",
"restore": "node ./tool/restore.js"
},
2.执行npm run translate 生成文件
3.找到src/i18n/zh.js,复制里面的内容
4.将复制的内容在谷歌翻译中进行机翻
5.在src/i18n文件夹中新建en.js
6.将机翻内容粘贴进去并保存
7.执行npm run restore 还原内容
此案例中使用的是VUE框架别的框架暂时还没有尝试,有兴趣的同学可以尝试一些别的框架。