Files
cosmos-explorer/utils/generateI18nKeys.mjs
sunghyunkang1111 2e5c355479 Added localization build (#2380)
* Added localization build

* Commit types

* Added locProject.json

* Localized file check-in by OneLocBuild Task: Build definition ID 13114: Build ID 2425084 (#2392)

* Fixed package.json

* Fix compilation error

* Localized file check-in by OneLocBuild Task: Build definition ID 13114: Build ID 2431677 (#2396)

* Localized file check-in by OneLocBuild Task: Build definition ID 13114: Build ID 2432830 (#2397)

* Localized file check-in by OneLocBuild Task: Build definition ID 13114: Build ID 2431872

* Localized file check-in by OneLocBuild Task: Build definition ID 13114: Build ID 2432783

* Localized file check-in by OneLocBuild Task: Build definition ID 13114: Build ID 2432830

* Localized file check-in by OneLocBuild Task: Build definition ID 13114: Build ID 2434398 (#2400)

---------

Co-authored-by: olprod <olprod@microsoft.com>
2026-02-26 13:32:33 -06:00

72 lines
2.9 KiB
JavaScript

/**
* Generates src/Localization/Keys.generated.ts from en/Resources.json.
*
* Every leaf value becomes its dot-notation key path, with JSDoc annotations
* showing the English translation so developers see real text on hover.
*
* Libraries:
* - values-to-keys — replaces translation values with dot-path keys
* - i18next-resources-for-ts (json2ts) — serialises objects as typed `as const` TS
*
* Usage: node utils/generateI18nKeys.mjs
*/
import { readFileSync, writeFileSync } from "fs";
import { json2ts } from "i18next-resources-for-ts";
import { dirname, resolve } from "path";
import { fileURLToPath } from "url";
import { replace } from "values-to-keys";
const __dirname = dirname(fileURLToPath(import.meta.url));
const ROOT = resolve(__dirname, "..");
const INPUT = resolve(ROOT, "src/Localization/en/Resources.json");
const OUTPUT = resolve(ROOT, "src/Localization/Keys.generated.ts");
// ── helpers ────────────────────────────────────────────────────────
/**
* Walk two parallel objects (keyed + original) and produce TS source
* with JSDoc comments showing the English value at every leaf.
*/
function serialiseWithJSDoc(obj, orig, indent = 2) {
const pad = " ".repeat(indent);
const lines = ["{"];
for (const key of Object.keys(obj)) {
const val = obj[key];
const origVal = orig[key];
if (typeof val === "object" && val !== null) {
lines.push(`${pad}${key}: ${serialiseWithJSDoc(val, origVal, indent + 2)},`);
} else {
lines.push(`${pad}/** ${origVal} */`);
lines.push(`${pad}${key}: ${JSON.stringify(val)},`);
}
}
lines.push(`${" ".repeat(Math.max(0, indent - 2))}}`);
return lines.join("\n");
}
// ── main ───────────────────────────────────────────────────────────
// Keep the original English values for JSDoc annotations
const original = JSON.parse(readFileSync(INPUT, "utf-8"));
// Use values-to-keys to replace every leaf value with its dot-path key
const keyed = replace(JSON.parse(readFileSync(INPUT, "utf-8")));
// Use json2ts to verify the shape is valid for `as const` export
// (We still use our own serialiser because json2ts doesn't add JSDoc comments)
json2ts(keyed); // validates structure; throws on malformed input
const banner = `\
// -----------------------------------------------------------------
// THIS FILE IS AUTO-GENERATED — DO NOT EDIT BY HAND
// Regenerate with: npm run generate:i18n-keys
// -----------------------------------------------------------------
`;
const body = `export const Keys = ${serialiseWithJSDoc(keyed, original)} as const;\n`;
writeFileSync(OUTPUT, banner + body, "utf-8");
// eslint-disable-next-line no-console
console.log(`Generated ${OUTPUT}`);