@chaoswise/intl 3.1.0 → 3.1.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/chaoswise-intl.js
CHANGED
|
@@ -4,8 +4,9 @@ const runUpdate = require('./scripts/update');
|
|
|
4
4
|
const runInitConfig = require('./scripts/initConfig');
|
|
5
5
|
const runAddLocale = require('./scripts/addLocale');
|
|
6
6
|
const runNoZhCn = require('./scripts/nozhcn');
|
|
7
|
+
const runVerify = require('./scripts/verify');
|
|
7
8
|
|
|
8
|
-
const SCRIPTS = ['intl', 'collect', 'update', 'nozhcn', 'addLocale', 'init'];
|
|
9
|
+
const SCRIPTS = ['intl', 'collect', 'update', 'nozhcn', 'addLocale', 'init', 'verify'];
|
|
9
10
|
|
|
10
11
|
const args = process.argv.slice(2);
|
|
11
12
|
|
|
@@ -24,6 +25,14 @@ if (script === 'update') {
|
|
|
24
25
|
if (script === 'addLocale') {
|
|
25
26
|
runAddLocale();
|
|
26
27
|
}
|
|
28
|
+
// verify: 检测代码中所有 intl.get('id') 是否都在 relationKey.json 或本地 locale 文件中
|
|
29
|
+
// Usage:
|
|
30
|
+
// chaoswise-intl verify → 发现孤立 id 时 exit(1)(CI 门禁)
|
|
31
|
+
// chaoswise-intl verify --warn → 仅警告,不 exit(1)
|
|
32
|
+
if (script === 'verify') {
|
|
33
|
+
const exitOnMissing = !args.includes('--warn');
|
|
34
|
+
runVerify({ exitOnMissing });
|
|
35
|
+
}
|
|
27
36
|
// nozhcn: detect (and optionally fix) Chinese characters in source files
|
|
28
37
|
// Usage:
|
|
29
38
|
// chaoswise-intl nozhcn → check mode (CI gate, exit 1 on findings)
|
|
@@ -9,11 +9,14 @@ module.exports = function f(
|
|
|
9
9
|
const { replaceWords, downloadIds, defaultKeyWordMap } = returns;
|
|
10
10
|
|
|
11
11
|
// XXX: [TRICKY] 防止中文转码为 unicode
|
|
12
|
+
// NOTE: recast 的 StringLiteral 打印分支直接使用 node.value(nodeStr),
|
|
13
|
+
// 不像 @babel/generator 那样读取 extra.raw,所以必须把真实 id 写入 node.value。
|
|
12
14
|
function hackValue(value, id) {
|
|
13
|
-
|
|
15
|
+
const finalId = id || value;
|
|
16
|
+
return Object.assign(t.StringLiteral(finalId), {
|
|
14
17
|
extra: {
|
|
15
|
-
raw: `'${
|
|
16
|
-
rawValue:
|
|
18
|
+
raw: `'${finalId}'`,
|
|
19
|
+
rawValue: finalId,
|
|
17
20
|
},
|
|
18
21
|
});
|
|
19
22
|
}
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
const fs = require('fs');
|
|
2
|
+
const path = require('path');
|
|
3
|
+
const glob = require('glob');
|
|
4
|
+
|
|
5
|
+
const getConf = require('./conf');
|
|
6
|
+
const { targetOutputFiles } = require('./util/getTargetFiles');
|
|
7
|
+
const transformAst = require('./util/transformAst');
|
|
8
|
+
const log = require('./util/log');
|
|
9
|
+
const file = require('./util/file');
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* verify: 检测当前工程输出文件中所有 intl.get('id') 的 id
|
|
13
|
+
* - pending : 临时 key,存在于 relationKey.json(尚未执行 update 替换)
|
|
14
|
+
* - ok : 已在本地 locale 文件中找到
|
|
15
|
+
* - missing : 两处均找不到,属于"孤立 id",运行时将无法解析
|
|
16
|
+
*
|
|
17
|
+
* 用法:
|
|
18
|
+
* chaoswise-intl verify → 发现 missing 时 exit(1)(CI 门禁)
|
|
19
|
+
* chaoswise-intl verify --warn → 仅警告,不 exit(1)
|
|
20
|
+
*/
|
|
21
|
+
async function verify({ exitOnMissing = true } = {}) {
|
|
22
|
+
log.info('词条 id 校验中...');
|
|
23
|
+
|
|
24
|
+
const conf = getConf();
|
|
25
|
+
const files = targetOutputFiles(conf);
|
|
26
|
+
|
|
27
|
+
if (!files.length) {
|
|
28
|
+
log.warn('未找到需要扫描的文件,请检查 output 配置');
|
|
29
|
+
return;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
// ── Step 1: 收集代码中所有原始 id(传入空对象,不触发替换也不写文件)──────
|
|
33
|
+
const info = transformAst('update', files, conf, {});
|
|
34
|
+
const allIds = [...new Set(info.downloadIds.filter(Boolean))];
|
|
35
|
+
|
|
36
|
+
if (!allIds.length) {
|
|
37
|
+
log.success('未发现任何国际化 id,无需校验');
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
// ── Step 2: 从 relationKey.json 获取待替换的临时 key 集合 ───────────────
|
|
42
|
+
const relationKey = file.readJson('relationKey.json') || {};
|
|
43
|
+
const pendingKeySet = new Set(Object.keys(relationKey));
|
|
44
|
+
|
|
45
|
+
// ── Step 3: 从本地 locale 文件获取已下载的合法 id 集合 ────────────────────
|
|
46
|
+
const rootPath = process.cwd();
|
|
47
|
+
const localeDir = path.resolve(rootPath, conf.localeOutput, 'locales');
|
|
48
|
+
const localeFiles = glob.sync(`${localeDir}/*.json`);
|
|
49
|
+
const localIdSet = new Set();
|
|
50
|
+
localeFiles.forEach((f) => {
|
|
51
|
+
try {
|
|
52
|
+
const json = JSON.parse(fs.readFileSync(f, 'utf-8'));
|
|
53
|
+
Object.keys(json).forEach((k) => localIdSet.add(k));
|
|
54
|
+
} catch (e) {
|
|
55
|
+
log.error(`读取 locale 文件失败:${f}`);
|
|
56
|
+
}
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
// ── Step 4: 分类统计 ──────────────────────────────────────────────────────
|
|
60
|
+
const pending = [];
|
|
61
|
+
const missing = [];
|
|
62
|
+
const ok = [];
|
|
63
|
+
|
|
64
|
+
for (const id of allIds) {
|
|
65
|
+
if (pendingKeySet.has(id)) {
|
|
66
|
+
pending.push({ tempKey: id, realId: relationKey[id] });
|
|
67
|
+
} else if (localIdSet.has(id)) {
|
|
68
|
+
ok.push(id);
|
|
69
|
+
} else {
|
|
70
|
+
missing.push(id);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
// ── Step 5: 输出结果 ──────────────────────────────────────────────────────
|
|
75
|
+
console.log('');
|
|
76
|
+
log.info(`扫描到 ${allIds.length} 个唯一 id(文件数:${files.length})`);
|
|
77
|
+
|
|
78
|
+
if (ok.length) {
|
|
79
|
+
log.success(`✓ ${ok.length} 个 id 已在本地 locale 文件中覆盖`);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
if (pending.length) {
|
|
83
|
+
log.warnToLog(`⚠ ${pending.length} 个临时 key 尚未执行 update 替换:`);
|
|
84
|
+
pending.forEach(({ tempKey, realId }) => {
|
|
85
|
+
log.warnToLog(` ${tempKey} → ${realId}`);
|
|
86
|
+
});
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
if (missing.length) {
|
|
90
|
+
log.error(`✗ ${missing.length} 个 id 在 relationKey.json 和本地 locale 文件中均不存在(孤立 id):`);
|
|
91
|
+
missing.forEach((id) => log.error(` ${id}`));
|
|
92
|
+
console.log('');
|
|
93
|
+
log.error('提示:孤立 id 可能是未上传到国际化平台、未执行 update 拉取,或已在平台删除的词条');
|
|
94
|
+
|
|
95
|
+
if (exitOnMissing) {
|
|
96
|
+
process.exit(1);
|
|
97
|
+
}
|
|
98
|
+
} else {
|
|
99
|
+
console.log('');
|
|
100
|
+
log.success('★★★ 所有词条 id 均已覆盖,校验通过 ★★★');
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
module.exports = verify;
|