chore: 统一本地服务器与远程仓库源码
- 合并 main 与 master 历史并以服务器结构为基线 - 保留迁移、数据保留、AWS 账单与部署安全能力 - 建立 SDD 规格和 CI 验证闭环
This commit is contained in:
commit
fd60361d93
460 files changed
+37492
-23871
No files matched your search
@@ -0,0 +1,65 @@
|
||||
import fs from 'node:fs';
|
||||
import path from 'node:path';
|
||||
|
||||
const sourceRoot = path.resolve('src');
|
||||
const locale = JSON.parse(fs.readFileSync(path.resolve('src/locales/zh-CN.json'), 'utf8'));
|
||||
const files = [];
|
||||
|
||||
function walk(dir) {
|
||||
for (const entry of fs.readdirSync(dir, { withFileTypes: true })) {
|
||||
const file = path.join(dir, entry.name);
|
||||
if (entry.isDirectory()) walk(file);
|
||||
else if (/\.(ts|tsx)$/.test(entry.name)) files.push(file);
|
||||
}
|
||||
}
|
||||
|
||||
function normalizeLegacyKeys(resource) {
|
||||
const legacyEntries = [];
|
||||
const collect = (node, parentPath = []) => {
|
||||
for (const [key, value] of Object.entries(node)) {
|
||||
if (typeof value === 'string' && key.includes('.')) legacyEntries.push([parentPath, key, value]);
|
||||
if (value && typeof value === 'object' && !Array.isArray(value)) collect(value, [...parentPath, key]);
|
||||
}
|
||||
};
|
||||
const setIfMissing = (segments, value) => {
|
||||
let node = resource;
|
||||
for (const segment of segments.slice(0, -1)) {
|
||||
if (!node[segment] || typeof node[segment] !== 'object') node[segment] = {};
|
||||
node = node[segment];
|
||||
}
|
||||
const last = segments.at(-1);
|
||||
if (node[last] === undefined) node[last] = value;
|
||||
};
|
||||
collect(resource);
|
||||
legacyEntries.forEach(([parentPath, key, value]) => {
|
||||
setIfMissing([...parentPath, ...key.split('.')], value);
|
||||
setIfMissing(key.split('.'), value);
|
||||
});
|
||||
}
|
||||
|
||||
function hasKey(resource, key) {
|
||||
return key.split('.').every((segment) => {
|
||||
if (!resource || !Object.hasOwn(resource, segment)) return false;
|
||||
resource = resource[segment];
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
normalizeLegacyKeys(locale);
|
||||
walk(sourceRoot);
|
||||
const missing = new Map();
|
||||
const pattern = /(?:\bi18n\.)?t\(\s*['"]([^'"]+)['"]/g;
|
||||
for (const file of files) {
|
||||
const source = fs.readFileSync(file, 'utf8');
|
||||
for (const match of source.matchAll(pattern)) {
|
||||
const key = match[1];
|
||||
// 聚焦历史文案工具生成的哈希键,避免新业务文案的翻译建设阻塞构建。 // Logan.Li
|
||||
if (/\.s\d[a-z0-9]{7,}$/i.test(key) && !hasKey(locale, key)) missing.set(key, file);
|
||||
}
|
||||
}
|
||||
|
||||
if (missing.size > 0) {
|
||||
for (const [key, file] of missing) console.error(`${key}: ${path.relative(process.cwd(), file)}`);
|
||||
process.exit(1);
|
||||
}
|
||||
console.log(`i18n check passed: ${files.length} source files scanned`);
|
||||
Reference in new issue
Block a user