mirror of
https://github.com/zoriya/v10.git
synced 2026-08-16 02:45:09 +00:00
docs(site): i18n updates after review
This commit is contained in:
@@ -0,0 +1,26 @@
|
||||
# Adding a built-in locale
|
||||
|
||||
Built-in locales live in `locales/`. The locale build generates lazy loaders, CDN chunks, and HTML/React re-exports from that directory.
|
||||
|
||||
1. Add `locales/<tag>.ts` using a BCP 47 filename such as `pt-BR.ts` or `zh-CN.ts`.
|
||||
|
||||
```ts
|
||||
import type { Translations } from '../types';
|
||||
|
||||
export default {
|
||||
Play: '...',
|
||||
Pause: '...',
|
||||
} satisfies Partial<Translations>;
|
||||
```
|
||||
|
||||
Use `locales/en.ts` as the source of phrases. Parametric strings must keep their placeholders.
|
||||
|
||||
2. Add the tag to `LOCALES` in `locales.ts`.
|
||||
|
||||
3. Run `pnpm -F @videojs/core build` to regenerate locale loaders and HTML/React re-exports. Do not edit generated files.
|
||||
|
||||
4. Run `pnpm -F @videojs/core test src/core/i18n` and add coverage for locale aliases or loader behavior when needed.
|
||||
|
||||
5. Run `pnpm -F @videojs/html build:cdn` to verify the generated CDN locale chunk.
|
||||
|
||||
Do not copy Video.js v8 locale JSON blindly. V10 uses different phrase keys and ARIA-label semantics.
|
||||
@@ -7,17 +7,23 @@ import FrameworkCase from '@/components/docs/FrameworkCase.astro';
|
||||
import Aside from '@/components/Aside.astro';
|
||||
import DocsLink from '@/components/docs/DocsLink.astro';
|
||||
|
||||
Video.js translates control labels, ARIA text, tooltips, and error copy through a single **global registry**. Components ask for strings by current English phrase (`Play`, `Pause`, `Seek forward {seconds} seconds`), so missing translations stay readable.
|
||||
Video.js ships in English by default. Non-English UI is opt-in: mount an i18n provider, then configure its active language. Video.js resolves the matching strings for control labels, ARIA text, tooltips, and error copy.
|
||||
|
||||
The default i18n path is automatic after you opt in. Built-in locale packs lazy-load on demand, and Chrome can fill missing languages or missing keys through the [Browser Translation API](https://developer.mozilla.org/en-US/docs/Web/API/Translator) when an on-device translation model is already available.
|
||||
|
||||
Components ask for strings by current English phrase (`Play`, `Pause`, `Seek forward {seconds} seconds`), so missing translations stay readable.
|
||||
|
||||
<FrameworkCase frameworks={["html"]}>
|
||||
|
||||
```html
|
||||
<html lang="es">
|
||||
<video-player>
|
||||
<video-skin>
|
||||
<video src="..." playsinline></video>
|
||||
</video-skin>
|
||||
</video-player>
|
||||
<media-i18n>
|
||||
<video-player>
|
||||
<video-skin>
|
||||
<video src="..." playsinline></video>
|
||||
</video-skin>
|
||||
</video-player>
|
||||
</media-i18n>
|
||||
</html>
|
||||
```
|
||||
|
||||
@@ -26,15 +32,18 @@ Video.js translates control labels, ARIA text, tooltips, and error copy through
|
||||
<FrameworkCase frameworks={["react"]}>
|
||||
|
||||
```tsx
|
||||
import { I18nProvider } from '@videojs/react/i18n';
|
||||
import { Provider, VideoSkin, Video } from '@videojs/react/video';
|
||||
|
||||
// Set `<html lang="es">` on the document (layout, _document, or index.html)
|
||||
export function App() {
|
||||
return (
|
||||
<Provider>
|
||||
<VideoSkin>
|
||||
<Video src="..." playsInline />
|
||||
</VideoSkin>
|
||||
<I18nProvider>
|
||||
<VideoSkin>
|
||||
<Video src="..." playsInline />
|
||||
</VideoSkin>
|
||||
</I18nProvider>
|
||||
</Provider>
|
||||
);
|
||||
}
|
||||
@@ -42,7 +51,19 @@ export function App() {
|
||||
|
||||
</FrameworkCase>
|
||||
|
||||
Register a locale once (or rely on lazy-loaded built-in packs), set `lang`, and skins pick up translated strings automatically.
|
||||
<FrameworkCase frameworks={["html"]}>
|
||||
|
||||
Mount `<media-i18n>` and set its `lang` attribute, or let it inherit the nearest ancestor `lang`. Built-in packs then load automatically.
|
||||
|
||||
</FrameworkCase>
|
||||
|
||||
<FrameworkCase frameworks={["react"]}>
|
||||
|
||||
Mount `I18nProvider` and pass its `locale` prop to force a language, or omit it to inherit `lang`. Built-in packs then load automatically.
|
||||
|
||||
</FrameworkCase>
|
||||
|
||||
Registering packs yourself is only needed when you want custom copy, synchronous first paint, SSR, or CDN loading.
|
||||
|
||||
## Phrase keys
|
||||
|
||||
@@ -52,9 +73,11 @@ Phrase params are typed in <DocsLink slug="reference/translation-params">`Transl
|
||||
|
||||
Parametric strings use `{placeholder}` tokens, for example `'Seek forward {seconds} seconds'` and `'{duration} remaining'`.
|
||||
|
||||
See <DocsLink slug="reference/translation-phrases">Translation phrases</DocsLink> for every current key and the player UI that uses it.
|
||||
|
||||
## Global registry
|
||||
|
||||
`registerI18n(locale, translations)` merges strings into a process-wide map. English (`en`) is pre-registered when the i18n bundle loads.
|
||||
`registerI18n(locale, translations)` merges strings into a process-wide map. English (`en`) is pre-registered when the i18n bundle loads, which is why the default player works without setup.
|
||||
|
||||
| API | Purpose |
|
||||
| --- | --- |
|
||||
@@ -63,41 +86,69 @@ Parametric strings use `{placeholder}` tokens, for example `'Seek forward {secon
|
||||
| <DocsLink slug="reference/has-registered-locale">`hasRegisteredLocale`</DocsLink> | Check whether a tag is in the registry |
|
||||
| <DocsLink slug="reference/on-i18n-registry-change">`onI18nRegistryChange`</DocsLink> | Subscribe to registry updates |
|
||||
|
||||
Import from `@videojs/html/i18n` or `@videojs/react/i18n` depending on your framework.
|
||||
|
||||
## When you need a provider
|
||||
|
||||
**You usually don't**. If the active locale is available and packs are registered (or lazy-loaded), built-in players already wire providers:
|
||||
|
||||
<FrameworkCase frameworks={["html"]}>
|
||||
|
||||
- `<video-player>`, `<audio-player>`, and skins include an i18n provider mixin.
|
||||
- Set `<html lang="es">` (or `lang` on an ancestor) and ship/register Spanish strings.
|
||||
|
||||
Use <DocsLink slug="reference/media-i18n">`<media-i18n>`</DocsLink> when you render **standalone** controls outside a player, or when one page hosts players in different languages.
|
||||
Import from `@videojs/html/i18n`.
|
||||
|
||||
</FrameworkCase>
|
||||
|
||||
<FrameworkCase frameworks={["react"]}>
|
||||
|
||||
- Preset skins render inside <DocsLink slug="reference/player-container">`Container`</DocsLink>, which mounts <DocsLink slug="reference/i18n-provider">`I18nProvider`</DocsLink> with `langRootRef` on the player shell.
|
||||
- Set `<html lang="es">` and register or lazy-load Spanish.
|
||||
|
||||
Wrap with an explicit <DocsLink slug="reference/i18n-provider">`I18nProvider`</DocsLink> when you need a forced locale, per-render overrides, or custom controls outside `Container`.
|
||||
Import from `@videojs/react/i18n`.
|
||||
|
||||
</FrameworkCase>
|
||||
|
||||
**You do need to register or lazy-load packs** before labels appear in the target language. `<html lang="fr">` alone does nothing if French strings were never registered and no built-in `fr` pack loads.
|
||||
## Opt into a language
|
||||
|
||||
Leave your app in English by default. To opt into another language, mount the framework provider around the translated player subtree:
|
||||
|
||||
<FrameworkCase frameworks={["html"]}>
|
||||
|
||||
- Wrap the player in <DocsLink slug="reference/media-i18n">`<media-i18n>`</DocsLink>.
|
||||
- Set `<html lang="es">` or `lang="es"` on `<media-i18n>` to opt into Spanish.
|
||||
- Video.js lazy-loads the shipped Spanish pack when it is not already registered.
|
||||
|
||||
Use a separate `<media-i18n>` for standalone controls or players that need different languages on the same page.
|
||||
|
||||
</FrameworkCase>
|
||||
|
||||
<FrameworkCase frameworks={["react"]}>
|
||||
|
||||
- Mount <DocsLink slug="reference/i18n-provider">`I18nProvider`</DocsLink> inside `Provider`, around the preset skin.
|
||||
- Omit the `locale` prop to inherit `<html lang="es">`, or pass `locale="es"` directly.
|
||||
- Video.js lazy-loads the shipped Spanish pack when it is not already registered.
|
||||
|
||||
Pass the `locale` prop to force a language or `translations` for per-render overrides.
|
||||
|
||||
</FrameworkCase>
|
||||
|
||||
If no pack exists, the provider keeps English until a registered pack, lazy-loaded pack, provider override, or supported browser translation layer supplies strings.
|
||||
|
||||
## Locale resolution
|
||||
|
||||
Providers resolve the active locale in order:
|
||||
<FrameworkCase frameworks={["html"]}>
|
||||
|
||||
1. **Explicit**: `lang` on <DocsLink slug="reference/media-i18n">`<media-i18n>`</DocsLink> or `locale` on <DocsLink slug="reference/i18n-provider">`I18nProvider`</DocsLink>
|
||||
2. **Ambient**: nearest ancestor `[lang]` (HTML) or `langRootRef` / `<html lang>` (React)
|
||||
`<media-i18n>` resolves its active language in order:
|
||||
|
||||
1. **Explicit**: its `lang` attribute
|
||||
2. **Ambient**: nearest ancestor `[lang]`
|
||||
3. **Fallback**: English defaults
|
||||
|
||||
Changing `<html lang>` re-renders wired controls without remounting the player. An explicit `locale` or `lang` on a provider overrides ambient `<html lang>` until you remove or update that override.
|
||||
Changing `<html lang>` re-renders wired controls without remounting the player. An explicit provider `lang` overrides ambient language until you remove or update it.
|
||||
|
||||
</FrameworkCase>
|
||||
|
||||
<FrameworkCase frameworks={["react"]}>
|
||||
|
||||
`I18nProvider` resolves its active language in order:
|
||||
|
||||
1. **Explicit**: its `locale` prop
|
||||
2. **Ambient**: `langRootRef` or `<html lang>`
|
||||
3. **Fallback**: English defaults
|
||||
|
||||
Changing `<html lang>` re-renders wired controls without remounting the player. An explicit `locale` prop overrides ambient language until you remove or update it.
|
||||
|
||||
</FrameworkCase>
|
||||
|
||||
## BCP 47 fallback
|
||||
|
||||
@@ -114,17 +165,66 @@ zh-Hant-HK → zh-hant → zh → en
|
||||
|
||||
Later layers win over earlier ones:
|
||||
|
||||
<FrameworkCase frameworks={["html"]}>
|
||||
|
||||
| Layer | Source |
|
||||
| --- | --- |
|
||||
| 1 (base) | English defaults (`en.ts`) |
|
||||
| 2 | Browser Translation API (Chrome, pre-installed model only) |
|
||||
| 3 | `registerI18n` / CDN locale modules |
|
||||
| 4 | Lazy built-in packs (`loadLocale`) |
|
||||
| 5 (top) | React `translations` prop on `I18nProvider` |
|
||||
|
||||
</FrameworkCase>
|
||||
|
||||
<FrameworkCase frameworks={["react"]}>
|
||||
|
||||
| Layer | Source |
|
||||
| --- | --- |
|
||||
| 1 (base) | English defaults (`en.ts`) |
|
||||
| 2 | Browser Translation API (Chrome, pre-installed model only) |
|
||||
| 3 | `registerI18n` / CDN locale modules |
|
||||
| 4 | Lazy built-in packs (`loadLocale`) |
|
||||
| 5 (top) | `translations` prop on `I18nProvider` |
|
||||
|
||||
</FrameworkCase>
|
||||
|
||||
## Built-in locale packs
|
||||
|
||||
Video.js ships locale files under `@videojs/html/i18n/locales/*` and `@videojs/react/i18n/locales/*`. Providers call `loadLocale` automatically when a pack is not already registered.
|
||||
Providers call `loadLocale` automatically for the active locale chain when a pack is not already registered, so app bundles can split locale packs into async chunks.
|
||||
|
||||
<FrameworkCase frameworks={["html"]}>
|
||||
|
||||
HTML locale files live under `@videojs/html/i18n/locales/*`.
|
||||
|
||||
</FrameworkCase>
|
||||
|
||||
<FrameworkCase frameworks={["react"]}>
|
||||
|
||||
React locale files live under `@videojs/react/i18n/locales/*`.
|
||||
|
||||
</FrameworkCase>
|
||||
|
||||
To preload a shipped language without writing a `registerI18n` call, import its side-effect module:
|
||||
|
||||
<FrameworkCase frameworks={["html"]}>
|
||||
|
||||
```ts
|
||||
import '@videojs/html/i18n/locales/es/register';
|
||||
```
|
||||
|
||||
</FrameworkCase>
|
||||
|
||||
<FrameworkCase frameworks={["react"]}>
|
||||
|
||||
```ts
|
||||
import '@videojs/react/i18n/locales/es/register';
|
||||
```
|
||||
|
||||
</FrameworkCase>
|
||||
|
||||
Import and register a pack manually when you need custom copy or want to preload a fixed language picker. See <DocsLink slug="how-to/i18n-register-locale">Register a locale</DocsLink>.
|
||||
|
||||
<FrameworkCase frameworks={["html"]}>
|
||||
|
||||
CDN consumers load self-registering modules:
|
||||
|
||||
@@ -133,9 +233,19 @@ CDN consumers load self-registering modules:
|
||||
<script type="module" src="https://cdn.jsdelivr.net/npm/@videojs/html/cdn/locales/es.js"></script>
|
||||
```
|
||||
|
||||
</FrameworkCase>
|
||||
|
||||
## Browser translation
|
||||
|
||||
After lazy loading runs, Video.js can ask the browser to translate the English registry through the [Browser Translation API](https://developer.mozilla.org/en-US/docs/Web/API/Translator). This currently works in Chrome when `globalThis.Translator` is available and the matching on-device model is already installed.
|
||||
|
||||
Video.js does not download translation models during normal provider resolution. If Chrome reports the model as unavailable, downloadable, or still downloading, controls keep using the registered, lazy-loaded, or English fallback strings.
|
||||
|
||||
Browser translation is a fallback, not a replacement for reviewed locale packs. Use shipped packs or your own registered strings for production-critical copy and SSR.
|
||||
|
||||
## Common pitfalls
|
||||
|
||||
```tsx
|
||||
```ts
|
||||
// ❌ Don't: old camelCase keys are ignored
|
||||
registerI18n('es', { play: 'Reproducir' });
|
||||
|
||||
@@ -143,7 +253,7 @@ registerI18n('es', { play: 'Reproducir' });
|
||||
registerI18n('es', { Play: 'Reproducir' });
|
||||
```
|
||||
|
||||
```tsx
|
||||
```ts
|
||||
// ❌ Don't: parametric key without the placeholder
|
||||
registerI18n('es', { 'Seek forward {seconds} seconds': 'Adelante 10 segundos' }); // TS error: missing {seconds}
|
||||
|
||||
@@ -151,15 +261,42 @@ registerI18n('es', { 'Seek forward {seconds} seconds': 'Adelante 10 segundos' })
|
||||
registerI18n('es', { 'Seek forward {seconds} seconds': 'Adelantar {seconds} segundos' });
|
||||
```
|
||||
|
||||
<FrameworkCase frameworks={["react"]}>
|
||||
|
||||
<Aside type="tip">
|
||||
For zero flash-of-English on SSR or locale switches, pass `translations` directly to `I18nProvider` instead of relying on async `loadLocale`. See <DocsLink slug="how-to/i18n-ssr">SSR with locale</DocsLink>.
|
||||
For zero flash of English on SSR or locale switches, pass `translations` directly to `I18nProvider` or register the locale before render. See <DocsLink slug="how-to/i18n-ssr">SSR with locale</DocsLink>.
|
||||
</Aside>
|
||||
|
||||
</FrameworkCase>
|
||||
|
||||
<FrameworkCase frameworks={["html"]}>
|
||||
|
||||
<Aside type="tip">
|
||||
For zero flash of English on SSR or locale switches, register the locale before render. See <DocsLink slug="how-to/i18n-ssr">SSR with locale</DocsLink>.
|
||||
</Aside>
|
||||
|
||||
</FrameworkCase>
|
||||
|
||||
## See also
|
||||
|
||||
- <DocsLink slug="reference/locale">`Locale`</DocsLink>, <DocsLink slug="reference/translations">`Translations`</DocsLink>, <DocsLink slug="reference/translator">`Translator`</DocsLink>: I18n types
|
||||
<FrameworkCase frameworks={["html"]}>
|
||||
|
||||
- <DocsLink slug="reference/media-i18n">`<media-i18n>`</DocsLink>, <DocsLink slug="reference/locale">`Locale`</DocsLink>, <DocsLink slug="reference/translations">`Translations`</DocsLink>, <DocsLink slug="reference/translator">`Translator`</DocsLink>: I18n APIs
|
||||
- <DocsLink slug="how-to/i18n-register-locale">Register a custom locale</DocsLink>
|
||||
- <DocsLink slug="how-to/i18n-override-translations">Override individual keys</DocsLink>
|
||||
- <DocsLink slug="how-to/i18n-switch-locale">Switch locale dynamically</DocsLink>
|
||||
- <DocsLink slug="how-to/i18n-ssr">SSR and hydration</DocsLink>
|
||||
- <DocsLink slug="concepts/accessibility">Accessibility</DocsLink>: Translated ARIA labels
|
||||
|
||||
</FrameworkCase>
|
||||
|
||||
<FrameworkCase frameworks={["react"]}>
|
||||
|
||||
- <DocsLink slug="reference/i18n-provider">`I18nProvider`</DocsLink>, <DocsLink slug="reference/locale">`Locale`</DocsLink>, <DocsLink slug="reference/translations">`Translations`</DocsLink>, <DocsLink slug="reference/translator">`Translator`</DocsLink>: I18n APIs
|
||||
- <DocsLink slug="how-to/i18n-register-locale">Register a custom locale</DocsLink>
|
||||
- <DocsLink slug="how-to/i18n-override-translations">Override individual keys</DocsLink>
|
||||
- <DocsLink slug="how-to/i18n-switch-locale">Switch locale dynamically</DocsLink>
|
||||
- <DocsLink slug="how-to/i18n-ssr">SSR and hydration</DocsLink>
|
||||
- <DocsLink slug="concepts/accessibility">Accessibility</DocsLink>: Translated ARIA labels
|
||||
|
||||
</FrameworkCase>
|
||||
|
||||
@@ -1,85 +0,0 @@
|
||||
---
|
||||
title: Add a built-in locale
|
||||
description: Ship a new translation pack in @videojs/core for contributors
|
||||
---
|
||||
|
||||
import Aside from '@/components/Aside.astro';
|
||||
import DocsLink from '@/components/docs/DocsLink.astro';
|
||||
|
||||
Built-in locales live in `packages/core/src/core/i18n/locales/`. The build generates lazy loaders, CDN chunks, and HTML/React re-exports from that directory.
|
||||
|
||||
This guide is for **contributors** adding or updating shipped packs. App authors should use <DocsLink slug="how-to/i18n-register-locale">Register a custom locale</DocsLink> instead.
|
||||
|
||||
### Prerequisites
|
||||
|
||||
- Familiarity with <DocsLink slug="concepts/i18n">Internationalization</DocsLink> and <DocsLink slug="reference/translation-params">`TranslationParams`</DocsLink>
|
||||
- English defaults in `packages/core/src/core/i18n/locales/en.ts` as the source of phrases
|
||||
|
||||
## 1. Add the locale file
|
||||
|
||||
Create `packages/core/src/core/i18n/locales/{tag}.ts` using the BCP 47 tag as the filename (`pt-BR.ts`, `zh-CN.ts`):
|
||||
|
||||
```ts title="packages/core/src/core/i18n/locales/xx.ts"
|
||||
import type { Translations } from '../types';
|
||||
|
||||
export default {
|
||||
Play: '…',
|
||||
Pause: '…',
|
||||
// all phrases from en.ts; completeness is preferred
|
||||
} satisfies Partial<Translations>;
|
||||
```
|
||||
|
||||
Use the current English phrases from `en.ts`. Parametric strings must include the same `{placeholder}` tokens (TypeScript enforces this via `satisfies Partial<Translations>`).
|
||||
|
||||
Copy guidelines:
|
||||
|
||||
- `Live`: sentence case; skins uppercase via CSS where needed
|
||||
- `Seek`: slider aria label, not legacy "Progress" wording
|
||||
- `'{duration} remaining'`: pattern with `{duration}` placeholder
|
||||
- Button and error strings: short aria-label style, aligned with V10 core label usage
|
||||
|
||||
## 2. Register the tag in built-in metadata
|
||||
|
||||
Add the tag to `LOCALES` in `packages/core/src/core/i18n/locales.ts`.
|
||||
|
||||
## 3. Regenerate loaders
|
||||
|
||||
From the repo root:
|
||||
|
||||
```bash
|
||||
pnpm -F @videojs/core build
|
||||
```
|
||||
|
||||
This runs `generate:locales` and updates:
|
||||
|
||||
- `packages/core/src/core/i18n/load-locale.ts`
|
||||
- `packages/core/src/core/i18n/locales/all.ts`
|
||||
- `packages/html/src/i18n/locales/*` and `packages/react/src/i18n/locales/*` re-exports
|
||||
- CDN locale stubs via `packages/html/scripts/build-cdn-locales.ts` when building HTML CDN output
|
||||
|
||||
Do not hand-edit generated files.
|
||||
|
||||
## 4. Test
|
||||
|
||||
```bash
|
||||
pnpm -F @videojs/core test src/core/i18n
|
||||
```
|
||||
|
||||
Add or extend locale tests if the tag introduces alias or loader edge cases.
|
||||
|
||||
## 5. CDN locale chunk
|
||||
|
||||
CDN builds emit `cdn/locales/{tag}.js` that import the pack and call `registerI18n`. Verify with:
|
||||
|
||||
```bash
|
||||
pnpm -F @videojs/html build:cdn
|
||||
```
|
||||
|
||||
<Aside type="note">
|
||||
Do not copy strings blindly from Video.js v8 `lang/` JSON. V10 uses different keys and aria-label semantics. Translate from `en.ts` keys and core `getLabel` usage.
|
||||
</Aside>
|
||||
|
||||
## What's next?
|
||||
|
||||
- Open a PR with the locale file and `built-in-locales.ts` change only (generated outputs come from CI/build)
|
||||
- <DocsLink slug="concepts/i18n">Internationalization concept</DocsLink>
|
||||
@@ -8,26 +8,40 @@ import DocsLink from '@/components/docs/DocsLink.astro';
|
||||
|
||||
`registerI18n` **merges**. Each call adds or replaces phrases for that locale tag without wiping prior registrations. Use this to tweak shipped packs or A/B test copy.
|
||||
|
||||
Read <DocsLink slug="concepts/i18n">Internationalization</DocsLink> for merge order and phrase naming.
|
||||
Read <DocsLink slug="concepts/i18n">Internationalization</DocsLink> for merge order and <DocsLink slug="reference/translation-phrases">Translation phrases</DocsLink> for the supported keys.
|
||||
|
||||
## Override after a built-in pack
|
||||
|
||||
<FrameworkCase frameworks={["html"]}>
|
||||
|
||||
```ts
|
||||
import { registerI18n } from '@videojs/html/i18n';
|
||||
import es from '@videojs/html/i18n/locales/es';
|
||||
import '@videojs/html/i18n/locales/es/register';
|
||||
|
||||
registerI18n('es', es);
|
||||
registerI18n('es', { Play: 'Comenzar' }); // only `Play` changes
|
||||
```
|
||||
|
||||
</FrameworkCase>
|
||||
|
||||
<FrameworkCase frameworks={["react"]}>
|
||||
|
||||
```ts
|
||||
import { registerI18n } from '@videojs/react/i18n';
|
||||
import '@videojs/react/i18n/locales/es/register';
|
||||
|
||||
registerI18n('es', { Play: 'Comenzar' }); // only `Play` changes
|
||||
```
|
||||
|
||||
</FrameworkCase>
|
||||
|
||||
Later registrations win for the same phrase. The rest of the `es` pack stays intact.
|
||||
|
||||
<FrameworkCase frameworks={["react"]}>
|
||||
|
||||
## React provider overrides
|
||||
|
||||
Pass `translations` on <DocsLink slug="reference/i18n-provider">`I18nProvider`</DocsLink> to scope overrides to one subtree. This layer sits **above** registry and lazy packs:
|
||||
|
||||
<FrameworkCase frameworks={["react"]}>
|
||||
|
||||
```tsx
|
||||
import { I18nProvider } from '@videojs/react/i18n';
|
||||
import { Provider, VideoSkin, Video } from '@videojs/react/video';
|
||||
@@ -53,6 +67,8 @@ Nested providers inherit the parent locale when you only pass `translations`:
|
||||
|
||||
</FrameworkCase>
|
||||
|
||||
<FrameworkCase frameworks={["html"]}>
|
||||
|
||||
## HTML reflected text
|
||||
|
||||
Use <DocsLink slug="reference/media-text">`<media-text>`</DocsLink> for static copy outside buttons:
|
||||
@@ -65,6 +81,8 @@ Use <DocsLink slug="reference/media-text">`<media-text>`</DocsLink> for static c
|
||||
|
||||
Override the phrase in the registry or set `lang` on the provider to a locale where you patched `Play`.
|
||||
|
||||
</FrameworkCase>
|
||||
|
||||
## Parametric phrases
|
||||
|
||||
Keep required placeholders when overriding:
|
||||
|
||||
@@ -7,62 +7,75 @@ import FrameworkCase from '@/components/docs/FrameworkCase.astro';
|
||||
import Aside from '@/components/Aside.astro';
|
||||
import DocsLink from '@/components/docs/DocsLink.astro';
|
||||
|
||||
Register strings once with <DocsLink slug="reference/register-i18n">`registerI18n`</DocsLink>, then set `lang` on the page or pass `locale` to a provider. Read <DocsLink slug="concepts/i18n">Internationalization</DocsLink> first if you are new to phrase keys and the registry.
|
||||
Video.js is English by default. Built-in packs lazy-load automatically for app bundles; use <DocsLink slug="reference/register-i18n">`registerI18n`</DocsLink> when you have custom strings, need synchronous first paint, or load locales from the CDN.
|
||||
|
||||
<FrameworkCase frameworks={["html"]}>
|
||||
|
||||
To opt into another language, mount `<media-i18n>` and set its `lang` attribute or an ancestor `lang` attribute.
|
||||
|
||||
</FrameworkCase>
|
||||
|
||||
<FrameworkCase frameworks={["react"]}>
|
||||
|
||||
To opt into another language, mount `I18nProvider`. Pass its `locale` prop to force a tag, or omit it to inherit `lang`.
|
||||
|
||||
</FrameworkCase>
|
||||
|
||||
Read <DocsLink slug="concepts/i18n">Internationalization</DocsLink> first if you are new to phrase keys and the registry.
|
||||
|
||||
### Prerequisites
|
||||
|
||||
- A locale tag ([BCP 47](https://www.rfc-editor.org/rfc/rfc5646), e.g. `es`, `pt-BR`)
|
||||
- A partial translation map keyed by current English phrases (`Play`, `Pause`, …)
|
||||
|
||||
## Use a shipped pack
|
||||
## Use a shipped pack synchronously
|
||||
|
||||
Built-in packs live in `@videojs/*/i18n/locales/*`. Import and register before the player renders:
|
||||
Built-in packs include side-effect modules that register a language before the player renders:
|
||||
|
||||
<FrameworkCase frameworks={["html"]}>
|
||||
|
||||
```ts title="main.ts"
|
||||
import '@videojs/html/video';
|
||||
import { registerI18n } from '@videojs/html/i18n';
|
||||
import es from '@videojs/html/i18n/locales/es';
|
||||
|
||||
registerI18n('es', es);
|
||||
import '@videojs/html/i18n/locales/es/register';
|
||||
```
|
||||
|
||||
```html title="index.html"
|
||||
<html lang="es">
|
||||
<video-player>
|
||||
<video-skin>
|
||||
<video src="..." playsinline></video>
|
||||
</video-skin>
|
||||
</video-player>
|
||||
<media-i18n>
|
||||
<video-player>
|
||||
<video-skin>
|
||||
<video src="..." playsinline></video>
|
||||
</video-skin>
|
||||
</video-player>
|
||||
</media-i18n>
|
||||
</html>
|
||||
```
|
||||
|
||||
If you skip `registerI18n`, the built-in provider still **lazy-loads** `es` when `lang="es"`. Explicit registration avoids the async gap on first paint.
|
||||
Without the side-effect import, `<media-i18n>` lazy-loads `es` when it resolves `lang="es"`. The import makes the first paint synchronous.
|
||||
|
||||
</FrameworkCase>
|
||||
|
||||
<FrameworkCase frameworks={["react"]}>
|
||||
|
||||
```tsx title="app.tsx"
|
||||
import { registerI18n } from '@videojs/react/i18n';
|
||||
import es from '@videojs/react/i18n/locales/es';
|
||||
import { I18nProvider } from '@videojs/react/i18n';
|
||||
import '@videojs/react/i18n/locales/es/register';
|
||||
import { Provider, VideoSkin, Video } from '@videojs/react/video';
|
||||
|
||||
registerI18n('es', es);
|
||||
|
||||
export function App() {
|
||||
return (
|
||||
<Provider>
|
||||
<VideoSkin>
|
||||
<Video src="..." playsInline />
|
||||
</VideoSkin>
|
||||
<I18nProvider locale="es">
|
||||
<VideoSkin>
|
||||
<Video src="..." playsInline />
|
||||
</VideoSkin>
|
||||
</I18nProvider>
|
||||
</Provider>
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
Preset skins use `Container`, which includes <DocsLink slug="reference/i18n-provider">`I18nProvider`</DocsLink>. Set `<html lang="es">` or wrap with `<I18nProvider locale="es">`.
|
||||
Wrap the player subtree with <DocsLink slug="reference/i18n-provider">`I18nProvider`</DocsLink>. Omit `locale` to inherit `<html lang="es">`.
|
||||
|
||||
</FrameworkCase>
|
||||
|
||||
@@ -102,29 +115,48 @@ export default es;
|
||||
|
||||
</FrameworkCase>
|
||||
|
||||
<FrameworkCase frameworks={["html"]}>
|
||||
|
||||
```ts
|
||||
import { registerI18n } from '@videojs/html/i18n'; // or @videojs/react/i18n
|
||||
import { registerI18n } from '@videojs/html/i18n';
|
||||
import es from './my-es';
|
||||
|
||||
registerI18n('es', es);
|
||||
```
|
||||
|
||||
All keys are optional. Missing keys fall back through the BCP 47 chain to English.
|
||||
</FrameworkCase>
|
||||
|
||||
<FrameworkCase frameworks={["react"]}>
|
||||
|
||||
```ts
|
||||
import { registerI18n } from '@videojs/react/i18n';
|
||||
import es from './my-es';
|
||||
|
||||
registerI18n('es', es);
|
||||
```
|
||||
|
||||
</FrameworkCase>
|
||||
|
||||
All keys are optional. Missing keys follow the <DocsLink slug="concepts/i18n">locale fallback chain</DocsLink> through a built-in pack, browser-translated copy in supported Chrome builds, or English.
|
||||
|
||||
<FrameworkCase frameworks={["html"]}>
|
||||
|
||||
## CDN
|
||||
|
||||
Load the player and a locale chunk. Locale modules call `registerI18n` on import:
|
||||
Load the player and a locale chunk. CDN locale modules call <DocsLink slug="reference/register-i18n">`registerI18n`</DocsLink> on import:
|
||||
|
||||
```html
|
||||
<script type="module" src="https://cdn.jsdelivr.net/npm/@videojs/html/cdn/video.js"></script>
|
||||
<script type="module" src="https://cdn.jsdelivr.net/npm/@videojs/html/cdn/locales/es.js"></script>
|
||||
|
||||
<html lang="es">
|
||||
<video-player>
|
||||
<video-skin>
|
||||
<video src="..." playsinline></video>
|
||||
</video-skin>
|
||||
</video-player>
|
||||
<media-i18n>
|
||||
<video-player>
|
||||
<video-skin>
|
||||
<video src="..." playsinline></video>
|
||||
</video-skin>
|
||||
</video-player>
|
||||
</media-i18n>
|
||||
</html>
|
||||
```
|
||||
|
||||
@@ -143,7 +175,9 @@ registerI18n('es', {
|
||||
});
|
||||
```
|
||||
|
||||
Load your module after the player script, before playback starts.
|
||||
Load your module after the player script and before playback starts.
|
||||
|
||||
</FrameworkCase>
|
||||
|
||||
## What's next?
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@ import FrameworkCase from '@/components/docs/FrameworkCase.astro';
|
||||
import Aside from '@/components/Aside.astro';
|
||||
import DocsLink from '@/components/docs/DocsLink.astro';
|
||||
|
||||
Server-rendered pages should output the correct `lang` **and** supply translations on the first client render. Lazy `loadLocale` runs after hydration. Without preloaded copy, controls briefly show English.
|
||||
Video.js is English by default. Server-rendered pages that opt into another language should mount the relevant provider, output the correct `lang`, and supply translations on the first client render. Lazy `loadLocale` and browser translation fallback run after hydration, so controls briefly show English without preloaded copy.
|
||||
|
||||
Read <DocsLink slug="concepts/i18n">Internationalization</DocsLink> for provider resolution and merge order.
|
||||
|
||||
@@ -19,14 +19,18 @@ Render the document language on the server:
|
||||
<html lang="es">
|
||||
```
|
||||
|
||||
React providers use a server snapshot of `undefined` for ambient lang, then read `<html lang>` on hydration. Passing `locale` explicitly avoids any mismatch.
|
||||
<FrameworkCase frameworks={["react"]}>
|
||||
|
||||
## Preload translations (React)
|
||||
React providers use a server snapshot of `undefined` for ambient lang, then read `<html lang>` on hydration. Passing the `locale` prop explicitly avoids any mismatch.
|
||||
|
||||
Import the locale pack on the server (or in a server component) and pass it to <DocsLink slug="reference/i18n-provider">`I18nProvider`</DocsLink>:
|
||||
</FrameworkCase>
|
||||
|
||||
<FrameworkCase frameworks={["react"]}>
|
||||
|
||||
## Preload translations
|
||||
|
||||
Import the locale pack on the server (or in a server component) and pass it to <DocsLink slug="reference/i18n-provider">`I18nProvider`</DocsLink>:
|
||||
|
||||
```tsx
|
||||
import { I18nProvider } from '@videojs/react/i18n';
|
||||
import { Provider, VideoSkin, Video } from '@videojs/react/video';
|
||||
@@ -46,13 +50,44 @@ export async function Player({ locale }: { locale: string }) {
|
||||
}
|
||||
```
|
||||
|
||||
`translations` on the first render skips the async lazy layer. Labels match on server and client.
|
||||
`translations` on the first render skips the async lazy layer and Chrome-only browser translation fallback. Labels match on server and client.
|
||||
|
||||
</FrameworkCase>
|
||||
|
||||
## Register on the server
|
||||
|
||||
For custom packs, call <DocsLink slug="reference/register-i18n">`registerI18n`</DocsLink> in server bootstrap code before rendering players:
|
||||
For a shipped pack, import its side-effect module in server bootstrap code before rendering players:
|
||||
|
||||
<FrameworkCase frameworks={["html"]}>
|
||||
|
||||
```ts
|
||||
import '@videojs/html/i18n/locales/es/register';
|
||||
```
|
||||
|
||||
</FrameworkCase>
|
||||
|
||||
<FrameworkCase frameworks={["react"]}>
|
||||
|
||||
```ts
|
||||
import '@videojs/react/i18n/locales/es/register';
|
||||
```
|
||||
|
||||
</FrameworkCase>
|
||||
|
||||
For a custom pack, call <DocsLink slug="reference/register-i18n">`registerI18n`</DocsLink> instead:
|
||||
|
||||
<FrameworkCase frameworks={["html"]}>
|
||||
|
||||
```ts
|
||||
import { registerI18n } from '@videojs/html/i18n';
|
||||
import es from './locales/es';
|
||||
|
||||
registerI18n('es', es);
|
||||
```
|
||||
|
||||
</FrameworkCase>
|
||||
|
||||
<FrameworkCase frameworks={["react"]}>
|
||||
|
||||
```ts
|
||||
import { registerI18n } from '@videojs/react/i18n';
|
||||
@@ -61,8 +96,12 @@ import es from './locales/es';
|
||||
registerI18n('es', es);
|
||||
```
|
||||
|
||||
</FrameworkCase>
|
||||
|
||||
The registry is module singleton state. Registration in server entry points carries into the client bundle when shared.
|
||||
|
||||
<FrameworkCase frameworks={["react"]}>
|
||||
|
||||
## next-intl and app routers
|
||||
|
||||
```tsx
|
||||
@@ -78,22 +117,25 @@ const { default: translations } = await import(`@videojs/react/i18n/locales/${lo
|
||||
|
||||
Match your app's locale negotiation. Video.js does not replace framework i18n; it consumes the tag you pass.
|
||||
|
||||
</FrameworkCase>
|
||||
|
||||
<FrameworkCase frameworks={["html"]}>
|
||||
|
||||
## HTML custom elements
|
||||
|
||||
SSR HTML players should emit `lang` on `<html>` or on <DocsLink slug="reference/media-i18n">`<media-i18n>`</DocsLink>. Register packs in the entry module loaded before custom elements upgrade:
|
||||
SSR HTML players should emit `lang` and wrap the player with <DocsLink slug="reference/media-i18n">`<media-i18n>`</DocsLink>. Register packs in the entry module loaded before custom elements upgrade:
|
||||
|
||||
```ts
|
||||
import '@videojs/html/video';
|
||||
import { registerI18n } from '@videojs/html/i18n';
|
||||
import es from '@videojs/html/i18n/locales/es';
|
||||
|
||||
registerI18n('es', es);
|
||||
import '@videojs/html/i18n/locales/es/register';
|
||||
```
|
||||
|
||||
<Aside type="caution">
|
||||
Do not rely on browser-only APIs (`getBrowserTranslations`) during SSR. Ship packs or register strings explicitly.
|
||||
Do not rely on browser-only translation APIs during SSR. Ship packs or register strings explicitly.
|
||||
</Aside>
|
||||
|
||||
</FrameworkCase>
|
||||
|
||||
## What's next?
|
||||
|
||||
- <DocsLink slug="how-to/i18n-switch-locale">Switch locale at runtime</DocsLink>
|
||||
|
||||
@@ -7,11 +7,11 @@ import FrameworkCase from '@/components/docs/FrameworkCase.astro';
|
||||
import Aside from '@/components/Aside.astro';
|
||||
import DocsLink from '@/components/docs/DocsLink.astro';
|
||||
|
||||
Video.js re-resolves translations when the active locale changes. How you trigger that depends on the platform.
|
||||
Video.js starts in English and re-resolves translations when you opt into another active locale. How you trigger that depends on the platform.
|
||||
|
||||
### Prerequisites
|
||||
|
||||
- <DocsLink slug="how-to/i18n-register-locale">Locale packs registered or lazy-loadable</DocsLink>
|
||||
- A target locale from a shipped lazy-loaded pack, a registered custom pack, or a Chrome browser translation fallback
|
||||
|
||||
## Ambient `<html lang>`
|
||||
|
||||
@@ -22,22 +22,32 @@ document.documentElement.lang = 'fr';
|
||||
```
|
||||
|
||||
<Aside type="note">
|
||||
Ambient switching only applies when no provider sets an explicit locale. React `I18nProvider locale={…}`, HTML `<media-i18n lang="…">`, and `element.lang` on a provider all override `<html lang>` until you remove or update that override.
|
||||
</Aside>
|
||||
|
||||
<FrameworkCase frameworks={["html"]}>
|
||||
|
||||
Player elements and skins observe `lang` on `<html>` and ancestors. No remount required.
|
||||
Ambient switching only applies when `<media-i18n>` has no explicit `lang` attribute.
|
||||
|
||||
</FrameworkCase>
|
||||
|
||||
<FrameworkCase frameworks={["react"]}>
|
||||
|
||||
`Container`'s <DocsLink slug="reference/i18n-provider">`I18nProvider`</DocsLink> reads `langRootRef` from the player shell. Updating `<html lang>` is enough when you are not forcing `locale` on an outer provider.
|
||||
Ambient switching only applies when `I18nProvider` has no explicit `locale` prop.
|
||||
|
||||
</FrameworkCase>
|
||||
</Aside>
|
||||
|
||||
<FrameworkCase frameworks={["html"]}>
|
||||
|
||||
Mounted `<media-i18n>` providers observe `lang` on `<html>` and ancestors. No remount required.
|
||||
|
||||
</FrameworkCase>
|
||||
|
||||
## Explicit provider locale
|
||||
<FrameworkCase frameworks={["react"]}>
|
||||
|
||||
An <DocsLink slug="reference/i18n-provider">`I18nProvider`</DocsLink> without `locale` reads `<html lang>`. Updating it is enough when you are not forcing an explicit locale.
|
||||
|
||||
</FrameworkCase>
|
||||
|
||||
## Explicit provider language
|
||||
|
||||
<FrameworkCase frameworks={["react"]}>
|
||||
|
||||
@@ -84,27 +94,23 @@ Changing `locale` triggers lazy `loadLocale` for built-in packs.
|
||||
</script>
|
||||
```
|
||||
|
||||
Or set `document.documentElement.lang` if the player inherits ambient language.
|
||||
Or set `document.documentElement.lang` when the mounted `<media-i18n>` inherits ambient language.
|
||||
|
||||
</FrameworkCase>
|
||||
|
||||
## Avoid flash while switching
|
||||
|
||||
Async lazy loads can briefly show English. Preload copy before the active locale changes with one of three common patterns:
|
||||
Async lazy loads and browser translation fallback can briefly show English. Preload copy before the active locale changes with one of three common patterns:
|
||||
|
||||
### Pre-register at bootstrap (React and HTML)
|
||||
### Preload at bootstrap
|
||||
|
||||
<DocsLink slug="reference/register-i18n">`registerI18n`</DocsLink> 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.
|
||||
Side-effect locale modules register shipped packs before the provider renders. Preload every language in a fixed picker to avoid the async gap.
|
||||
|
||||
<FrameworkCase frameworks={["react"]}>
|
||||
|
||||
```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);
|
||||
import '@videojs/react/i18n/locales/es/register';
|
||||
import '@videojs/react/i18n/locales/fr/register';
|
||||
|
||||
// Switching locale is instant: no remount, no lazy-load gap
|
||||
<I18nProvider locale={userLocale}>
|
||||
@@ -117,12 +123,8 @@ registerI18n('fr', fr);
|
||||
<FrameworkCase frameworks={["html"]}>
|
||||
|
||||
```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);
|
||||
import '@videojs/html/i18n/locales/es/register';
|
||||
import '@videojs/html/i18n/locales/fr/register';
|
||||
```
|
||||
|
||||
```html
|
||||
@@ -137,7 +139,9 @@ registerI18n('fr', fr);
|
||||
|
||||
</FrameworkCase>
|
||||
|
||||
### Prefetch before switching (React)
|
||||
<FrameworkCase frameworks={["react"]}>
|
||||
|
||||
### Prefetch before switching
|
||||
|
||||
When you cannot register every locale up front, import and register immediately before updating `locale`:
|
||||
|
||||
@@ -174,7 +178,7 @@ async function switchTo(next: string) {
|
||||
|
||||
| Approach | Scope | Best for |
|
||||
| --- | --- | --- |
|
||||
| `registerI18n` at bootstrap | Global, all providers | Language picker with a fixed set of locales |
|
||||
| Side-effect locale imports | Global, all providers | Language picker with a fixed set of shipped locales |
|
||||
| `registerI18n` before switch | Global, all providers | On-demand prefetch before changing `locale` |
|
||||
| `I18nProvider translations` | Single provider subtree | Scoped overrides, SSR first paint |
|
||||
|
||||
@@ -186,9 +190,13 @@ async function switchTo(next: string) {
|
||||
For server-rendered first paint, see <DocsLink slug="how-to/i18n-ssr">SSR and hydration</DocsLink>.
|
||||
</Aside>
|
||||
|
||||
## CDN
|
||||
</FrameworkCase>
|
||||
|
||||
Reload or navigate with an updated `locale` query parameter, or load a different locale module before playback. CDN shells typically full-reload on locale change because locale script tags are not hot-swappable.
|
||||
## Browser translation fallback
|
||||
|
||||
If a switched locale has no registered or shipped pack, Video.js can use Chrome's [Browser Translation API](https://developer.mozilla.org/en-US/docs/Web/API/Translator) when the browser exposes `globalThis.Translator` and already has the target model installed. This is automatic after lazy loading is attempted.
|
||||
|
||||
Do not rely on it for instant switching. Preload or register reviewed packs when the language picker should update without a flash of English.
|
||||
|
||||
## What's next?
|
||||
|
||||
|
||||
@@ -1,44 +0,0 @@
|
||||
---
|
||||
title: BuiltInLocale
|
||||
description: Union of shipped BCP 47 locale tags with autocomplete in TypeScript
|
||||
---
|
||||
|
||||
import DocsLink from '@/components/docs/DocsLink.astro';
|
||||
|
||||
`BuiltInLocale` narrows <DocsLink slug="reference/locale">`Locale`</DocsLink> to tags with shipped translation packs. TypeScript suggests these tags when you call `registerI18n`, `loadLocale`, or import locale modules.
|
||||
|
||||
## App imports
|
||||
|
||||
```ts
|
||||
import es from '@videojs/html/i18n/locales/es';
|
||||
// or @videojs/react/i18n/locales/es
|
||||
```
|
||||
|
||||
## Definition
|
||||
|
||||
```ts
|
||||
type BuiltInLocale = (typeof LOCALES)[number];
|
||||
```
|
||||
|
||||
`LOCALES` lists shipped packs (`es`, `pt-BR`, `zh-CN`, …). Bare language tags such as `pt` and `zh` are handled by the normal locale lookup chain when there is a matching registered or loaded layer.
|
||||
|
||||
## Lazy loading
|
||||
|
||||
Providers call `loadLocale(tag)` for tags in the resolved locale chain when a pack is not already registered. Explicit `registerI18n` or CDN locale modules skip the async gap on first paint.
|
||||
|
||||
## Examples
|
||||
|
||||
```ts
|
||||
import { registerI18n } from '@videojs/react/i18n';
|
||||
import es from '@videojs/react/i18n/locales/es';
|
||||
|
||||
registerI18n('es', es); // 'es' autocompletes as BuiltInLocale
|
||||
```
|
||||
|
||||
Custom app locales (`'xx'`) use `Locale` but are not members of `BuiltInLocale`.
|
||||
|
||||
## Related
|
||||
|
||||
- <DocsLink slug="reference/locale">`Locale`</DocsLink>
|
||||
- <DocsLink slug="how-to/i18n-add-built-in-locale">Add a built-in locale (contributors)</DocsLink>
|
||||
- <DocsLink slug="how-to/i18n-register-locale">Register a custom locale</DocsLink>
|
||||
@@ -1,21 +1,38 @@
|
||||
---
|
||||
title: createI18n
|
||||
description: Factory that creates a React i18n provider with custom loading options
|
||||
description: Factory that creates framework i18n helpers with custom loading options
|
||||
---
|
||||
|
||||
import UtilReference from "@/components/docs/api-reference/UtilReference.astro";
|
||||
import DocsLink from "@/components/docs/DocsLink.astro";
|
||||
import FrameworkCase from "@/components/docs/FrameworkCase.astro";
|
||||
|
||||
<FrameworkCase frameworks={["html"]}>
|
||||
|
||||
`createI18n` returns a context-bound `ProviderMixin`, `TextMixin`, and `I18nController` for custom elements. Use it when you need a custom locale loader or custom i18n elements. Most apps use `<media-i18n>` and `<media-text>` from `@videojs/html/i18n`.
|
||||
|
||||
```ts
|
||||
import { ReactiveElement } from '@videojs/element';
|
||||
import { createI18n } from '@videojs/html/i18n';
|
||||
|
||||
const { ProviderMixin, TextMixin } = createI18n();
|
||||
|
||||
class LocalizedRoot extends ProviderMixin(ReactiveElement) {}
|
||||
class LocalizedText extends TextMixin(ReactiveElement) {}
|
||||
```
|
||||
|
||||
<UtilReference util="createI18n" />
|
||||
|
||||
</FrameworkCase>
|
||||
|
||||
<FrameworkCase frameworks={["react"]}>
|
||||
|
||||
`createI18n` returns an `I18nProvider`, `useTranslator`, and `useLocale` wired to the shared React i18n context used by the stock skins and controls. Use it when you need options such as a custom locale loader. Most apps import the default exports from `@videojs/react/i18n` instead.
|
||||
`createI18n` returns an `I18nProvider`, `useTranslator`, and `useLocale` wired to the shared React i18n context used by the stock skins and controls. Use it when you need options such as a custom locale loader. Most apps use the default exports from `@videojs/react/i18n`.
|
||||
|
||||
```tsx
|
||||
import { createI18n } from '@videojs/react/i18n';
|
||||
|
||||
const { I18nProvider, useTranslator } = createI18n({
|
||||
loadLocale: async (tag) => {
|
||||
loader: async (tag) => {
|
||||
const mod = await import(`@videojs/react/i18n/locales/${tag}`);
|
||||
return mod.default;
|
||||
},
|
||||
|
||||
@@ -5,16 +5,32 @@ description: Build a typed translator from a resolved translation map
|
||||
|
||||
import UtilReference from "@/components/docs/api-reference/UtilReference.astro";
|
||||
import DocsLink from "@/components/docs/DocsLink.astro";
|
||||
import FrameworkCase from "@/components/docs/FrameworkCase.astro";
|
||||
|
||||
`createTranslator` wraps a <DocsLink slug="reference/translations">`Translations`</DocsLink> map and returns a <DocsLink slug="reference/translator">`Translator`</DocsLink>. Providers call this internally after merging registry, lazy, and prop layers. Use it directly for custom UI outside built-in mixins.
|
||||
`createTranslator` wraps a <DocsLink slug="reference/translations">`Translations`</DocsLink> map and returns a <DocsLink slug="reference/translator">`Translator`</DocsLink>. Providers call this internally after merging registry, lazy-loaded built-in packs, browser-translated fallback copy, and provider layers. Use it directly for custom UI outside built-in controls.
|
||||
|
||||
<FrameworkCase frameworks={["html"]}>
|
||||
|
||||
```ts
|
||||
import { createTranslator, getI18nTranslations } from '@videojs/html/i18n';
|
||||
// or @videojs/react/i18n
|
||||
|
||||
const t = createTranslator(getI18nTranslations('fr'), 'fr');
|
||||
t('Play');
|
||||
t('Seek forward {seconds} seconds', { seconds: 5 });
|
||||
```
|
||||
|
||||
</FrameworkCase>
|
||||
|
||||
<FrameworkCase frameworks={["react"]}>
|
||||
|
||||
```ts
|
||||
import { createTranslator, getI18nTranslations } from '@videojs/react/i18n';
|
||||
|
||||
const t = createTranslator(getI18nTranslations('fr'), 'fr');
|
||||
t('Play');
|
||||
t('Seek forward {seconds} seconds', { seconds: 5 });
|
||||
```
|
||||
|
||||
</FrameworkCase>
|
||||
|
||||
<UtilReference util="createTranslator" />
|
||||
|
||||
@@ -5,17 +5,32 @@ description: Read the merged translation map for a locale using BCP 47 parent-ch
|
||||
|
||||
import UtilReference from "@/components/docs/api-reference/UtilReference.astro";
|
||||
import DocsLink from "@/components/docs/DocsLink.astro";
|
||||
import FrameworkCase from "@/components/docs/FrameworkCase.astro";
|
||||
|
||||
`getI18nTranslations` walks the BCP 47 lookup chain (`es-MX` → `es` → `en`) and merges registry layers into one map. Providers and `createTranslator` use this internally; call it directly when building custom UI outside the built-in mixins.
|
||||
`getI18nTranslations` walks the BCP 47 lookup chain (`es-MX` → `es` → `en`) and merges registry layers into one map. Providers combine this map with lazy-loaded built-in packs and provider overrides. Call it directly when building custom UI outside built-in controls.
|
||||
|
||||
See <DocsLink slug="concepts/i18n">Internationalization</DocsLink> for merge order and fallback rules.
|
||||
|
||||
<FrameworkCase frameworks={["html"]}>
|
||||
|
||||
```ts
|
||||
import { createTranslator, getI18nTranslations } from '@videojs/html/i18n';
|
||||
// or @videojs/react/i18n
|
||||
|
||||
const t = createTranslator(getI18nTranslations('pt-BR'), 'pt-BR');
|
||||
t('Play'); // merged Portuguese string
|
||||
t('Play');
|
||||
```
|
||||
|
||||
</FrameworkCase>
|
||||
|
||||
<FrameworkCase frameworks={["react"]}>
|
||||
|
||||
```ts
|
||||
import { createTranslator, getI18nTranslations } from '@videojs/react/i18n';
|
||||
|
||||
const t = createTranslator(getI18nTranslations('pt-BR'), 'pt-BR');
|
||||
t('Play');
|
||||
```
|
||||
|
||||
</FrameworkCase>
|
||||
|
||||
<UtilReference util="getI18nTranslations" />
|
||||
|
||||
@@ -5,8 +5,11 @@ description: Check whether an exact locale tag exists in the global i18n registr
|
||||
|
||||
import UtilReference from "@/components/docs/api-reference/UtilReference.astro";
|
||||
import DocsLink from "@/components/docs/DocsLink.astro";
|
||||
import FrameworkCase from "@/components/docs/FrameworkCase.astro";
|
||||
|
||||
`hasRegisteredLocale` returns whether a normalized locale tag has an explicit registry layer from `registerI18n`. It does **not** indicate whether a lazy built-in pack exists. Only registry entries count.
|
||||
`hasRegisteredLocale` returns whether a normalized locale tag has an explicit registry layer from <DocsLink slug="reference/register-i18n">`registerI18n`</DocsLink>. It does **not** indicate whether a lazy built-in pack exists. Only registry entries count.
|
||||
|
||||
<FrameworkCase frameworks={["html"]}>
|
||||
|
||||
```ts
|
||||
import { hasRegisteredLocale, registerI18n } from '@videojs/html/i18n';
|
||||
@@ -16,4 +19,18 @@ registerI18n('fr', { Play: 'Lecture' });
|
||||
hasRegisteredLocale('fr'); // true
|
||||
```
|
||||
|
||||
</FrameworkCase>
|
||||
|
||||
<FrameworkCase frameworks={["react"]}>
|
||||
|
||||
```ts
|
||||
import { hasRegisteredLocale, registerI18n } from '@videojs/react/i18n';
|
||||
|
||||
hasRegisteredLocale('fr'); // false until registered
|
||||
registerI18n('fr', { Play: 'Lecture' });
|
||||
hasRegisteredLocale('fr'); // true
|
||||
```
|
||||
|
||||
</FrameworkCase>
|
||||
|
||||
<UtilReference util="hasRegisteredLocale" />
|
||||
|
||||
@@ -9,7 +9,7 @@ import FrameworkCase from "@/components/docs/FrameworkCase.astro";
|
||||
|
||||
<FrameworkCase frameworks={["react"]}>
|
||||
|
||||
`I18nProvider` resolves the active locale, merges registry and lazy pack layers, and exposes a translator through context. Preset skins mount it inside <DocsLink slug="reference/player-container">`Container`</DocsLink> with `langRootRef` on the player shell.
|
||||
`I18nProvider` resolves the active locale, lazy-loads built-in packs, merges registry and provider layers, and exposes a translator through context. Wrap it around a player or custom controls that should translate.
|
||||
|
||||
Wrap custom controls or force a locale explicitly:
|
||||
|
||||
@@ -21,7 +21,7 @@ import { I18nProvider } from '@videojs/react/i18n';
|
||||
</I18nProvider>
|
||||
```
|
||||
|
||||
Omit `locale` to inherit the nearest `lang` attribute (via `langRootRef` or `<html lang>`). See <DocsLink slug="concepts/i18n">Internationalization</DocsLink> for merge priority and SSR guidance.
|
||||
Omit `locale` to inherit the nearest `lang` attribute (via `langRootRef` or `<html lang>`). English is the fallback when no non-English locale is active or no translation layer supplies a string. See <DocsLink slug="concepts/i18n">Internationalization</DocsLink> for merge priority, browser translation fallback, and SSR guidance.
|
||||
|
||||
<UtilReference util="I18nProvider" />
|
||||
|
||||
|
||||
@@ -4,38 +4,55 @@ description: BCP 47 language tag type for i18n registry and provider APIs
|
||||
---
|
||||
|
||||
import DocsLink from '@/components/docs/DocsLink.astro';
|
||||
import FrameworkCase from '@/components/docs/FrameworkCase.astro';
|
||||
|
||||
`Locale` is the BCP 47 tag type used by <DocsLink slug="reference/register-i18n">`registerI18n`</DocsLink>, providers, and <DocsLink slug="reference/translator">`Translator`</DocsLink>. Shipped packs autocomplete as <DocsLink slug="reference/built-in-locale">`BuiltInLocale`</DocsLink>; any other tag remains valid at runtime.
|
||||
`Locale` is the BCP 47 tag type used by <DocsLink slug="reference/register-i18n">`registerI18n`</DocsLink> and provider APIs. Shipped tags autocomplete, and any other BCP 47 tag remains valid at runtime.
|
||||
|
||||
## Import
|
||||
|
||||
<FrameworkCase frameworks={["html"]}>
|
||||
|
||||
```ts
|
||||
import type { Locale } from '@videojs/html/i18n';
|
||||
// or @videojs/react/i18n
|
||||
```
|
||||
|
||||
</FrameworkCase>
|
||||
|
||||
<FrameworkCase frameworks={["react"]}>
|
||||
|
||||
```ts
|
||||
import type { Locale } from '@videojs/react/i18n';
|
||||
```
|
||||
|
||||
</FrameworkCase>
|
||||
|
||||
## Definition
|
||||
|
||||
```ts
|
||||
type Locale = BuiltInLocale | (string & {});
|
||||
type Locale = (typeof LOCALES)[number] | (string & {});
|
||||
```
|
||||
|
||||
The `(string & {})` pattern keeps custom tags (`'xx'`, `'en-US'`) type-safe without losing autocomplete for built-ins.
|
||||
The `(string & {})` pattern keeps custom tags (`'xx'`, `'en-US'`) type-safe without losing autocomplete for shipped tags.
|
||||
|
||||
## Provider use
|
||||
|
||||
<FrameworkCase frameworks={["html"]}>
|
||||
|
||||
Set a `lang` attribute on <DocsLink slug="reference/media-i18n">`<media-i18n>`</DocsLink>; HTML providers do not have a `locale` attribute.
|
||||
|
||||
</FrameworkCase>
|
||||
|
||||
<FrameworkCase frameworks={["react"]}>
|
||||
|
||||
Pass a `Locale` to the `locale` prop on <DocsLink slug="reference/i18n-provider">`I18nProvider`</DocsLink>, or omit the prop to inherit `lang`.
|
||||
|
||||
</FrameworkCase>
|
||||
|
||||
## Resolution
|
||||
|
||||
Providers and `getI18nTranslations` normalize tags and walk the parent chain (`es-MX` → `es` → `en`) via `findLocaleKeys`. See <DocsLink slug="concepts/i18n">Internationalization</DocsLink> for explicit vs ambient resolution.
|
||||
|
||||
## Examples
|
||||
|
||||
```ts
|
||||
const es: Locale = 'es';
|
||||
const custom: Locale = 'en-US';
|
||||
const regional: Locale = 'pt-BR';
|
||||
```
|
||||
Providers and `getI18nTranslations` normalize tags and walk the parent chain (`es-MX` → `es` → `en`) via `findLocaleKeys`. See <DocsLink slug="concepts/i18n">Internationalization</DocsLink> for explicit and ambient resolution.
|
||||
|
||||
## Related
|
||||
|
||||
- <DocsLink slug="reference/built-in-locale">`BuiltInLocale`</DocsLink>
|
||||
- <DocsLink slug="reference/register-i18n">`registerI18n`</DocsLink>
|
||||
- <DocsLink slug="how-to/i18n-switch-locale">Switch locale dynamically</DocsLink>
|
||||
|
||||
@@ -8,17 +8,14 @@ import FrameworkCase from "@/components/docs/FrameworkCase.astro";
|
||||
|
||||
<FrameworkCase frameworks={["html"]}>
|
||||
|
||||
`<media-i18n>` applies the i18n provider mixin to a standalone subtree. Built-in `<video-player>` and skins already include this mixin — use the element when rendering **controls outside a player** or when sibling players need different locales.
|
||||
`<media-i18n>` applies the i18n provider mixin to a subtree. Wrap a player, standalone controls, or one of several players that need different locales with this element. Without it, HTML controls use English defaults.
|
||||
|
||||
Register locale strings with <DocsLink slug="reference/register-i18n">`registerI18n`</DocsLink>, then set `lang` on the provider or an ancestor. See <DocsLink slug="concepts/i18n">Internationalization</DocsLink> for phrase keys and fallback behavior.
|
||||
Set `lang` on the provider or an ancestor. Built-in packs lazy-load automatically; register locale strings with <DocsLink slug="reference/register-i18n">`registerI18n`</DocsLink> when you need custom copy or synchronous first paint. See <DocsLink slug="reference/translation-phrases">Translation phrases</DocsLink> for supported keys.
|
||||
|
||||
```html
|
||||
<script type="module">
|
||||
import '@videojs/html/i18n';
|
||||
import { registerI18n } from '@videojs/html/i18n';
|
||||
import es from '@videojs/html/i18n/locales/es';
|
||||
|
||||
registerI18n('es', es);
|
||||
import '@videojs/html/i18n/locales/es/register';
|
||||
</script>
|
||||
|
||||
<media-i18n lang="es">
|
||||
|
||||
@@ -18,7 +18,7 @@ import FrameworkCase from "@/components/docs/FrameworkCase.astro";
|
||||
|
||||
## Text content
|
||||
|
||||
The initial text content is the English translation phrase (`Play`, `Pause`, `{duration} remaining`, …). If the phrase is not registered for the active locale, `<media-text>` keeps the original text.
|
||||
The initial text content is the English translation phrase (`Play`, `Pause`, `{duration} remaining`, …). See <DocsLink slug="reference/translation-phrases">Translation phrases</DocsLink> for supported keys. If the phrase is not registered for the active locale, `<media-text>` keeps the original text.
|
||||
|
||||
Parametric phrases are not yet supported on `<media-text>` — use `createTranslator` in script for interpolated strings.
|
||||
|
||||
|
||||
@@ -4,9 +4,14 @@ description: Subscribe to global i18n registry mutations
|
||||
---
|
||||
|
||||
import UtilReference from "@/components/docs/api-reference/UtilReference.astro";
|
||||
import FrameworkCase from "@/components/docs/FrameworkCase.astro";
|
||||
|
||||
`onI18nRegistryChange` registers a callback that runs whenever any locale layer changes, for example after `registerI18n` or browser translation prefetch. Returns an unsubscribe function.
|
||||
|
||||
<FrameworkCase frameworks={["react"]}>
|
||||
|
||||
React `I18nProvider` uses this to invalidate translators when the registry updates.
|
||||
|
||||
</FrameworkCase>
|
||||
|
||||
<UtilReference util="onI18nRegistryChange" />
|
||||
|
||||
@@ -5,10 +5,26 @@ description: Register or merge translation strings for a BCP 47 locale tag in th
|
||||
|
||||
import UtilReference from "@/components/docs/api-reference/UtilReference.astro";
|
||||
import DocsLink from "@/components/docs/DocsLink.astro";
|
||||
import FrameworkCase from "@/components/docs/FrameworkCase.astro";
|
||||
|
||||
`registerI18n` merges a partial translation map into the process-wide registry for a locale tag. English defaults are registered by the i18n bundle. Call `registerI18n` for custom locales or to patch shipped packs before the player renders.
|
||||
`registerI18n` merges a partial translation map into the process-wide registry for a locale tag. English defaults are registered by the i18n bundle. Built-in non-English packs lazy-load automatically; call `registerI18n` for custom locales, CDN locale modules, or patched shipped packs before the provider renders.
|
||||
|
||||
Import from `@videojs/html/i18n` or `@videojs/react/i18n`. Keys are the current English phrases (`Play`, `Pause`). See <DocsLink slug="concepts/i18n">Internationalization</DocsLink> and <DocsLink slug="reference/translations">`Translations`</DocsLink>.
|
||||
Keys are the current English phrases (`Play`, `Pause`). See <DocsLink slug="reference/translation-phrases">Translation phrases</DocsLink> and <DocsLink slug="reference/translations">`Translations`</DocsLink>.
|
||||
|
||||
<FrameworkCase frameworks={["html"]}>
|
||||
|
||||
```ts
|
||||
import { registerI18n } from '@videojs/html/i18n';
|
||||
|
||||
registerI18n('es', {
|
||||
Play: 'Reproducir',
|
||||
Pause: 'Pausar',
|
||||
});
|
||||
```
|
||||
|
||||
</FrameworkCase>
|
||||
|
||||
<FrameworkCase frameworks={["react"]}>
|
||||
|
||||
```ts
|
||||
import { registerI18n } from '@videojs/react/i18n';
|
||||
@@ -19,4 +35,6 @@ registerI18n('es', {
|
||||
});
|
||||
```
|
||||
|
||||
</FrameworkCase>
|
||||
|
||||
<UtilReference util="registerI18n" />
|
||||
|
||||
@@ -4,16 +4,30 @@ description: Typed contract for translation phrases and their placeholder argume
|
||||
---
|
||||
|
||||
import DocsLink from '@/components/docs/DocsLink.astro';
|
||||
import FrameworkCase from '@/components/docs/FrameworkCase.astro';
|
||||
|
||||
`TranslationParams` maps every current English translation phrase to its argument shape. Phrases with `never` accept only `t('Phrase')`. Phrases with an object accept `t('Phrase {value}', { … })` with typed placeholder names.
|
||||
`TranslationParams` maps every current English translation phrase to its argument shape. Phrases with `never` accept only `t('Phrase')`. Phrases with an object accept `t('Phrase {value}', { ... })` with typed placeholder names.
|
||||
|
||||
See <DocsLink slug="reference/translation-phrases">Translation phrases</DocsLink> for the complete key catalog and where each phrase appears.
|
||||
|
||||
## Import
|
||||
|
||||
<FrameworkCase frameworks={["html"]}>
|
||||
|
||||
```ts
|
||||
import type { TranslationParams } from '@videojs/html/i18n';
|
||||
// or @videojs/react/i18n
|
||||
```
|
||||
|
||||
</FrameworkCase>
|
||||
|
||||
<FrameworkCase frameworks={["react"]}>
|
||||
|
||||
```ts
|
||||
import type { TranslationParams } from '@videojs/react/i18n';
|
||||
```
|
||||
|
||||
</FrameworkCase>
|
||||
|
||||
## Definition
|
||||
|
||||
```ts
|
||||
@@ -22,7 +36,7 @@ type TranslationParams = {
|
||||
Pause: never;
|
||||
'Seek forward {seconds} seconds': { seconds: number | string };
|
||||
'{duration} remaining': { duration: string };
|
||||
// …
|
||||
// ...
|
||||
};
|
||||
```
|
||||
|
||||
@@ -39,10 +53,11 @@ English defaults and the full phrase list live in `packages/core/src/core/i18n/l
|
||||
| `{duration} remaining` | `{duration}` |
|
||||
| `{percent}, muted` | `{percent}` |
|
||||
| `Volume {value}` | `{value}` |
|
||||
| `Auto ({label})` | `{label}` |
|
||||
|
||||
All other phrases are plain strings with no parameters.
|
||||
|
||||
## Usage with Translator
|
||||
## Usage
|
||||
|
||||
```ts
|
||||
const t: Translator = createTranslator(translations, 'es');
|
||||
@@ -52,16 +67,10 @@ t('Seek forward {seconds} seconds', { seconds: 10 });
|
||||
t('{duration} remaining', { duration: '1 minute' });
|
||||
```
|
||||
|
||||
TypeScript rejects missing placeholders when defining <DocsLink slug="reference/translations">`Translations`</DocsLink> overlays:
|
||||
|
||||
```ts
|
||||
registerI18n('es', {
|
||||
'Seek forward {seconds} seconds': 'Adelantar', // error: missing {seconds}
|
||||
});
|
||||
```
|
||||
TypeScript rejects missing placeholders when defining <DocsLink slug="reference/translations">`Translations`</DocsLink> overlays.
|
||||
|
||||
## Related
|
||||
|
||||
- <DocsLink slug="reference/translations">`Translations`</DocsLink>
|
||||
- <DocsLink slug="reference/translator">`Translator`</DocsLink>
|
||||
- <DocsLink slug="concepts/i18n">Internationalization</DocsLink>: Phrase keys overview
|
||||
- <DocsLink slug="reference/translation-phrases">Translation phrases</DocsLink>
|
||||
|
||||
@@ -0,0 +1,76 @@
|
||||
---
|
||||
title: Translation phrases
|
||||
description: English i18n phrase keys and the player UI that uses them
|
||||
---
|
||||
|
||||
import DocsLink from '@/components/docs/DocsLink.astro';
|
||||
|
||||
Video.js uses the English phrases below as translation keys. They are defined in `packages/core/src/core/i18n/locales/en.ts` and typed by <DocsLink slug="reference/translation-params">`TranslationParams`</DocsLink>. Both HTML and React controls use the same keys.
|
||||
|
||||
Use these keys with <DocsLink slug="reference/register-i18n">`registerI18n`</DocsLink> or React `I18nProvider` `translations` overrides.
|
||||
|
||||
## Playback controls
|
||||
|
||||
| Phrase | Used by |
|
||||
| --- | --- |
|
||||
| `Play`, `Pause`, `Replay` | Play button and its tooltip |
|
||||
| `Mute`, `Unmute` | Mute button and its tooltip |
|
||||
| `Seek forward {seconds} seconds`, `Seek backward {seconds} seconds` | Seek buttons and their tooltips |
|
||||
| `Enter fullscreen`, `Exit fullscreen` | Fullscreen button and input feedback |
|
||||
| `Enter picture-in-picture`, `Exit picture-in-picture` | Picture-in-picture button |
|
||||
| `Enable captions`, `Disable captions` | Captions button and captions selection control |
|
||||
| `Playing live`, `Seek to live edge`, `Live` | Live button |
|
||||
| `Start casting`, `Stop casting`, `Connecting` | Cast button; `Connecting` also appears on the AirPlay button |
|
||||
|
||||
## Time and volume
|
||||
|
||||
| Phrase | Used by |
|
||||
| --- | --- |
|
||||
| `Seek` | Time slider aria label |
|
||||
| `Volume` | Volume slider aria label and input feedback |
|
||||
| `Current time`, `Duration`, `Remaining` | Time display aria labels |
|
||||
| `{duration} remaining` | Remaining time display |
|
||||
| `{duration}. Show elapsed time.`, `{duration}. Show duration.`, `{duration}. Show remaining time.` | Toggleable time display aria labels |
|
||||
| `Playback rate {rate}` | Playback-rate button and radio group |
|
||||
| `{current} of {duration}` | Time slider value text |
|
||||
| `{percent}, muted` | Muted volume slider value text |
|
||||
| `Muted`, `Volume {value}` | Volume input feedback |
|
||||
|
||||
## Playback feedback
|
||||
|
||||
| Phrase | Used by |
|
||||
| --- | --- |
|
||||
| `Captions on`, `Captions off` | Input feedback after captions changes |
|
||||
| `Paused`, `Playing` | Input feedback after playback changes |
|
||||
| `Fullscreen`, `Exit fullscreen` | Input feedback after fullscreen changes |
|
||||
| `Picture in picture`, `Exit picture in picture` | Input feedback after picture-in-picture changes |
|
||||
|
||||
## Errors
|
||||
|
||||
| Phrase | Used by |
|
||||
| --- | --- |
|
||||
| `You stopped media playback before it finished.` | Media error dialog for `MEDIA_ERR_ABORTED` |
|
||||
| `This media could not be loaded due to a network or server issue.` | Media error dialog for `MEDIA_ERR_NETWORK` |
|
||||
| `This media could not be played. It may be corrupted, or your browser may not support its format.` | Media error dialog for `MEDIA_ERR_DECODE` |
|
||||
| `This media could not be loaded. It may be unavailable, or your browser may not support its format.` | Media error dialog for `MEDIA_ERR_SRC_NOT_SUPPORTED` |
|
||||
| `This media could not be played because it could not be decrypted.` | Media error dialog for `MEDIA_ERR_ENCRYPTED` |
|
||||
| `Something went wrong.`, `An unexpected error occurred.` | Generic media error dialog title and fallback description |
|
||||
| `OK` | Error dialog confirmation button |
|
||||
|
||||
## Settings and track menus
|
||||
|
||||
| Phrase | Used by |
|
||||
| --- | --- |
|
||||
| `Settings` | Video settings menu trigger |
|
||||
| `Quality`, `Auto`, `Auto ({label})` | Quality menu and automatic-quality option |
|
||||
| `Audio` | Audio-track menu and fallback track label |
|
||||
| `Default` | Reserved default-option label; no stock control currently emits it |
|
||||
| `Speed`, `Playback rate` | Playback-rate menu and radio group |
|
||||
| `Captions`, `Subtitles`, `Off` | Captions menu and track options |
|
||||
| `Back` | Nested settings-menu back button |
|
||||
|
||||
## Related
|
||||
|
||||
- <DocsLink slug="reference/translation-params">`TranslationParams`</DocsLink>
|
||||
- <DocsLink slug="reference/translations">`Translations`</DocsLink>
|
||||
- <DocsLink slug="how-to/i18n-override-translations">Override translations</DocsLink>
|
||||
@@ -4,16 +4,36 @@ description: Partial map of English translation phrases to localized strings
|
||||
---
|
||||
|
||||
import DocsLink from '@/components/docs/DocsLink.astro';
|
||||
import FrameworkCase from '@/components/docs/FrameworkCase.astro';
|
||||
|
||||
`Translations` is the shape for locale packs passed to <DocsLink slug="reference/register-i18n">`registerI18n`</DocsLink>, the React `translations` prop on <DocsLink slug="reference/i18n-provider">`I18nProvider`</DocsLink>, and <DocsLink slug="reference/create-translator">`createTranslator`</DocsLink>. Every entry is optional. Missing keys fall back through the BCP 47 chain to English.
|
||||
`Translations` is the shape for locale packs passed to <DocsLink slug="reference/register-i18n">`registerI18n`</DocsLink> and <DocsLink slug="reference/create-translator">`createTranslator`</DocsLink>. Every entry is optional. Missing keys fall back through the BCP 47 chain, lazy-loaded built-in packs, supported browser translation fallback, and English.
|
||||
|
||||
<FrameworkCase frameworks={["react"]}>
|
||||
|
||||
`Translations` is also the type for the `translations` prop on <DocsLink slug="reference/i18n-provider">`I18nProvider`</DocsLink>.
|
||||
|
||||
</FrameworkCase>
|
||||
|
||||
See <DocsLink slug="reference/translation-phrases">Translation phrases</DocsLink> for every supported key.
|
||||
|
||||
## Import
|
||||
|
||||
<FrameworkCase frameworks={["html"]}>
|
||||
|
||||
```ts
|
||||
import type { Translations } from '@videojs/html/i18n';
|
||||
// or @videojs/react/i18n
|
||||
```
|
||||
|
||||
</FrameworkCase>
|
||||
|
||||
<FrameworkCase frameworks={["react"]}>
|
||||
|
||||
```ts
|
||||
import type { Translations } from '@videojs/react/i18n';
|
||||
```
|
||||
|
||||
</FrameworkCase>
|
||||
|
||||
## Definition
|
||||
|
||||
```ts
|
||||
@@ -25,13 +45,14 @@ type Translations = {
|
||||
};
|
||||
```
|
||||
|
||||
Parametric values must include the same `{placeholder}` substrings as English (`{seconds}`, `{duration}`, …). TypeScript enforces this when you use `satisfies Partial<Translations>`.
|
||||
Parametric values must include the same `{placeholder}` substrings as English (`{seconds}`, `{duration}`, and so on). TypeScript enforces this when you use `satisfies Partial<Translations>`.
|
||||
|
||||
## Examples
|
||||
|
||||
<FrameworkCase frameworks={["html"]}>
|
||||
|
||||
```ts
|
||||
import type { Translations } from '@videojs/html/i18n';
|
||||
// or @videojs/react/i18n
|
||||
import { registerI18n, type Translations } from '@videojs/html/i18n';
|
||||
|
||||
const es = {
|
||||
Play: 'Reproducir',
|
||||
@@ -42,10 +63,24 @@ const es = {
|
||||
registerI18n('es', es);
|
||||
```
|
||||
|
||||
</FrameworkCase>
|
||||
|
||||
<FrameworkCase frameworks={["react"]}>
|
||||
|
||||
```tsx
|
||||
<I18nProvider locale="de" translations={{ Play: 'Abspielen' }} />
|
||||
import { I18nProvider, type Translations } from '@videojs/react/i18n';
|
||||
|
||||
const translations = {
|
||||
Play: 'Abspielen',
|
||||
} satisfies Partial<Translations>;
|
||||
|
||||
<I18nProvider locale="de" translations={translations}>
|
||||
<Player />
|
||||
</I18nProvider>;
|
||||
```
|
||||
|
||||
</FrameworkCase>
|
||||
|
||||
Only supplied keys override lower layers. See <DocsLink slug="concepts/i18n">Internationalization</DocsLink> for merge priority.
|
||||
|
||||
## Related
|
||||
|
||||
@@ -4,16 +4,34 @@ description: Typed function that resolves English translation phrases to localiz
|
||||
---
|
||||
|
||||
import DocsLink from '@/components/docs/DocsLink.astro';
|
||||
import FrameworkCase from '@/components/docs/FrameworkCase.astro';
|
||||
|
||||
`Translator` is the callable returned by <DocsLink slug="reference/create-translator">`createTranslator`</DocsLink> and <DocsLink slug="reference/use-translator">`useTranslator`</DocsLink>. It turns current English phrases from core controls into localized copy and interpolates `{placeholder}` tokens when params are required.
|
||||
`Translator` is the callable returned by <DocsLink slug="reference/create-translator">`createTranslator`</DocsLink>. It turns current English phrases from core controls into localized copy and interpolates `{placeholder}` tokens when params are required.
|
||||
|
||||
<FrameworkCase frameworks={["react"]}>
|
||||
|
||||
`useTranslator` also returns a `Translator` from the nearest `I18nProvider`.
|
||||
|
||||
</FrameworkCase>
|
||||
|
||||
## Import
|
||||
|
||||
<FrameworkCase frameworks={["html"]}>
|
||||
|
||||
```ts
|
||||
import type { Translator } from '@videojs/html/i18n';
|
||||
// or @videojs/react/i18n
|
||||
```
|
||||
|
||||
</FrameworkCase>
|
||||
|
||||
<FrameworkCase frameworks={["react"]}>
|
||||
|
||||
```ts
|
||||
import type { Translator } from '@videojs/react/i18n';
|
||||
```
|
||||
|
||||
</FrameworkCase>
|
||||
|
||||
## Definition
|
||||
|
||||
```ts
|
||||
@@ -30,14 +48,30 @@ Missing phrases in the active map resolve to the source English (`'Play'`) so pa
|
||||
|
||||
## Create manually
|
||||
|
||||
<FrameworkCase frameworks={["html"]}>
|
||||
|
||||
```ts
|
||||
import { createTranslator, getI18nTranslations } from '@videojs/html/i18n';
|
||||
// or @videojs/react/i18n
|
||||
|
||||
const t = createTranslator(getI18nTranslations('pt-BR'), 'pt-BR');
|
||||
t('Pause'); // localized or English fallback
|
||||
t('Pause');
|
||||
```
|
||||
|
||||
</FrameworkCase>
|
||||
|
||||
<FrameworkCase frameworks={["react"]}>
|
||||
|
||||
```ts
|
||||
import { createTranslator, getI18nTranslations } from '@videojs/react/i18n';
|
||||
|
||||
const t = createTranslator(getI18nTranslations('pt-BR'), 'pt-BR');
|
||||
t('Pause');
|
||||
```
|
||||
|
||||
</FrameworkCase>
|
||||
|
||||
<FrameworkCase frameworks={["react"]}>
|
||||
|
||||
## React hook
|
||||
|
||||
```tsx
|
||||
@@ -49,6 +83,8 @@ function Label() {
|
||||
}
|
||||
```
|
||||
|
||||
</FrameworkCase>
|
||||
|
||||
Control components resolve phrases from core `getLabel()` through their framework adapters. You rarely call `t()` directly unless building custom UI.
|
||||
|
||||
## Related
|
||||
@@ -56,3 +92,4 @@ Control components resolve phrases from core `getLabel()` through their framewor
|
||||
- <DocsLink slug="reference/create-translator">`createTranslator`</DocsLink>
|
||||
- <DocsLink slug="reference/use-translator">`useTranslator`</DocsLink>
|
||||
- <DocsLink slug="reference/translation-params">`TranslationParams`</DocsLink>
|
||||
- <DocsLink slug="reference/translation-phrases">Translation phrases</DocsLink>
|
||||
|
||||
@@ -18,7 +18,7 @@ import { useTranslator } from '@videojs/react/i18n';
|
||||
|
||||
function PlayLabel() {
|
||||
const t = useTranslator();
|
||||
return <span>{t('play')}</span>;
|
||||
return <span>{t('Play')}</span>;
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
@@ -17,11 +17,6 @@ export const sidebar: Sidebar = [
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
sidebarLabel: 'Contributing',
|
||||
devOnly: true,
|
||||
contents: [{ slug: 'how-to/i18n-add-built-in-locale', sidebarLabel: 'Add a built-in locale' }],
|
||||
},
|
||||
{
|
||||
sidebarLabel: 'Getting started',
|
||||
// May change when we revisit this section's boundary with Concepts (#1105)
|
||||
@@ -198,11 +193,11 @@ export const sidebar: Sidebar = [
|
||||
{ slug: 'reference/has-registered-locale', sidebarLabel: 'hasRegisteredLocale' },
|
||||
{ slug: 'reference/on-i18n-registry-change', sidebarLabel: 'onI18nRegistryChange' },
|
||||
{ slug: 'reference/create-translator', sidebarLabel: 'createTranslator' },
|
||||
{ slug: 'reference/translation-phrases', sidebarLabel: 'Translation phrases' },
|
||||
{
|
||||
sidebarLabel: 'Types',
|
||||
defaultOpen: false,
|
||||
contents: [
|
||||
{ slug: 'reference/built-in-locale', sidebarLabel: 'BuiltInLocale' },
|
||||
{ slug: 'reference/locale', sidebarLabel: 'Locale' },
|
||||
{ slug: 'reference/translation-params', sidebarLabel: 'TranslationParams' },
|
||||
{ slug: 'reference/translations', sidebarLabel: 'Translations' },
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
.astro-code {
|
||||
font-family: var(--font-mono), monospace;
|
||||
font-variant-ligatures: none;
|
||||
color: var(--color-manila-light);
|
||||
}
|
||||
|
||||
/* reinforcing shared.codeBlock */
|
||||
|
||||
@@ -6,7 +6,7 @@ import type { ShikiTransformer } from 'shiki';
|
||||
*
|
||||
* Shiki should only highlight the text; the code container's background and
|
||||
* scrolling are owned by `CodeFrame` and the `.astro-code` rules. Token colors
|
||||
* live on the inner spans, so removing the pre's style leaves them untouched.
|
||||
* live on the inner spans, while `.astro-code` supplies the plaintext color.
|
||||
*
|
||||
* Astro adds its built-in `pre` transformer before user transformers, so this
|
||||
* one runs last and sees the fully-assembled style to remove.
|
||||
|
||||
Reference in New Issue
Block a user