识别umi react项目 一个文件中的中文
let a = "你是个笨蛋" 这样子的识别不了
标签中的中文要用span 或者p标签 包起来 不可以截断
多层级抓取 需要创建同层级存放结果文件辅助
const fs = require('fs');
const CryptoJS = require('crypto-js');
const axios = require('axios');
const path = require('path');
const dictionary = require('./dictionary.js');
type chineseObj = {
index: number;
text: string;
type: string;
};
const folderChoices = findCurFolderDirectory();
console.log(
'🚀 ~ file: find-chinese.ts ~ line 15 ~ folderChoices',
folderChoices
);
// 手动参数
// const path = 'appGroupManagement'; //同等级下的文件名称
// 结果参数
var enObj: { [key: string]: string } = {}; // 所有键值对 - 英
var temp: string = ''; // 单文件字符串内容
var fileArr: string[] = [];
// getDictionary();
// replaceChinese();
// 生成词典文件
export async function getDictionary() {
fun(path); // 抓文件
for (let e of fileArr) {
const { curPageChineseArr, transArr } = await dealPageFun(e);
for (let { text, index } of curPageChineseArr) {
let key = newKeyFun(text, transArr[index]);
enObj[text] = key;
}
}
writeDictionaryFun(enObj);
}
// 替换页面中文
export async function replaceChinese(): Promise<void> {
fun(path); // 抓文件
for (let e of fileArr) {
const { curPageChineseArr, transArr } = await dealPageFun(e);
for (let { text, type, index } of curPageChineseArr) {
let key = newKeyFun(text, transArr[index]);
enObj[key] = text;
replaceSlotFun(index, key, type);
}
writeFileFun(path, temp);
}
writeEnFun(enObj);
generateOtrLanguageFun('ja');
}
// 识别文件 全同步
function fun(path: string) {
const stats = fs.statSync(path);
// 是tsx文件 不是less文件
if (stats.isFile() && path.indexOf('.less') == -1) {
fileArr.push(path);
}
// 是目录 去查他下面的所有文件
if (stats.isDirectory()) {
const files = fs.readdirSync(path + '/');
// 遍历文件夹下面所有的文件名
for (let e of files) {
// mac系统会有这个文件 这个文件就跳过
if (e == '.DS_Store') return null;
fun(`${path}/${e}`);
}
}
}
// 识别 当前目录下的所有文件
function findCurFolderDirectory(): string[] {
const list: string[] = [];
const parentFile = path.resolve(__dirname, './') + '/';
const files = fs.readdirSync(parentFile);
for (let e of files) {
e == '.DS_Store' || e == 'find-chinese.ts' ? '' : list.push(e);
}
return list;
}
// 获取中文数组 和 翻译数组
async function dealPageFun(path: string) {
temp = readFileFun(path);
let curPageChineseArr: chineseObj[] = [];
let transArr: string[] = [];
// 拿中文
curPageChineseArr = findChinese();
if (curPageChineseArr.length == 0) {
return { curPageChineseArr, transArr };
}
const chiArr = curPageChineseArr.map((e) => e?.text);
console.log('中文--' + path + '--');
console.log(chiArr);
// 翻译
transArr = await translateFun(chiArr.join('\n'), 'en');
console.log('翻译--' + path + '--');
console.log(transArr);
return { curPageChineseArr, transArr };
}
/*
找到汉字 换成插槽 三种情况
="xxx" => ={intl.formatMessage({ id: 'xxx' })} title placeholder label value
"xxx" || 'xxx' => intl.formatMessage({ id: 'xxx' }) 对象和new Error里面的文字 正则
>xxx</ => {intl.formatMessage({ id: 'xxx' })} 标签里面的汉字 全部替换 有个要求 标签里面不要写备注 文字必须用span或者p标签包起来
temp 页面字符串
*/
function findChinese() {
// 保存本页中文的对象
let chineseArr: chineseObj[] = [];
let index = 0;
// ="xxx" propsText
temp = temp.replace(/(=")([\u4e00-\u9fa5,。!?;]+)"/g, (str) => {
chineseArr.push({ text: str.slice(2, -1), type: 'propsText', index });
return `@=${index++}=#`;
});
// "xxx" || 'xxx' objText
temp = temp.replace(/(['"])([\u4e00-\u9fa5,。!?;]+)\1/g, (str) => {
chineseArr.push({ text: str.slice(1, -1), type: 'objText', index });
return `@=${index++}=#`;
});
// >xxx</ tagText
temp = temp.replace(
/(>)([\u4e00-\u9fa5,。!?;a-zA-Z,.!?]+)(<\/)/g,
(str) => {
chineseArr.push({ text: str.slice(1, -2), type: 'tagText', index });
return `@=${index++}=#`;
}
);
return chineseArr;
}
// 翻译 传入中文字符串 用\n分割 返回翻译好的数组
function translateFun(query = '', to: string): Promise<string[]> {
let appKey = '4c45db8c6b1cd6ac';
let key = 'CbRY2Jgdp2RrFDrUBRryNDvzDpHnsHxN';
let curtime = Math.round(new Date().getTime() / 1000);
let salt = 'abuuio' + Math.round(Math.random() * 100);
let str1 = appKey + truncate(query) + salt + curtime + key;
let sign = CryptoJS.SHA256(str1).tostring(CryptoJS.enc.Hex);
let url = 'https://openapi.youdao.com/api';
const params = {
q: query,
from: 'zh-CHS',
to,
appKey,
salt,
sign,
signType: 'v3',
curtime: curtime,
};
// console.log(params)
// 请求格式 表单
axios.defaults.headers.post['content-Type'] =
'application/x-www-form-urlencoded;charset=UTF-8';
axios.defaults.transformRequest = [
function (data: { [x: string]: string | number | boolean }) {
let ret = '';
for (let it in data) {
ret +=
encodeURIComponent(it) + '=' + encodeURIComponent(data[it]) + '&';
}
return ret;
},
];
return new Promise((resolve) => {
axios
.post(url, params)
.then(function ({ data }: any) {
const { errorCode, translation } = data;
if (errorCode == '0') {
resolve(translation[0].split('\n') || []);
} else {
console.log('翻译接口错误 错误代码 --', errorCode);
}
})
.catch(function () {
console.log('axios 错误');
});
});
// input
function truncate(q: string) {
var len = q.length;
if (len <= 20) return q;
return q.substring(0, 10) + len + q.substring(len - 10, len);
}
}
// 生成key 包括去重 截取
function newKeyFun(chi: string, en: string): string {
// 匹配词典
if (dictionary.hasOwnProperty(chi)) {
return dictionary[chi];
}
// 标点 替换成 "_"
let key = en.toLocaleLowerCase().replace(/[\s,.!?]+/g, '_');
// key去重
while (enObj.hasOwnProperty(key)) {
if (enObj[key] == chi) {
break;
} else {
key += 'm';
}
}
// 如果最后一位是 "_" 则删除
let lastChar = key.charAt(key.length - 1);
if (lastChar == '_') {
key = key.slice(0, -1);
}
return key;
}
// 替换插槽
function replaceSlotFun(index: number, key: string, type: string) {
let slot = `@=${index}=#`;
switch (type) {
case 'propsText':
temp = temp.replace(slot, `={intl.formatMessage({ id: '${key}' })}`);
break;
case 'objText':
temp = temp.replace(slot, `intl.formatMessage({ id: '${key}' })`);
break;
case 'tagText':
temp = temp.replace(slot, `>{intl.formatMessage({ id: '${key}' })}</`);
break;
}
}
// 根据英文的json文件 生成其他语言的文件
async function generateOtrLanguageFun(lan: string) {
let jaObj: { [key: string]: string } = {};
let values = Object.values(enObj);
let keys = Object.keys(enObj);
let transArr = await translateFun(values.join('\n'), lan);
keys.forEach((val, index) => {
jaObj[val] = transArr[index];
});
writeJaFun(jaObj);
console.log('🚀 生成日语文件');
}
// 写入词典json
function writeDictionaryFun(obj: Object) {
let json =
'module.exports = index =' + JSON.stringify(obj).replaceAll('","', '",\n"');
writeFileFun('dictionary.js', json);
console.log('写入词典--' + path + '--' + json);
}
// 写入英文json
function writeEnFun(obj: Object) {
let json =
'const index = ' +
JSON.stringify(obj)
.replaceAll(',"', ',\n')
.replaceAll('":', ': ')
.replace('{"', '{');
writeFileFun('en-json.js', json);
}
// 写入日本json
function writeJaFun(obj: Object) {
let json =
'const index = \n' +
JSON.stringify(obj)
.replaceAll('","', '",\n')
.replaceAll('":"', ':"')
.replace('{"', '{');
writeFileFun('ja-json.js', json);
}
// 读文件 同步
function readFileFun(path: string) {
const data = fs.readFileSync(path);
return data.tostring();
}
// 写文件 异步
function writeFileFun(path: string, content: string) {
fs.writeFile(path, content, function (err: Error) {
if (err) {
return console.error(err);
}
console.log(path, '写入文件完成!');
});
}