td-octopus 0.0.3 → 0.0.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/cmds/resource.js +15 -0
- package/package.json +2 -1
- package/src/extract/extract.js +1 -1
- package/src/extract/replace.js +1 -2
- package/src/resource/extract.js +151 -0
- package/src/translate/index.js +3 -4
- package/src/utils/const.js +5 -1
- package/src/{extract → utils}/file.js +0 -0
- package/src/utils/syncLang.js +21 -22
package/cmds/resource.js
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
const fs = require('fs');
|
|
2
|
+
const { isString } = require('lodash');
|
|
3
|
+
const { extractAll } = require('../src/resource/extract');
|
|
4
|
+
|
|
5
|
+
exports.command = 'resource [dirPath] [resourcePath]';
|
|
6
|
+
|
|
7
|
+
exports.describe = 'resource [dirPath] [resourcePath] resourcePath 为目前系统已翻译的文件目录;一键批量替换指定文件夹下的所有 this.resource';
|
|
8
|
+
|
|
9
|
+
exports.handler = async (argv) => {
|
|
10
|
+
extractAll({
|
|
11
|
+
dirPath: isString(argv.dirPath) && argv.dirPath,
|
|
12
|
+
resourcePath: isString(argv.resourcePath) && argv.resourcePath,
|
|
13
|
+
});
|
|
14
|
+
}
|
|
15
|
+
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "td-octopus",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.5",
|
|
4
4
|
"description": "I18N tool",
|
|
5
5
|
"author": "Anthony Li",
|
|
6
6
|
"bin": {
|
|
@@ -18,6 +18,7 @@
|
|
|
18
18
|
"ora": "^5.4.1",
|
|
19
19
|
"pinyin-pro": "^3.3.1",
|
|
20
20
|
"prettier": "^2.7.1",
|
|
21
|
+
"properties": "^1.2.1",
|
|
21
22
|
"shelljs": "^0.8.5",
|
|
22
23
|
"slash2": "^2.0.0",
|
|
23
24
|
"ts-node": "^10.8.1",
|
package/src/extract/extract.js
CHANGED
|
@@ -2,7 +2,7 @@ const slash = require('slash2');
|
|
|
2
2
|
const _ = require('lodash');
|
|
3
3
|
const path = require('path');
|
|
4
4
|
|
|
5
|
-
const { getSpecifiedFiles, readFile, writeFile, isFile, isDirectory } = require('
|
|
5
|
+
const { getSpecifiedFiles, readFile, writeFile, isFile, isDirectory } = require('../utils/file');
|
|
6
6
|
const { translateText, findMatchKey, findMatchValue, translateKeyText, getProjectConfig } = require('../utils');
|
|
7
7
|
const { successInfo, failInfo, highlightText } = require('../utils/colors');
|
|
8
8
|
const { findChineseText } = require('./findChineseText');
|
package/src/extract/replace.js
CHANGED
|
@@ -4,8 +4,7 @@
|
|
|
4
4
|
const _ = require('lodash');
|
|
5
5
|
const prettier = require('prettier');
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
const { getSpecifiedFiles, readFile, writeFile, isFile, isDirectory } = require('./file');
|
|
7
|
+
const { getSpecifiedFiles, readFile, writeFile, isFile, isDirectory } = require('../utils/file');
|
|
9
8
|
const {
|
|
10
9
|
translateText,
|
|
11
10
|
findMatchKey,
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
const slash = require('slash2');
|
|
2
|
+
const _ = require('lodash');
|
|
3
|
+
const path = require('path');
|
|
4
|
+
const Parser = require('properties');
|
|
5
|
+
|
|
6
|
+
const { getSpecifiedFiles, readFile, writeFile, isFile, isDirectory } = require('../utils/file');
|
|
7
|
+
const { translateText, findMatchKey, findMatchValue, translateKeyText, getProjectConfig } = require('../utils');
|
|
8
|
+
const { successInfo, failInfo, highlightText } = require('../utils/colors');
|
|
9
|
+
|
|
10
|
+
const CONFIG = getProjectConfig();
|
|
11
|
+
|
|
12
|
+
function formatExclude(exclude) {
|
|
13
|
+
return (exclude || []).map(p => path.resolve(process.cwd(), p));
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
const findAllCnFile = (dir) => {
|
|
17
|
+
const first = dir.split(',')[0];
|
|
18
|
+
|
|
19
|
+
let files = [];
|
|
20
|
+
if (isDirectory(first)) {
|
|
21
|
+
const dirPath = path.resolve(process.cwd(), dir);
|
|
22
|
+
files = getSpecifiedFiles(dirPath, formatExclude(CONFIG.exclude));
|
|
23
|
+
} else {
|
|
24
|
+
files = removeLangsFiles(dir.split(','));
|
|
25
|
+
}
|
|
26
|
+
const filterFiles = files.filter(file => {
|
|
27
|
+
let flag = false;
|
|
28
|
+
flag = (file.endsWith('.properties') && file.indexOf('cn.properties') !== -1);
|
|
29
|
+
return (isFile(file) && flag);
|
|
30
|
+
});
|
|
31
|
+
return filterFiles
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
function findAllCnFileSrc(dir, keyMap) {
|
|
35
|
+
const first = dir.split(',')[0];
|
|
36
|
+
|
|
37
|
+
let files = [];
|
|
38
|
+
if (isDirectory(first)) {
|
|
39
|
+
const dirPath = path.resolve(process.cwd(), dir);
|
|
40
|
+
files = getSpecifiedFiles(dirPath, formatExclude(CONFIG.exclude));
|
|
41
|
+
} else {
|
|
42
|
+
files = removeLangsFiles(dir.split(','));
|
|
43
|
+
}
|
|
44
|
+
const filterFiles = files.filter(file => {
|
|
45
|
+
let flag = false;
|
|
46
|
+
for (let index = 0; index < CONFIG.fileSuffix.length; index++) {
|
|
47
|
+
const element = CONFIG.fileSuffix[index];
|
|
48
|
+
flag = file.endsWith(element);
|
|
49
|
+
if (flag) {
|
|
50
|
+
break;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
return (isFile(file) && flag);
|
|
54
|
+
});
|
|
55
|
+
let replaceList = []
|
|
56
|
+
let list = []
|
|
57
|
+
let errorList = []
|
|
58
|
+
for (let index = 0; index < filterFiles.length; index++) {
|
|
59
|
+
const file = filterFiles[index];
|
|
60
|
+
let code = readFile(file);
|
|
61
|
+
const pathKey = regPathSrc(file);
|
|
62
|
+
replaceList = []
|
|
63
|
+
const regRresource1 = new RegExp('this\\.resource\\([\'|\"](\\S*?)[\'|\"]\\)', 'g')
|
|
64
|
+
const regRresource = new RegExp('this\\.resource\\([\'|\"](\\S*?)[\'|\"]\\)', 'g')
|
|
65
|
+
if (regRresource1.test(code)) {
|
|
66
|
+
if (keyMap[pathKey] && errorList.length === 0) {
|
|
67
|
+
let r = "";
|
|
68
|
+
while (r = regRresource.exec(code)) {
|
|
69
|
+
replaceList.push({
|
|
70
|
+
source: r[0],
|
|
71
|
+
key: r[1]
|
|
72
|
+
})
|
|
73
|
+
list.push({
|
|
74
|
+
source: r[0],
|
|
75
|
+
key: r[1]
|
|
76
|
+
})
|
|
77
|
+
}
|
|
78
|
+
console.log(`${highlightText(file)} 发现 ${highlightText(replaceList.length)} 处 this.resource`);
|
|
79
|
+
for (let index = 0; index < replaceList.length; index++) {
|
|
80
|
+
const item = replaceList[index];
|
|
81
|
+
code = code.replace(item.source, `'${keyMap[pathKey][item.key] ? keyMap[pathKey][item.key] : keyMap['common'][item.key]}'`)
|
|
82
|
+
}
|
|
83
|
+
writeFile(file, code);
|
|
84
|
+
} else {
|
|
85
|
+
errorList.push(file);
|
|
86
|
+
failInfo(`${file} 文件目录没匹配`);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
return errorList.length ? [] : list;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
const regPath = (file) => {
|
|
95
|
+
const tempPath = CONFIG.regPath ? CONFIG.regPath : 'locale'
|
|
96
|
+
const reg = new RegExp(`${tempPath}\/(\\S*?)\/cn\.`, 'g');
|
|
97
|
+
const list = reg.exec(file)
|
|
98
|
+
return list ? list[1].toLocaleLowerCase() : ''
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
const regPathSrc = (file) => {
|
|
102
|
+
const reg = new RegExp(`src\/(\\S*)[\/|\.]?`, 'g');
|
|
103
|
+
const list = reg.exec(file)
|
|
104
|
+
let temp = list[1] ? list[1].toLocaleLowerCase() : ''
|
|
105
|
+
temp = temp.split('/')
|
|
106
|
+
let str = temp[0] + '/' + temp[1]
|
|
107
|
+
if (temp[0] === 'routes' || temp[0] === 'pages') {
|
|
108
|
+
str = temp[1] + '/' + temp[2]
|
|
109
|
+
}
|
|
110
|
+
return str
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
/**
|
|
114
|
+
* 递归匹配项目中所有的代码的中文
|
|
115
|
+
* @param {dirPath} 文件夹路径
|
|
116
|
+
*/
|
|
117
|
+
function extractAll({ dirPath, resourcePath }) {
|
|
118
|
+
const dirArr = dirPath ? [dirPath] : CONFIG.include && CONFIG.include.length > 0 ? CONFIG.include : ['./'];
|
|
119
|
+
|
|
120
|
+
const dirResourceArr = resourcePath ? [resourcePath] : CONFIG.resourcePath && CONFIG.resourcePath.length > 0 ? CONFIG.resourcePath : ['./'];
|
|
121
|
+
|
|
122
|
+
const allFlies = _.flatten(dirResourceArr.map(findAllCnFile));
|
|
123
|
+
let allKeyObj = {}
|
|
124
|
+
allFlies.forEach((file) => {
|
|
125
|
+
let code = readFile(file);
|
|
126
|
+
Parser.parse(code, {}, (err, obj) => {
|
|
127
|
+
if (err) {
|
|
128
|
+
console.log(err);
|
|
129
|
+
} else {
|
|
130
|
+
const pathKey = regPath(file);
|
|
131
|
+
allKeyObj[pathKey] = obj
|
|
132
|
+
}
|
|
133
|
+
});
|
|
134
|
+
});
|
|
135
|
+
|
|
136
|
+
|
|
137
|
+
const allTargetStrs = _.flatten(dirArr.map((dir) => {
|
|
138
|
+
return findAllCnFileSrc(dir, allKeyObj)
|
|
139
|
+
}));
|
|
140
|
+
|
|
141
|
+
|
|
142
|
+
if (allTargetStrs.length === 0) {
|
|
143
|
+
console.log(highlightText('以上文件中没有发现源文件 this.resource!'), allTargetStrs);
|
|
144
|
+
return;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
successInfo('替换成功!')
|
|
148
|
+
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
module.exports = { extractAll };
|
package/src/translate/index.js
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
* @Author: 郑泳健
|
|
4
4
|
* @Date: 2022-06-01 13:56:18
|
|
5
5
|
* @LastEditors: 郑泳健
|
|
6
|
-
* @LastEditTime: 2022-
|
|
6
|
+
* @LastEditTime: 2022-12-28 15:47:31
|
|
7
7
|
*/
|
|
8
8
|
const {
|
|
9
9
|
syncFiles,
|
|
@@ -33,13 +33,12 @@ function translate() {
|
|
|
33
33
|
spinner.start('正在同步文件')
|
|
34
34
|
await syncFiles(distLang);
|
|
35
35
|
spinner.succeed('同步文件成功')
|
|
36
|
-
await syncLang();
|
|
37
36
|
|
|
38
|
-
const
|
|
37
|
+
const zhCN = syncLang('zh-CN');
|
|
39
38
|
const zhCNflat = flatObject(zhCN);
|
|
40
39
|
|
|
41
40
|
for (const lang of distLang) {
|
|
42
|
-
const
|
|
41
|
+
const currentLangMap = syncLang(lang);
|
|
43
42
|
const langFlat = flatObject(currentLangMap);
|
|
44
43
|
spinner.start('正在同步文件的key')
|
|
45
44
|
// 删除掉多余的key,增加新的key,同时提取没有翻译过的key的列表
|
package/src/utils/const.js
CHANGED
|
@@ -23,7 +23,11 @@ const PROJECT_CONFIG = {
|
|
|
23
23
|
defaultTranslateKeyApi: 'Pinyin', // 批量提取文案时生成key值时的默认翻译源
|
|
24
24
|
importI18N: `import I18N from 'src/utils/I18N';`,
|
|
25
25
|
include:['./src'],
|
|
26
|
-
exclude:[]
|
|
26
|
+
exclude:[],
|
|
27
|
+
regPath: 'locale', // 正则匹配路径地址使用
|
|
28
|
+
resourcePath: [
|
|
29
|
+
"./src/constants/locale"
|
|
30
|
+
],
|
|
27
31
|
},
|
|
28
32
|
langMap: {
|
|
29
33
|
['en-US']: 'en',
|
|
File without changes
|
package/src/utils/syncLang.js
CHANGED
|
@@ -1,25 +1,24 @@
|
|
|
1
|
-
require('
|
|
2
|
-
|
|
3
|
-
module: 'commonjs'
|
|
4
|
-
}
|
|
5
|
-
});
|
|
6
|
-
const shell = require('shelljs');
|
|
7
|
-
const path = require('path');
|
|
8
|
-
const {
|
|
9
|
-
otpPath,
|
|
10
|
-
changeFileSuffix,
|
|
11
|
-
getNeedChangeNameFileList
|
|
12
|
-
} = require('./translate');
|
|
1
|
+
const fs = require('fs')
|
|
2
|
+
const { otpPath } = require('./translate');
|
|
13
3
|
|
|
4
|
+
module.exports = (lang) => {
|
|
5
|
+
try {
|
|
6
|
+
const list = fs.readdirSync(otpPath + '/' + lang);
|
|
7
|
+
let langMap = {};
|
|
8
|
+
list.forEach((i) => {
|
|
9
|
+
const suffixCheck = ['.js', '.ts', '.jsx', 'tsx'].some(it => i.endsWith(it));
|
|
10
|
+
if (suffixCheck && !['index.js', 'index.jsx', 'index.ts', 'index.tsx'].includes(i)) {
|
|
11
|
+
const str = fs.readFileSync(`${otpPath}/${lang}/${i}`, 'utf-8');
|
|
12
|
+
const replaceStr = str.replace(/export default|\;/g, '');
|
|
13
|
+
const json = eval("(" + replaceStr + ")");
|
|
14
|
+
const key = i.split('.')[0];
|
|
14
15
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
await changeFileSuffix(filelist, '.js', '.ts')
|
|
16
|
+
langMap[key] = json;
|
|
17
|
+
}
|
|
18
|
+
});
|
|
19
|
+
return langMap
|
|
20
|
+
}catch (e) {
|
|
21
|
+
console.log(e.message, 'e.message')
|
|
22
|
+
return {}
|
|
23
|
+
}
|
|
25
24
|
}
|