fix(ui): bootstrap source-only locales (#131015)

Allow source-only locale contributions to load intentional English bootstrap copy until post-merge generated memory exists. Derive refresh targets from canonical locale data while preserving strict validation.

Co-authored-by: Ayaan Zaidi <hi@obviy.us>
This commit is contained in:
Ayaan Zaidi
2026-08-27 22:43:35 +05:30
committed by GitHub
parent 608e365ce4
commit c85be96d6e
12 changed files with 115 additions and 82 deletions
+1 -1
View File
@@ -103,7 +103,7 @@ const DEPRECATION_HYGIENE_PATH_RE =
const WRAPPER_SHADOWING_PATH_RE =
/^(?:package\.json$|src\/|scripts\/(?:check-(?:export-name-collisions|wrapper-shadowing)\.mts$|lib\/ts-guard-utils\.mts$))/u;
const CONTROL_UI_I18N_VERIFY_PATH_RE =
/^(?:package\.json$|ui\/(?:src\/|config\/control-ui-locales\.ts$)|scripts\/(?:control-ui-i18n(?:-(?:report|verify))?\.ts|lib\/control-ui-i18n-[^/]+\.ts)$|test\/scripts\/control-ui-i18n[^/]*\.test\.ts$)/u;
/^(?:package\.json$|ui\/(?:src\/|config\/control-ui-locales\.ts$)|scripts\/(?:control-ui-i18n(?:-(?:report|verify))?\.ts|lib\/(?:control-ui-i18n-[^/]+\.ts|control-ui-i18n-config\.json))$|test\/scripts\/control-ui-i18n[^/]*\.test\.ts$)/u;
const SHRINK_RATCHET_OWNER_PATH = "scripts/lib/shrink-ratchet.mts";
const CORE_OXLINT_TS_CONFIG = "config/tsconfig/oxlint.core.json";
const EXTENSIONS_OXLINT_TS_CONFIG = "config/tsconfig/oxlint.extensions.json";
+1 -1
View File
@@ -92,7 +92,7 @@ const WINDOWS_WORKER_BUNDLE_SCOPE_RE =
const WINDOWS_WORKER_WORKSPACE_SCOPE_RE =
/^src\/(?:node-host\/node-worker-transfer-client(?:\.test)?|gateway\/worker-environments\/(?:node-worker-tunnel(?:\.test)?|workspace-sync-(?:scripts|manifest\.test)))\.ts$/;
const CONTROL_UI_I18N_SCOPE_RE =
/^(ui\/src\/i18n\/|ui\/config\/control-ui-locales\.ts$|scripts\/(?:control-ui-i18n(?:-verify)?\.ts|lib\/control-ui-i18n-(?:catalog|config|raw-copy|sync-plan)\.ts)$|\.github\/workflows\/control-ui-locale-refresh\.yml$)/;
/^(ui\/src\/i18n\/|ui\/config\/control-ui-locales\.ts$|scripts\/(?:control-ui-i18n(?:-verify)?\.ts|lib\/control-ui-i18n-(?:(?:catalog|config|raw-copy|sync-plan)\.ts|config\.json))$|\.github\/workflows\/control-ui-locale-refresh\.yml$)/;
const CONTROL_UI_RAW_COPY_SOURCE_RE = /^ui\/src\/(?:app|components|lib|pages)\/.*\.tsx?$/;
const CONTROL_UI_HARD_GENERATED_I18N_RE =
/^ui\/src\/i18n\/\.i18n\/(?:catalog-fallbacks\.json|[^/]+\.(?:meta\.json|tm\.jsonl))$/;
+9 -9
View File
@@ -306,15 +306,15 @@ export async function syncControlUiCatalogFallbackBaseline(options: {
}
export async function verifyRuntimeLocaleConfig() {
const registryRaw = await readFile(
path.join(ROOT, "ui", "src", "i18n", "lib", "registry.ts"),
"utf8",
);
const typesRaw = await readFile(path.join(ROOT, "ui", "src", "i18n", "lib", "types.ts"), "utf8");
for (const entry of CONTROL_UI_LOCALE_ENTRIES) {
if (!registryRaw.includes(`"${entry.locale}"`) || !typesRaw.includes(`| "${entry.locale}"`)) {
throw new Error(`runtime locale config is missing ${entry.locale}`);
}
const registryPath = path.join(ROOT, "ui", "src", "i18n", "lib", "registry.ts");
const registry = (await import(pathToFileURL(registryPath).href)) as {
SUPPORTED_LOCALES: readonly string[];
};
const expectedLocales = ["en", ...CONTROL_UI_LOCALE_ENTRIES.map((entry) => entry.locale)];
if (!compareStringArrays(registry.SUPPORTED_LOCALES, expectedLocales)) {
throw new Error(
`runtime locale config is out of sync: expected ${expectedLocales.join(", ")}, got ${registry.SUPPORTED_LOCALES.join(", ")}`,
);
}
const enMap = (await loadControlUiLocaleCatalog(SOURCE_LOCALE_PATH, "en")) ?? {};
+22
View File
@@ -0,0 +1,22 @@
[
{ "locale": "zh-CN", "fileName": "zh-CN.ts", "exportName": "zh_CN", "languageKey": "zhCN" },
{ "locale": "zh-TW", "fileName": "zh-TW.ts", "exportName": "zh_TW", "languageKey": "zhTW" },
{ "locale": "pt-BR", "fileName": "pt-BR.ts", "exportName": "pt_BR", "languageKey": "ptBR" },
{ "locale": "de", "fileName": "de.ts", "exportName": "de", "languageKey": "de" },
{ "locale": "es", "fileName": "es.ts", "exportName": "es", "languageKey": "es" },
{ "locale": "ja-JP", "fileName": "ja-JP.ts", "exportName": "ja_JP", "languageKey": "jaJP" },
{ "locale": "ko", "fileName": "ko.ts", "exportName": "ko", "languageKey": "ko" },
{ "locale": "fr", "fileName": "fr.ts", "exportName": "fr", "languageKey": "fr" },
{ "locale": "hi", "fileName": "hi.ts", "exportName": "hi", "languageKey": "hi" },
{ "locale": "ar", "fileName": "ar.ts", "exportName": "ar", "languageKey": "ar" },
{ "locale": "it", "fileName": "it.ts", "exportName": "it", "languageKey": "it" },
{ "locale": "tr", "fileName": "tr.ts", "exportName": "tr", "languageKey": "tr" },
{ "locale": "uk", "fileName": "uk.ts", "exportName": "uk", "languageKey": "uk" },
{ "locale": "id", "fileName": "id.ts", "exportName": "id", "languageKey": "id" },
{ "locale": "pl", "fileName": "pl.ts", "exportName": "pl", "languageKey": "pl" },
{ "locale": "th", "fileName": "th.ts", "exportName": "th", "languageKey": "th" },
{ "locale": "vi", "fileName": "vi.ts", "exportName": "vi", "languageKey": "vi" },
{ "locale": "nl", "fileName": "nl.ts", "exportName": "nl", "languageKey": "nl" },
{ "locale": "fa", "fileName": "fa.ts", "exportName": "fa", "languageKey": "fa" },
{ "locale": "ru", "fileName": "ru.ts", "exportName": "ru", "languageKey": "ru" }
]
+2 -22
View File
@@ -1,24 +1,4 @@
import controlUiLocaleEntries from "./control-ui-i18n-config.json" with { type: "json" };
import type { LocaleEntry } from "./control-ui-i18n-sync-plan.ts";
export const CONTROL_UI_LOCALE_ENTRIES: readonly LocaleEntry[] = [
{ locale: "zh-CN", fileName: "zh-CN.ts", exportName: "zh_CN", languageKey: "zhCN" },
{ locale: "zh-TW", fileName: "zh-TW.ts", exportName: "zh_TW", languageKey: "zhTW" },
{ locale: "pt-BR", fileName: "pt-BR.ts", exportName: "pt_BR", languageKey: "ptBR" },
{ locale: "de", fileName: "de.ts", exportName: "de", languageKey: "de" },
{ locale: "es", fileName: "es.ts", exportName: "es", languageKey: "es" },
{ locale: "ja-JP", fileName: "ja-JP.ts", exportName: "ja_JP", languageKey: "jaJP" },
{ locale: "ko", fileName: "ko.ts", exportName: "ko", languageKey: "ko" },
{ locale: "fr", fileName: "fr.ts", exportName: "fr", languageKey: "fr" },
{ locale: "hi", fileName: "hi.ts", exportName: "hi", languageKey: "hi" },
{ locale: "ar", fileName: "ar.ts", exportName: "ar", languageKey: "ar" },
{ locale: "it", fileName: "it.ts", exportName: "it", languageKey: "it" },
{ locale: "tr", fileName: "tr.ts", exportName: "tr", languageKey: "tr" },
{ locale: "uk", fileName: "uk.ts", exportName: "uk", languageKey: "uk" },
{ locale: "id", fileName: "id.ts", exportName: "id", languageKey: "id" },
{ locale: "pl", fileName: "pl.ts", exportName: "pl", languageKey: "pl" },
{ locale: "th", fileName: "th.ts", exportName: "th", languageKey: "th" },
{ locale: "vi", fileName: "vi.ts", exportName: "vi", languageKey: "vi" },
{ locale: "nl", fileName: "nl.ts", exportName: "nl", languageKey: "nl" },
{ locale: "fa", fileName: "fa.ts", exportName: "fa", languageKey: "fa" },
{ locale: "ru", fileName: "ru.ts", exportName: "ru", languageKey: "ru" },
];
export const CONTROL_UI_LOCALE_ENTRIES = controlUiLocaleEntries satisfies readonly LocaleEntry[];