This commit is contained in:
Andras Schmelczer 2026-07-12 15:03:33 +01:00
parent 982e0cc89c
commit cfaf58dfba
44 changed files with 793 additions and 201 deletions

View file

@ -16,7 +16,7 @@
// present in en.ts > server so they can be translated.
//
// The script parses the TypeScript source with the compiler API and walks the
// AST no runtime import, no transpilation, no temp files. Run it with:
// AST: no runtime import, no transpilation, no temp files. Run it with:
// node frontend/scripts/check-translations.mjs
import { readFileSync, readdirSync } from 'fs';
@ -106,7 +106,7 @@ function parseFile(path) {
}
// Recursively turn a TS literal expression into a plain JS value.
// Returns undefined for nodes we don't understand — callers must check.
// Returns undefined for nodes we don't understand. Callers must check.
function literalToJs(node) {
if (!node) return undefined;
if (ts.isStringLiteral(node) || ts.isNoSubstitutionTemplateLiteral(node)) return node.text;
@ -217,7 +217,7 @@ function readServerFeatureNames() {
// Names of the Enum/Numeric feature *configs* (each needs a description + detail
// translation). We take the FIRST `name:` field after every Feature::Enum( /
// Feature::Numeric( opening. This deliberately skips macro-generated configs
// whose name is a `concat!(...)` expression (the crime rates handled via
// whose name is a `concat!(...)` expression (the crime rates, handled via
// deriveLegacyCrimeKeys instead) and stops the lazy match from running past such
// a config into an unrelated FeatureGroup `name:` (which previously made the
// group name "Properties" look like a required feature).
@ -302,7 +302,7 @@ function checkLeafConsistency(path, enValue, trValue, lang) {
const got = tokenMultiset(trValue, re);
if (!multisetsEqual(want, got)) {
fail(
`[${lang}] ${path}: ${label} mismatch en=${JSON.stringify(want)} ` +
`[${lang}] ${path}: ${label} mismatch, en=${JSON.stringify(want)} ` +
`${lang}=${JSON.stringify(got)}`
);
}
@ -425,7 +425,7 @@ function checkRecordCoverage(file, varName, supportedCodes, serverKeys, required
// Every key here must also be a translatable feature name in en.ts > server,
// or a legacy crime key that maps onto the per-window server keys (see
// deriveLegacyCrimeKeys / legacyCrimeFeatureKey). Otherwise the description is
// unreachable ts() looks up server.${name}.
// unreachable: ts() looks up server.${name}.
for (const key of union) {
if (!serverKeys.has(key) && !legacyCrimeKeys.has(key)) {
fail(`${file}: key "${key}" has no matching entry in en.ts > server`);
@ -532,7 +532,7 @@ function main() {
console.error(`\n${errors.length} translation error(s).`);
process.exit(1);
}
console.log(`i18n OK ${supportedCodes.length} languages, ${warnings.length} warning(s).`);
console.log(`i18n OK: ${supportedCodes.length} languages, ${warnings.length} warning(s).`);
}
main();