import { readFile } from 'node:fs/promises' import { build } from 'esbuild' const zh = JSON.parse(await readFile('src/i18n/locales/zh-CN.json', 'utf8')) const en = JSON.parse(await readFile('src/i18n/locales/en.json', 'utf8')) function flattenKeys(value, prefix = '') { const keys = [] for (const [key, child] of Object.entries(value)) { const path = prefix ? `${prefix}.${key}` : key if (child && typeof child === 'object' && !Array.isArray(child)) { keys.push(...flattenKeys(child, path)) } else { keys.push(path) } } return keys.sort() } const zhKeys = flattenKeys(zh) const enKeys = flattenKeys(en) const missingInEnglish = zhKeys.filter((key) => !enKeys.includes(key)) const missingInChinese = enKeys.filter((key) => !zhKeys.includes(key)) if (missingInEnglish.length || missingInChinese.length) { throw new Error([ missingInEnglish.length ? `Missing in English: ${missingInEnglish.join(', ')}` : '', missingInChinese.length ? `Missing in Chinese: ${missingInChinese.join(', ')}` : '', ].filter(Boolean).join('\n')) } const bundled = await build({ entryPoints: ['src/i18n/index.ts'], bundle: true, format: 'esm', platform: 'node', write: false, logLevel: 'silent', }) const i18nModule = await import( `data:text/javascript;base64,${Buffer.from(bundled.outputFiles[0].contents).toString('base64')}` ) const cases = [ [null, ['zh-CN'], 'zh-CN'], [null, ['zh-Hant-TW'], 'zh-CN'], [null, ['en-US'], 'en'], [null, ['fr-FR'], 'en'], [null, ['ko-KR', 'en-US'], 'en'], ['en', ['zh-CN'], 'en'], ['zh-CN', ['en-US'], 'zh-CN'], ] for (const [saved, browserLanguages, expected] of cases) { const actual = i18nModule.resolveAppLocale(saved, browserLanguages) if (actual !== expected) { throw new Error(`Locale resolution failed for ${JSON.stringify(browserLanguages)}: expected ${expected}, got ${actual}`) } } console.log(`i18n 校验通过:${zhKeys.length} 个消息键,中英语言包一致,自动语言与缓存优先级正确`)