45 lines
1.8 KiB
JavaScript
45 lines
1.8 KiB
JavaScript
const fs = require('fs');
|
|
const path = require('path');
|
|
const root = 'src';
|
|
const exts = ['.tsx', '.ts', '.jsx', '.js'];
|
|
const excludeDirs = ['locales', 'node_modules', 'i18n'];
|
|
function walk(dir) {
|
|
const out = [];
|
|
for (const e of fs.readdirSync(dir, { withFileTypes: true })) {
|
|
const full = path.join(dir, e.name);
|
|
if (e.isDirectory()) { if (!excludeDirs.includes(e.name)) out.push(...walk(full)); }
|
|
else if (exts.includes(path.extname(e.name))) out.push(full);
|
|
}
|
|
return out;
|
|
}
|
|
function load(p) {
|
|
let s = fs.readFileSync(p, 'utf8');
|
|
s = s.replace(/const\s+\w+\s*=\s*\{/, 'var obj = {');
|
|
s = s.replace(/export\s+default\s+\w+;?/, '');
|
|
s = s.replace(/\bconst\b/g, 'var');
|
|
return new Function(s + '\nreturn obj;')();
|
|
}
|
|
function flat(o, p, r) { p = p || ''; r = r || {}; for (const k of Object.keys(o)) { const key = p ? p + '.' + k : k; if (o[k] && typeof o[k] === 'object' && !Array.isArray(o[k])) flat(o[k], key, r); else r[key] = o[k]; } return r; }
|
|
|
|
const zhMap = flat(load('src/locales/zh/index.ts'));
|
|
const enMap = flat(load('src/locales/en/index.ts'));
|
|
|
|
const refRegex = /(?:i18n\.t|[^a-zA-Z]t)\(\s*['"`]([a-zA-Z][a-zA-Z0-9_.]*?)['"`]/g;
|
|
const files = walk(root);
|
|
const refKeys = new Set();
|
|
for (const f of files) {
|
|
const c = fs.readFileSync(f, 'utf8');
|
|
let m; while ((m = refRegex.exec(c))) refKeys.add(m[1]);
|
|
}
|
|
let missZh = [], missEn = [], missBoth = [];
|
|
for (const k of refKeys) {
|
|
if (!(k in zhMap)) missZh.push(k);
|
|
if (!(k in enMap)) missEn.push(k);
|
|
if (!(k in zhMap) && !(k in enMap)) missBoth.push(k);
|
|
}
|
|
console.log('Referenced unique keys:', refKeys.size);
|
|
console.log('Missing in ZH:', missZh.length);
|
|
console.log('Missing in EN:', missEn.length);
|
|
console.log('Missing in BOTH:', missBoth.length);
|
|
if (missBoth.length) console.log('SAMPLE missing-both:', missBoth.slice(0, 20).join(', '));
|