feat(core): add built-in locale packs and lazy loadLocale (#1590)

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
Sam Potts
2026-06-18 12:16:47 -07:00
committed by GitHub
co-authored by Cursor
parent 768bf09da0
commit 9170a5879e
171 changed files with 3416 additions and 6 deletions
@@ -0,0 +1,118 @@
import { readdirSync, unlinkSync, writeFileSync } from 'node:fs';
import { dirname, resolve } from 'node:path';
import { fileURLToPath } from 'node:url';
import { BUILT_IN_LOCALES, LOCALE_ALIAS_TAGS, SHIPPED_LOCALE_TAGS } from '../src/core/i18n/built-in-locales.ts';
const GENERATED_HEADER = '/** Generated by packages/core/scripts/generate-i18n-locales.ts — do not edit. */\n';
const coreRoot = resolve(dirname(fileURLToPath(import.meta.url)), '..');
const coreLocalesDir = resolve(coreRoot, 'src/core/i18n/locales');
const htmlLocalesDir = resolve(coreRoot, '../html/src/i18n/locales');
const reactLocalesDir = resolve(coreRoot, '../react/src/i18n/locales');
const PLATFORM_LOCALE_TAGS = ['en', ...SHIPPED_LOCALE_TAGS] as const;
function importBinding(tag: string): string {
return /^[a-zA-Z_$][a-zA-Z0-9_$]*$/.test(tag) ? tag : tag.replace(/-/g, '_');
}
function objectEntry(tag: string): string {
const binding = importBinding(tag);
if (tag === binding) {
return ` ${tag},`;
}
return ` '${tag}': ${binding},`;
}
function generateLoadLocaleTs(): string {
const tags = [...BUILT_IN_LOCALES, ...LOCALE_ALIAS_TAGS];
const entries = tags.map((tag) => ` '${tag}': () => import('./locales/${tag}'),`).join('\n');
const normalizedEntries = tags
.map((tag) => ` '${tag.trim().replaceAll('_', '-').toLowerCase()}': '${tag}',`)
.join('\n');
return `${GENERATED_HEADER}import { canonicalLocaleRegistryKey, hasRegisteredI18n, localeLookupChain } from './registry';
import type { Translations } from './types';
const loaders = {
${entries}
} as const satisfies Record<string, () => Promise<{ default: Partial<Translations> }>>;
const loaderTagByNormalized = {
${normalizedEntries}
} as const satisfies Record<string, keyof typeof loaders>;
/** Lazy-import a shipped locale pack when the tag is not already in the registry. */
export async function loadLocale(tag: string): Promise<Partial<Translations> | undefined> {
if (hasRegisteredI18n(tag)) return undefined;
for (const chainTag of localeLookupChain(tag)) {
if (hasRegisteredI18n(chainTag)) return undefined;
const loaderTag =
loaderTagByNormalized[canonicalLocaleRegistryKey(chainTag) as keyof typeof loaderTagByNormalized];
const load = loaderTag ? loaders[loaderTag] : undefined;
if (load) return (await load()).default;
}
return undefined;
}
`;
}
function generateCoreAllTs(): string {
const importTags = ['en', ...BUILT_IN_LOCALES, ...LOCALE_ALIAS_TAGS];
const imports = importTags.map((tag) => `import ${importBinding(tag)} from './${tag}';`).join('\n');
const objectLines = [' en,', ...BUILT_IN_LOCALES.map(objectEntry), ...LOCALE_ALIAS_TAGS.map(objectEntry)].join('\n');
return `${GENERATED_HEADER}import type { Translations } from '../types';
${imports}
/** Every built-in locale pack keyed by BCP 47 tag (includes \`en\` and shorthand aliases \`pt\` / \`zh\`). */
export const all = {
${objectLines}
} as const satisfies Record<string, Partial<Translations>>;
export type LocaleTag = keyof typeof all;
/** BCP 47 tags for every pack in {@link all}. */
export const localeTags = Object.keys(all) as LocaleTag[];
`;
}
function generatePlatformDefaultReExport(tag: string): string {
return `${GENERATED_HEADER}export { default } from '@videojs/core/i18n/locales/${tag}';
`;
}
function generatePlatformAllReExport(): string {
return `${GENERATED_HEADER}export { all, type LocaleTag, localeTags } from '@videojs/core/i18n/locales/all';
`;
}
function writeGenerated(path: string, content: string): void {
writeFileSync(path, content.endsWith('\n') ? content : `${content}\n`);
}
function syncPlatformLocaleDir(dir: string): void {
const expected = new Set<string>([...PLATFORM_LOCALE_TAGS, 'all'].map((tag) => `${tag}.ts`));
for (const tag of PLATFORM_LOCALE_TAGS) {
writeGenerated(resolve(dir, `${tag}.ts`), generatePlatformDefaultReExport(tag));
}
writeGenerated(resolve(dir, 'all.ts'), generatePlatformAllReExport());
for (const file of readdirSync(dir)) {
if (!file.endsWith('.ts') || expected.has(file)) {
continue;
}
unlinkSync(resolve(dir, file));
}
}
writeGenerated(resolve(coreLocalesDir, 'all.ts'), generateCoreAllTs());
writeGenerated(resolve(coreRoot, 'src/core/i18n/load-locale.ts'), generateLoadLocaleTs());
syncPlatformLocaleDir(htmlLocalesDir);
syncPlatformLocaleDir(reactLocalesDir);
console.log('[generate-i18n-locales] Updated core all.ts, load-locale.ts, and html/react locale re-exports');