@chaoswise/intl 1.2.0 → 1.2.1
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/bin/scripts/collect.js +18 -5
- package/bin/scripts/conf/default.js +14 -14
- package/bin/scripts/conf/initConfig.js +2 -2
- package/bin/scripts/service/index.js +13 -3
- package/bin/scripts/update.js +4 -3
- package/bin/scripts/util/makeVisitorCollect.js +59 -28
- package/bin/scripts/util/makeVisitorUpdate.js +1 -1
- package/bin/scripts/util/transformAst.js +12 -1
- package/bin/scripts/util/writeNewWordsFile.js +1 -1
- package/package.json +2 -2
package/bin/scripts/collect.js
CHANGED
|
@@ -7,12 +7,16 @@ const log = require('./util/log');
|
|
|
7
7
|
const file = require('./util/file');
|
|
8
8
|
const writeNewWordsFile = require('./util/writeNewWordsFile');
|
|
9
9
|
const { readWordJson } = require('./util/getWord');
|
|
10
|
+
const getGroupName = require('./util/getGroupName');
|
|
10
11
|
|
|
11
12
|
const service = require('./service');
|
|
12
13
|
|
|
13
14
|
async function collect() {
|
|
14
|
-
|
|
15
|
+
|
|
16
|
+
log.info('工程扫描中...')
|
|
17
|
+
|
|
15
18
|
const conf = getConf();
|
|
19
|
+
const groupName = getGroupName();
|
|
16
20
|
const newWordsFileType = conf.newWordsFileType || 'excel';
|
|
17
21
|
|
|
18
22
|
// 检查newWordsFileType
|
|
@@ -36,6 +40,8 @@ async function collect() {
|
|
|
36
40
|
|
|
37
41
|
// 在国际化平台中获取所有已存在中文信息
|
|
38
42
|
const res = await service.searchByZh(info.allWords);
|
|
43
|
+
// 在国际化平台记录特殊方法
|
|
44
|
+
await service.saveMethod({ groupName, specialMethod: info.specialMethod });
|
|
39
45
|
|
|
40
46
|
if (res.code !== 10000) {
|
|
41
47
|
log.error('请求数据出错:' + res.msg);
|
|
@@ -46,10 +52,13 @@ async function collect() {
|
|
|
46
52
|
|
|
47
53
|
const replaceWords = {}; // { zh: id } 需要在代码中替换的词条id
|
|
48
54
|
const newWords = {}; // { zh1: '待翻译', zh2: '请选择:中文1/中文2' }
|
|
55
|
+
const exist = {}; // 根据中文只查出一条数据的已有词条
|
|
49
56
|
Object.entries(wordsMap).forEach(([word, value]) => {
|
|
50
57
|
// 如果当前中文词条在平台中存在,且对应英文翻译有且只有一条,那么直接替换代码中的中文为当前id,否则生成临时key,让开发者手动确认
|
|
51
58
|
if (value.length === 1) {
|
|
52
|
-
|
|
59
|
+
const { id, key, zh, en } = value[0];
|
|
60
|
+
replaceWords[word] = key;
|
|
61
|
+
exist[id] = { id, key, zh, en };
|
|
53
62
|
} else {
|
|
54
63
|
const id = uuidv4();
|
|
55
64
|
replaceWords[word] = id;
|
|
@@ -65,11 +74,15 @@ async function collect() {
|
|
|
65
74
|
}
|
|
66
75
|
});
|
|
67
76
|
|
|
77
|
+
|
|
78
|
+
// 在国际化平台中保存所有已存在词条
|
|
79
|
+
await service.saveExist({groupName, exist});
|
|
80
|
+
|
|
68
81
|
// 第二次遍历,传入replaceWords,对代码进行国际化通用API转化,把词条替换成数据库的id,或者脚本临时生成的uuid
|
|
69
82
|
transformAst('collect', files, conf, replaceWords);
|
|
70
83
|
|
|
71
|
-
log.success('脚本执行成功');
|
|
72
|
-
log.
|
|
84
|
+
log.success('★★★ 脚本执行成功 ★★★');
|
|
85
|
+
log.info('国际化配置文件: .intlconfig.js,可根据需求自定义修改');
|
|
73
86
|
// 本次扫描出新的待翻译词条,写入到newWords中
|
|
74
87
|
if (Object.keys(newWords).length) {
|
|
75
88
|
writeNewWordsFile(newWordsFileType, newWords);
|
|
@@ -79,7 +92,7 @@ async function collect() {
|
|
|
79
92
|
if (warnLogs.length) {
|
|
80
93
|
const fileName = `intl.logs.warn.${(new Date).toLocaleString().replace(/[\/ ]/g, '_')}.txt`;
|
|
81
94
|
file.write(fileName, JSON.stringify(warnLogs, null, 2));
|
|
82
|
-
log.
|
|
95
|
+
log.warn(`存在脚本无法处理的情况,具体查看 ${fileName} 手动处理`);
|
|
83
96
|
}
|
|
84
97
|
}
|
|
85
98
|
|
|
@@ -55,30 +55,30 @@ module.exports = function (excludes = []) {
|
|
|
55
55
|
endOfLine: 'lf',
|
|
56
56
|
},
|
|
57
57
|
|
|
58
|
-
// <
|
|
59
|
-
// intlTag 是 '
|
|
60
|
-
// intlTagIdPath 是 'id
|
|
58
|
+
// <FormattedMessage id='id' defaultMessage='中文' />
|
|
59
|
+
// intlTag 是 'FormattedMessage'
|
|
60
|
+
// intlTagIdPath 是 'id'
|
|
61
61
|
// intlTagDefaultWordPath 是 'defaultMessage',并且如果不配置,默认是'defaultMessage'
|
|
62
|
-
intlTag: '',
|
|
63
|
-
intlTagIdPath: '',
|
|
64
|
-
intlTagDefaultWordPath: '',
|
|
62
|
+
intlTag: 'FormattedMessage',
|
|
63
|
+
intlTagIdPath: 'id',
|
|
64
|
+
intlTagDefaultWordPath: 'defaultMessage',
|
|
65
65
|
|
|
66
66
|
// intl.formatMessage({
|
|
67
|
-
//
|
|
67
|
+
// id: 'id',
|
|
68
68
|
// defaultMessage: '默认值',
|
|
69
69
|
// })
|
|
70
70
|
// intlFunctionName 是 intl.formatMessage
|
|
71
|
-
// intlFunctionIdPath 是 '0.
|
|
71
|
+
// intlFunctionIdPath 是 '0.id'。 如果 配置成 'id' 也行,intlFunctionIdPath如果不以数字开头,会在前面加上'0.' 'id' 就会变成 '0.id'
|
|
72
72
|
// intlFunctionDefaultWordPath 是 '0.defaultMessage',其他的说明同intlFunctionIdPath
|
|
73
|
-
intlFunctionName: '',
|
|
74
|
-
intlFunctionIdPath: '',
|
|
75
|
-
intlFunctionDefaultWordPath: '',
|
|
73
|
+
intlFunctionName: 'intl.formatMessage',
|
|
74
|
+
intlFunctionIdPath: 'id',
|
|
75
|
+
intlFunctionDefaultWordPath: 'defaultMessage',
|
|
76
76
|
|
|
77
77
|
// 做过国际化的项目,中文config的路径。例如:'src/local/zh.json'
|
|
78
78
|
localWordPath: '',
|
|
79
79
|
|
|
80
80
|
// 配置 需要被脚本删除的依赖包的名字
|
|
81
|
-
removePkgName: [],
|
|
81
|
+
removePkgName: ['react-intl'],
|
|
82
82
|
|
|
83
83
|
// 需要删除的函数和装饰器 的名称
|
|
84
84
|
removeFunctionName: ['injectIntl'],
|
|
@@ -86,8 +86,8 @@ module.exports = function (excludes = []) {
|
|
|
86
86
|
// package.json中项目名称的key
|
|
87
87
|
groupNameKey: 'packageName',
|
|
88
88
|
|
|
89
|
-
//
|
|
90
|
-
specialFileReg: [/
|
|
89
|
+
// 特殊文件处理数组的每一项为正则或者字符串 这里默认匹配router.config.js
|
|
90
|
+
specialFileReg: ['src/config/router.config.js'],
|
|
91
91
|
|
|
92
92
|
// newWords文件的类型 json或者excel
|
|
93
93
|
newWordsFileType: 'excel',
|
|
@@ -10,7 +10,7 @@ module.exports = function initConfig() {
|
|
|
10
10
|
const customConfig = getCustomConfig();
|
|
11
11
|
|
|
12
12
|
if (customConfig) {
|
|
13
|
-
|
|
13
|
+
log.error(`${customConfigName}已存在,请删除后重新执行`);
|
|
14
14
|
return;
|
|
15
15
|
}
|
|
16
16
|
|
|
@@ -33,5 +33,5 @@ module.exports = function initConfig() {
|
|
|
33
33
|
prettier.format(code, { ...defaultConfig.prettier, parser: 'babel' })
|
|
34
34
|
);
|
|
35
35
|
|
|
36
|
-
log.success(
|
|
36
|
+
log.success(`★★★ 初始化配置文件成功:.intlconfig.js ★★★`);
|
|
37
37
|
}
|
|
@@ -3,7 +3,7 @@ const getConf = require('../conf');
|
|
|
3
3
|
|
|
4
4
|
const conf = getConf();
|
|
5
5
|
|
|
6
|
-
axios.defaults.baseURL = (conf.baseURL || '') + '/api/i18n
|
|
6
|
+
axios.defaults.baseURL = (conf.baseURL || '') + '/api/i18n';
|
|
7
7
|
|
|
8
8
|
axios.interceptors.response.use(
|
|
9
9
|
function (response) {
|
|
@@ -20,10 +20,20 @@ axios.interceptors.response.use(
|
|
|
20
20
|
|
|
21
21
|
// 在国际化平台中获取所有已存在中文信息
|
|
22
22
|
exports.searchByZh = (zhs) => {
|
|
23
|
-
return axios.post('/searchByZh', zhs);
|
|
23
|
+
return axios.post('/dictionary/searchByZh', zhs);
|
|
24
24
|
};
|
|
25
25
|
|
|
26
26
|
// 根据词条id获取所有数据库词条信息
|
|
27
27
|
exports.getJson = ({ groupName, downloadIds }) => {
|
|
28
|
-
return axios.post('/getJson', { groupName, downloadIds });
|
|
28
|
+
return axios.post('/dictionary/getJson', { groupName, downloadIds });
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
// 保存替换的特殊方法
|
|
32
|
+
exports.saveMethod = (data) => {
|
|
33
|
+
return axios.post('/history/method/save', data);
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
// 保存已有词条
|
|
37
|
+
exports.saveExist = (data) => {
|
|
38
|
+
return axios.post('/history/exist/save', data);
|
|
29
39
|
};
|
package/bin/scripts/update.js
CHANGED
|
@@ -6,6 +6,7 @@ const log = require('./util/log');
|
|
|
6
6
|
const file = require('./util/file');
|
|
7
7
|
|
|
8
8
|
async function update() {
|
|
9
|
+
log.info('词条更新中...')
|
|
9
10
|
const conf = getConf();
|
|
10
11
|
const files = getTargetFiles(conf);
|
|
11
12
|
|
|
@@ -13,17 +14,17 @@ async function update() {
|
|
|
13
14
|
const relationKey = file.readJson('relationKey.json') || {};
|
|
14
15
|
|
|
15
16
|
const info = transformAst('update', files, conf, relationKey);
|
|
16
|
-
await downloadJson(info.downloadIds);
|
|
17
|
+
await downloadJson(info.downloadIds.filter(Boolean));
|
|
17
18
|
|
|
18
19
|
const needDelete = Boolean(Object.keys(relationKey).length);
|
|
19
20
|
if (needDelete) {
|
|
20
21
|
file.delete('newWords.json');
|
|
21
22
|
file.delete('relationKey.json');
|
|
22
23
|
|
|
23
|
-
log.success('newWords.json和relationKey.json 已删除');
|
|
24
|
+
// log.success('newWords.json和relationKey.json 已删除');
|
|
24
25
|
}
|
|
25
26
|
|
|
26
|
-
log.success('脚本执行成功');
|
|
27
|
+
log.success('★★★ 脚本执行成功 ★★★');
|
|
27
28
|
}
|
|
28
29
|
|
|
29
30
|
// update();
|
|
@@ -32,10 +32,7 @@ module.exports = function (
|
|
|
32
32
|
{ filePath, special },
|
|
33
33
|
) {
|
|
34
34
|
|
|
35
|
-
|
|
36
|
-
intlTagDefaultWordPath = intlTagDefaultWordPath || 'defaultMessage';
|
|
37
|
-
|
|
38
|
-
const { replaceWords, allWords, downloadIds } = returns;
|
|
35
|
+
const { replaceWords, allWords, downloadIds, specialMethod } = returns;
|
|
39
36
|
const hacked = {};
|
|
40
37
|
|
|
41
38
|
// 在没有replaceWords的情况下,不用log信息,这里统一处理
|
|
@@ -62,15 +59,17 @@ module.exports = function (
|
|
|
62
59
|
return preFixPath + path;
|
|
63
60
|
}
|
|
64
61
|
// 插入注释
|
|
65
|
-
function insertFailCommon(node) {
|
|
62
|
+
function insertFailCommon(node, errorMsg) {
|
|
66
63
|
const comment = node?.leadingComments?.value
|
|
67
|
-
|
|
68
|
-
|
|
64
|
+
const errMsg = `${commentStr} ${errorMsg}`;
|
|
65
|
+
if (comment && comment.trim() === errMsg.trim()) return;
|
|
66
|
+
t.addComment(node, 'leading', errMsg);
|
|
69
67
|
}
|
|
70
68
|
// 在jsx中插入注释
|
|
71
|
-
function insertFailCommonInJsx(path) {
|
|
69
|
+
function insertFailCommonInJsx(path, errorMsg) {
|
|
72
70
|
const comment = path?.node?.leadingComments?.value
|
|
73
|
-
|
|
71
|
+
const errMsg = `${commentStr} ${errorMsg}`;
|
|
72
|
+
if (comment && comment.trim() === errMsg.trim()) return;
|
|
74
73
|
path.insertBefore(
|
|
75
74
|
t.jsxExpressionContainer(
|
|
76
75
|
{
|
|
@@ -78,7 +77,7 @@ module.exports = function (
|
|
|
78
77
|
"innerComments": [
|
|
79
78
|
{
|
|
80
79
|
"type": "CommentBlock",
|
|
81
|
-
"value":
|
|
80
|
+
"value": errMsg
|
|
82
81
|
}
|
|
83
82
|
]
|
|
84
83
|
}
|
|
@@ -450,24 +449,43 @@ module.exports = function (
|
|
|
450
449
|
|
|
451
450
|
let value = getWord(chaoswiseIntlId);
|
|
452
451
|
if (!value) {
|
|
453
|
-
let
|
|
454
|
-
if (typeof
|
|
455
|
-
value =
|
|
452
|
+
let defaultValue = FormPath.getIn(chaoswiseIntlIdData, getFullPath(intlFunctionDefaultWordPath));
|
|
453
|
+
if (typeof defaultValue === 'string' && defaultValue) {
|
|
454
|
+
value = defaultValue;
|
|
456
455
|
} else {
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
properLog.warn(
|
|
456
|
+
let errorMsg = '';
|
|
457
|
+
|
|
458
|
+
if (!intlFunctionIdPath) {
|
|
459
|
+
errorMsg = `intlFunctionIdPath未配置`;
|
|
460
|
+
properLog.warn(errorMsg);
|
|
461
|
+
} else {
|
|
462
|
+
if (!chaoswiseIntlId) {
|
|
463
|
+
errorMsg = `在 ${intlFunctionName}() 中未找到 ${intlFunctionIdPath} 对应的值`;
|
|
464
|
+
properLog.warn(`文件 ${filePath} 中,在 ${intlFunctionName}() 中未找到 ${intlFunctionIdPath} 对应的值`);
|
|
465
|
+
} else if(!localWordPath) {
|
|
466
|
+
// 中文json文件未配置
|
|
467
|
+
errorMsg = `国际化中文文件路径 localWordPath 未配置`;
|
|
468
|
+
properLog.warn(errorMsg);
|
|
469
|
+
} else {
|
|
470
|
+
// word找不到
|
|
471
|
+
errorMsg = `国际化中文文件 ${localWordPath} 未找到 ${chaoswiseIntlId} 对应的值`;
|
|
472
|
+
properLog.warn(errorMsg);
|
|
473
|
+
}
|
|
462
474
|
}
|
|
463
|
-
if (intlFunctionDefaultWordPath) {
|
|
464
|
-
|
|
475
|
+
if (intlFunctionDefaultWordPath && !defaultValue) {
|
|
476
|
+
errorMsg = `在 ${intlFunctionName}() 中未找到 ${intlFunctionDefaultWordPath} 对应的值`;
|
|
477
|
+
properLog.warn(`文件 ${filePath} 中,在 ${intlFunctionName} 中未找到 ${intlFunctionDefaultWordPath} 对应的值`);
|
|
465
478
|
}
|
|
466
|
-
|
|
479
|
+
|
|
480
|
+
insertFailCommon(node, errorMsg);
|
|
467
481
|
}
|
|
468
482
|
}
|
|
469
483
|
|
|
470
484
|
if (value && isPrimary(value)) {
|
|
485
|
+
if (!specialMethod.includes(fnName)) {
|
|
486
|
+
specialMethod.push(fnName);
|
|
487
|
+
}
|
|
488
|
+
|
|
471
489
|
res.needReplace = true;
|
|
472
490
|
res.value = value;
|
|
473
491
|
}
|
|
@@ -591,29 +609,42 @@ module.exports = function (
|
|
|
591
609
|
if (typeof defaultValue === 'string') {
|
|
592
610
|
word = defaultValue;
|
|
593
611
|
} else {
|
|
612
|
+
let errorMsg = '';
|
|
594
613
|
if (!intlTagIdPath) {
|
|
595
|
-
|
|
614
|
+
errorMsg = `intlTagIdPath未配置`;
|
|
615
|
+
properLog.warn(errorMsg);
|
|
596
616
|
} else {
|
|
597
617
|
if (!id) {
|
|
598
|
-
|
|
618
|
+
errorMsg = `文件 ${filePath} 中,在<${intlTag} /> 中未找到 ${intlTagIdPath} 对应的值`;
|
|
619
|
+
properLog.warn(`在<${intlTag} /> 中未找到 ${intlTagIdPath} 对应的值`);
|
|
620
|
+
} else if(!localWordPath) {
|
|
621
|
+
// 中文json文件未配置
|
|
622
|
+
errorMsg = `国际化中文文件路径 localWordPath 未配置`;
|
|
623
|
+
properLog.warn(errorMsg);
|
|
599
624
|
} else {
|
|
600
625
|
// word找不到
|
|
601
|
-
|
|
626
|
+
errorMsg = `国际化中文文件 ${localWordPath} 未找到 ${id} 对应的值`;
|
|
627
|
+
properLog.warn(errorMsg);
|
|
602
628
|
}
|
|
603
629
|
}
|
|
604
|
-
if (defaultValue === false) {
|
|
605
|
-
|
|
630
|
+
if (intlTagDefaultWordPath && defaultValue === false) {
|
|
631
|
+
errorMsg = `在<${intlTag} /> 中未找到 ${intlTagDefaultWordPath} 对应的值`;
|
|
632
|
+
properLog.warn(`文件 ${filePath} 在 <${intlTag} /> 中未找到 ${intlTagDefaultWordPath} 对应的值`);
|
|
606
633
|
}
|
|
607
634
|
|
|
608
635
|
if (['JSXFragment', 'JSXElement'].includes(parentNodeType)) {
|
|
609
|
-
insertFailCommonInJsx(path);
|
|
636
|
+
insertFailCommonInJsx(path, errorMsg);
|
|
610
637
|
} else {
|
|
611
|
-
insertFailCommon(node);
|
|
638
|
+
insertFailCommon(node, errorMsg);
|
|
612
639
|
}
|
|
613
640
|
|
|
614
641
|
}
|
|
615
642
|
}
|
|
616
643
|
if (word && isPrimary(word)) {
|
|
644
|
+
if (!specialMethod.includes(jsxName)) {
|
|
645
|
+
specialMethod.push(jsxName);
|
|
646
|
+
}
|
|
647
|
+
|
|
617
648
|
// 替换国际化标签,<FormatMessage id='zhongwenid' defaultMessage="中文" /> 换成 {intl.get(id).d('中文')}
|
|
618
649
|
let res = makeReplace(word);
|
|
619
650
|
|
|
@@ -100,7 +100,7 @@ module.exports = function f(
|
|
|
100
100
|
(node.callee.type === 'MemberExpression' &&
|
|
101
101
|
node.callee.object.name === i18nObject &&
|
|
102
102
|
node.callee.property.name === i18nMethod) ||
|
|
103
|
-
(node.callee.type === 'Identifier' && node.callee.name === i18nMethod)
|
|
103
|
+
(!i18nObject && node.callee.type === 'Identifier' && node.callee.name === i18nMethod)
|
|
104
104
|
) {
|
|
105
105
|
// 收集现有的 key
|
|
106
106
|
const args = node.arguments;
|
|
@@ -81,6 +81,7 @@ module.exports = function (type, files = [], conf = {}, replaceWords) {
|
|
|
81
81
|
|
|
82
82
|
const allWords = []; // 收集到的所有词条
|
|
83
83
|
const downloadIds = []; // 需要从平台下载的词条id
|
|
84
|
+
const specialMethod = []; // 替换的国际化特殊方法
|
|
84
85
|
|
|
85
86
|
// babel配置
|
|
86
87
|
const transformOptions = {
|
|
@@ -113,7 +114,15 @@ module.exports = function (type, files = [], conf = {}, replaceWords) {
|
|
|
113
114
|
files.forEach((file) => {
|
|
114
115
|
const { filePath } = file;
|
|
115
116
|
|
|
116
|
-
if (
|
|
117
|
+
if (
|
|
118
|
+
specialFileReg.some(item => {
|
|
119
|
+
if (typeof item === 'string') {
|
|
120
|
+
return item === filePath;
|
|
121
|
+
} else {
|
|
122
|
+
return item.test(filePath);
|
|
123
|
+
}
|
|
124
|
+
})
|
|
125
|
+
) {
|
|
117
126
|
file.special = true;
|
|
118
127
|
}
|
|
119
128
|
const isTSX = ['.ts', '.tsx'].includes(path.extname(filePath));
|
|
@@ -122,6 +131,7 @@ module.exports = function (type, files = [], conf = {}, replaceWords) {
|
|
|
122
131
|
allWords,
|
|
123
132
|
replaceWords: replaceWords || {},
|
|
124
133
|
downloadIds,
|
|
134
|
+
specialMethod,
|
|
125
135
|
hasImport: false, // 是否已经引入通用国际化API,import {init} from ...;
|
|
126
136
|
hasTouch: false, // 是否存在需要替换的词条
|
|
127
137
|
};
|
|
@@ -183,5 +193,6 @@ module.exports = function (type, files = [], conf = {}, replaceWords) {
|
|
|
183
193
|
return {
|
|
184
194
|
allWords,
|
|
185
195
|
downloadIds,
|
|
196
|
+
specialMethod,
|
|
186
197
|
};
|
|
187
198
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@chaoswise/intl",
|
|
3
|
-
"version": "1.2.
|
|
3
|
+
"version": "1.2.1",
|
|
4
4
|
"author": "cloudwiser",
|
|
5
5
|
"description": "intl",
|
|
6
6
|
"main": "lib/index.js",
|
|
@@ -83,5 +83,5 @@
|
|
|
83
83
|
"react-dom": "^16.13.1"
|
|
84
84
|
},
|
|
85
85
|
"license": "MIT",
|
|
86
|
-
"gitHead": "
|
|
86
|
+
"gitHead": "e90f035c659bef6d8cfe7ae08cfbc6117f8b5a79"
|
|
87
87
|
}
|