From 1458e0878d3240f8ffa25c18ab695dc8cd6bcb2e Mon Sep 17 00:00:00 2001 From: Sam Potts Date: Tue, 26 May 2026 11:33:42 +1000 Subject: [PATCH] docs(site): expand locale switch flash-avoidance examples Document registerI18n pre-caching at bootstrap and before switch, compare with I18nProvider translations prop, and note global merge behavior. Co-authored-by: Cursor --- .../docs/how-to/i18n-switch-locale.mdx | 79 ++++++++++++++++++- 1 file changed, 77 insertions(+), 2 deletions(-) diff --git a/site/src/content/docs/how-to/i18n-switch-locale.mdx b/site/src/content/docs/how-to/i18n-switch-locale.mdx index 0f9356b5..2f91ae6d 100644 --- a/site/src/content/docs/how-to/i18n-switch-locale.mdx +++ b/site/src/content/docs/how-to/i18n-switch-locale.mdx @@ -90,10 +90,77 @@ Or set `document.documentElement.lang` if the player inherits ambient language. ## Avoid flash while switching -Async lazy loads can briefly show English. Pre-import the pack and pass `translations`: +Async lazy loads can briefly show English. Preload copy before the active locale changes — three common patterns: + +### Pre-register at bootstrap (React and HTML) + +`registerI18n` writes to a global registry that providers read synchronously. Register every locale you plan to switch between once at startup; `loadLocale` skips tags already in the registry. +```tsx +import { registerI18n } from '@videojs/react/i18n'; +import es from '@videojs/react/i18n/locales/es'; +import fr from '@videojs/react/i18n/locales/fr'; + +registerI18n('es', es); +registerI18n('fr', fr); + +// Switching locale is instant — no remount, no lazy-load gap + + ... + +``` + + + + + +```ts +import { registerI18n } from '@videojs/html/i18n'; +import es from '@videojs/html/i18n/locales/es'; +import fr from '@videojs/html/i18n/locales/fr'; + +registerI18n('es', es); +registerI18n('fr', fr); +``` + +```html + + ... + + + +``` + + + +### Prefetch before switching (React) + +When you cannot register every locale up front, import and register immediately before updating `locale`: + +```tsx +import { registerI18n } from '@videojs/react/i18n'; + +async function switchTo(next: 'es' | 'fr') { + const { default: translations } = await import(`@videojs/react/i18n/locales/${next}`); + registerI18n(next, translations); + setLocale(next); +} + + + ... + +``` + +You still pay the import cost once per locale, but later switches to the same tag stay synchronous. + +### Scoped overrides with `translations` (React) + +Pass `translations` on `I18nProvider` when overrides should apply to one subtree only, or when you want copy colocated with the switch handler: + ```tsx async function switchTo(next: string) { const { default: translations } = await import(`@videojs/react/i18n/locales/${next}`); @@ -105,7 +172,15 @@ async function switchTo(next: string) { ``` - +| Approach | Scope | Best for | +| --- | --- | --- | +| `registerI18n` at bootstrap | Global — all providers | Language picker with a fixed set of locales | +| `registerI18n` before switch | Global — all providers | On-demand prefetch before changing `locale` | +| `I18nProvider translations` | Single provider subtree | Scoped overrides, SSR first paint | + +