const fs = require('fs'); const path = require('path'); const root = 'src'; const exts = ['.tsx', '.ts', '.jsx', '.js']; const excludeDirs = ['locales', 'node_modules']; // Regex to match a run of CJK characters (and surrounding simple chars) inside a string-ish // We capture any quoted string (single/double/backtick) containing CJK. const cjk = /[\u4e00-\u9fff]/; function walk(dir) { const out = []; for (const entry of fs.readdirSync(dir, { withFileTypes: true })) { const full = path.join(dir, entry.name); if (entry.isDirectory()) { if (excludeDirs.includes(entry.name)) continue; out.push(...walk(full)); } else if (exts.includes(path.extname(entry.name))) { out.push(full); } } return out; } const files = walk(root); let total = 0; const perFile = []; for (const f of files) { const lines = fs.readFileSync(f, 'utf8').split('\n'); const hits = []; lines.forEach((line, i) => { // skip pure comment lines (// ... or * ...) const trimmed = line.trim(); if (trimmed.startsWith('//') || trimmed.startsWith('*')) return; if (!cjk.test(line)) return; hits.push({ line: i + 1, text: line.trim() }); }); if (hits.length) { perFile.push({ file: f, hits }); total += hits.length; } } console.log('Total files with CJK:', perFile.length, 'Total CJK lines:', total); for (const pf of perFile) { console.log('\n### ' + pf.file + ' (' + pf.hits.length + ')'); for (const h of pf.hits) { console.log(' L' + h.line + ': ' + h.text.slice(0, 200)); } }