Skip to content

Commit acf5ef5

Browse files
committed
Add a script for diff keys in language files
1 parent 609ff55 commit acf5ef5

1 file changed

Lines changed: 149 additions & 0 deletions

File tree

src/lang/langDiffWithEn.js

Lines changed: 149 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,149 @@
1+
/**
2+
* Language Pack Diff Checker Script
3+
*
4+
* Purpose:
5+
* Compare src/lang/locale/en.ts and a target language file (e.g. zh-cn.ts), output missing and extra keys.
6+
* Output is color-coded:
7+
* - Green: Key exists in en.ts but missing in the target language file
8+
* - Red: Key exists in the target language file but not in en.ts
9+
* - Yellow: The same key exists in both files but the line numbers are different
10+
*
11+
* Dependencies:
12+
* Node.js environment, no extra dependencies required.
13+
*
14+
* Usage:
15+
* 1. Open a terminal in this file's directory (or project root).
16+
* 2. Run:
17+
* node src/lang/langDiffWithEn.js zh-cn
18+
* # or node src/lang/langDiffWithEn.js ja
19+
* # The argument is the language file name (without extension), default is zh-cn
20+
*
21+
* Output:
22+
* + (green): Key exists in en.ts but missing in the target language file
23+
* - (red): Key exists in the target language file but not in en.ts
24+
* ! (yellow): The same key exists in both files but the line numbers are different
25+
* If there is no output, the two files have identical keys.
26+
*/
27+
/**
28+
* 语言包差异检测脚本
29+
*
30+
* 用途:
31+
* 比较 src/lang/locale/en.ts 与指定语言文件(如 zh-cn.ts)中的 key,输出缺失和多余的 key。
32+
* 输出内容会用不同颜色区分:
33+
* - 绿色:en.ts 有但目标语言缺失的 key
34+
* - 红色:目标语言有但 en.ts 没有的 key
35+
* - 黄色:相同的 key 所在的行号不相同
36+
*
37+
* 依赖:
38+
* Node.js 环境,无需额外依赖。
39+
*
40+
* 用法:
41+
* 1. 在命令行进入本文件所在目录(或项目根目录)。
42+
* 2. 运行:
43+
* node src/lang/langDiffWithEn.js zh-cn
44+
* # 或 node src/lang/langDiffWithEn.js ja
45+
* # 参数为语言文件名(不带扩展名),默认为 zh-cn
46+
*
47+
* 输出说明:
48+
* + 开头(绿色):en.ts 有但目标语言缺失的 key
49+
* - 开头(红色):目标语言有但 en.ts 没有的 key
50+
* ! 开头(黄色):相同的 key 所在的行号不相同
51+
* 若无输出则表示两个文件 key 完全一致。
52+
*/
53+
54+
const fs = require("fs");
55+
const path = require("path");
56+
57+
/**
58+
* 读取 locale 文件夹下指定语言和 en.ts 文件,逐行解析键值和行号
59+
* @param lang 语言文件名(不含扩展名),如 zh-cn
60+
* @returns { en: Record<string, {value: string, line: number}>, lang: Record<string, {value: string, line: number}> }
61+
*/
62+
function readLocaleFiles(lang = "zh-cn") {
63+
// 构造 locale 目录路径
64+
const localeDir = path.join(__dirname, "./locale");
65+
// 获取 en.ts 文件路径
66+
const enFile = path.join(localeDir, "en.ts");
67+
// 获取指定语言文件路径
68+
const langFile = path.join(localeDir, `${lang}.ts`);
69+
/**
70+
* 解析指定的语言文件,提取每个 key 的值和所在行号
71+
* @param file 文件路径
72+
* @returns {Record<string, {value: string, line: number}>}
73+
*/
74+
const parse = (file) => {
75+
// 读取文件内容并按行分割
76+
const lines = fs.readFileSync(file, "utf8").split(/\r?\n/);
77+
const result = {};
78+
let inExport = false;
79+
for (let i = 0; i < lines.length; i++) {
80+
const line = lines[i];
81+
// 检查是否进入 export default 块
82+
if (!inExport && line.includes("export default")) {
83+
inExport = true;
84+
continue;
85+
}
86+
if (!inExport) continue;
87+
// 匹配 key: "value", 格式的行
88+
const m = line.match(/^\s*([A-Z0-9_]+)\s*:\s*.*?,?$/);
89+
if (m) {
90+
let key = m[1];
91+
// 保存 key 及其所在行号
92+
result[key] = i + 1;
93+
}
94+
}
95+
return result;
96+
};
97+
// 返回 en 和指定语言的解析结果
98+
return {
99+
en: parse(enFile),
100+
lang: parse(langFile),
101+
};
102+
}
103+
104+
/**
105+
* 比较 en 和 lang 的 key/value,输出差异
106+
*/
107+
108+
function diffLang(lang = "zh-cn") {
109+
const { en, lang: l } = readLocaleFiles(lang);
110+
const allKeys = new Set([...Object.keys(en), ...Object.keys(l)]);
111+
const diffs = [];
112+
for (const key of allKeys) {
113+
if (!(key in en)) {
114+
diffs.push(`- ${key}: ${l[key]}`);
115+
} else if (!(key in l)) {
116+
diffs.push(`+ ${key}: ${en[key]}`);
117+
} else {
118+
if (en[key] !== l[key]) {
119+
diffs.push(`! ${key}: en: ${en[key]} <--> lang: ${l[key]}`);
120+
}
121+
}
122+
}
123+
return diffs;
124+
}
125+
126+
// CLI
127+
if (require.main === module) {
128+
const lang = process.argv[2] || "zh-cn";
129+
const diffs = diffLang(lang);
130+
if (diffs.length === 0) {
131+
console.log(`语言文件 ${lang} 与 en.ts 无差异`);
132+
} else {
133+
diffs.forEach((line) => {
134+
if (line.startsWith("+")) {
135+
// 绿色
136+
console.log("\x1b[32m%s\x1b[0m", line);
137+
} else if (line.startsWith("-")) {
138+
// 红色
139+
console.log("\x1b[31m%s\x1b[0m", line);
140+
} else if (line.startsWith("!")) {
141+
// 黄色
142+
console.log("\x1b[33m%s\x1b[0m", line);
143+
} else {
144+
// 默认
145+
console.log(line);
146+
}
147+
});
148+
}
149+
}

0 commit comments

Comments
 (0)