Initial Commit

This commit is contained in:
2026-05-27 23:47:53 +01:00
parent fbc70f96e6
commit 9b28db724f
18103 changed files with 1600554 additions and 0 deletions

View File

@@ -0,0 +1,109 @@
#!/usr/bin/env bun
/**
* `check-locale-completeness.ts` — assert every key in
* `<package>/src/locales/en-GB.json` exists in every other locale
* bundle shipped by the package. Pure file walk; no transitive deps on
* the package source.
*
* Usage:
* bun packages/react/react-ui/scripts/check-locale-completeness.ts <package-root>
*
* Exit codes:
* 0 — every key parity-complete
* 1 — at least one key missing
* 2 — internal failure
*/
import { readdir, readFile } from "node:fs/promises";
import { join, resolve } from "node:path";
interface BundleDiff {
readonly locale: string;
readonly missing: ReadonlyArray<string>;
readonly extra: ReadonlyArray<string>;
}
export async function checkLocaleCompleteness(
packageRoot: string
): Promise<BundleDiff[]> {
const localesDir = join(resolve(packageRoot), "src", "locales");
const enPath = join(localesDir, "en-GB.json");
const enKeys = new Set(
Object.keys(JSON.parse(await readFile(enPath, "utf8")))
);
const entries = await readdir(localesDir);
const diffs: BundleDiff[] = [];
for (const entry of entries) {
if (entry === "en-GB.json") continue;
if (!entry.endsWith(".json")) continue;
const otherPath = join(localesDir, entry);
const other = JSON.parse(await readFile(otherPath, "utf8")) as Record<
string,
string
>;
const otherKeys = new Set(Object.keys(other));
const missing: string[] = [];
for (const k of enKeys) {
if (!otherKeys.has(k)) missing.push(k);
}
const extra: string[] = [];
for (const k of otherKeys) {
if (!enKeys.has(k)) extra.push(k);
}
if (missing.length > 0 || extra.length > 0) {
diffs.push({
locale: entry.replace(/\.json$/, ""),
missing,
extra,
});
}
}
return diffs;
}
function format(diffs: ReadonlyArray<BundleDiff>): string {
if (diffs.length === 0) {
return "check-locale-completeness: every locale parity-complete.";
}
const lines: string[] = [
`check-locale-completeness: ${diffs.length} locale(s) failed parity.`,
];
for (const d of diffs) {
lines.push(` ${d.locale}:`);
if (d.missing.length > 0) {
lines.push(" missing keys:");
for (const k of d.missing) lines.push(` - ${k}`);
}
if (d.extra.length > 0) {
lines.push(" extra keys (not in en-GB):");
for (const k of d.extra) lines.push(` - ${k}`);
}
}
return lines.join("\n");
}
async function main(): Promise<void> {
const argv = process.argv.slice(2);
if (argv.length === 0) {
process.stderr.write(
"Usage: check-locale-completeness.ts <package-root>\n"
);
process.exit(2);
}
const root = argv[0] as string;
const diffs = await checkLocaleCompleteness(root);
const message = format(diffs);
if (diffs.length === 0) {
process.stdout.write(`${message}\n`);
process.exit(0);
}
process.stderr.write(`${message}\n`);
process.exit(1);
}
if (import.meta.main) {
await main().catch((err: unknown) => {
process.stderr.write(`internal error: ${(err as Error).message}\n`);
process.exit(2);
});
}