Override translations
Patch individual i18n strings without replacing an entire locale pack
registerI18n merges. Each call adds or replaces translations for that locale tag without wiping prior registrations. Use this to tweak shipped packs or A/B test copy.
Read Internationalization for the translation model and merge order, and Translation keys for the supported keys.
Override after a built-in pack
import { registerI18n } from '@videojs/html/i18n';
import '@videojs/html/i18n/locales/es/register';
registerI18n('es', { buttons: { play: 'Comenzar' } }); // only `buttons.play` changesimport { registerI18n } from '@videojs/react/i18n';
import '@videojs/react/i18n/locales/es/register';
registerI18n('es', { buttons: { play: 'Comenzar' } }); // only `buttons.play` changesLater registrations win for the same key. The rest of the es pack stays intact.
React provider overrides
Pass translations on I18nProvider to scope overrides to one subtree. This layer sits above registry and lazy packs:
import { I18nProvider } from '@videojs/react/i18n';
import { Provider, VideoSkin, Video } from '@videojs/react/video';
<Provider>
<I18nProvider locale="es" translations={{ buttons: { play: 'Comenzar' } }}>
<VideoSkin>
<Video src="..." playsInline />
</VideoSkin>
</I18nProvider>
</Provider>Nested providers inherit the parent locale when you only pass translations:
<I18nProvider locale="de">
<I18nProvider translations={{ buttons: { play: 'Override' } }}>
{/* locale stays `de`; only `buttons.play` differs */}
</I18nProvider>
</I18nProvider>HTML translated text
Use <media-text> for static copy outside buttons:
<media-i18n lang="es">
<media-text token="buttons.play">Play</media-text>
</media-i18n>The token is the lookup key and the text content is the English fallback. Override buttons.play in the registry or set lang on the provider to a locale where you patched it.
Override component text
Translation overrides change the built-in accessible labels, tooltips, and default visible text that use the same key. Set a component’s text content or children when you only need to replace its visible content.
Set text content to replace a component’s default visible text:
<media-live-button>On air</media-live-button>Use <media-text> when authored content should still follow the active locale:
<media-live-button>
<media-text token="live.badge">On air</media-text>
</media-live-button>For content that changes with component state, add one <media-text> per state and show or hide them with the same state attributes used for icons:
<media-play-button>
<media-text token="buttons.play" class="play-text">Play video</media-text>
<media-text token="buttons.pause" class="pause-text">Pause video</media-text>
<media-text token="buttons.replay" class="replay-text">Watch again</media-text>
</media-play-button>.play-text,
.pause-text,
.replay-text { display: none; }
media-play-button[data-paused]:not([data-ended]) .play-text { display: inline; }
media-play-button:not([data-paused]) .pause-text { display: inline; }
media-play-button[data-ended] .replay-text { display: inline; }This is the same state-attribute pattern used to switch icons. The token translates each fallback for the active locale.
Pass children to replace a component’s default visible text:
import { LiveButton } from '@videojs/react';
<LiveButton>On air</LiveButton>Authored React children are literal. Use useTranslator when custom children also need localization, or use a translation override when the same copy should apply to the component’s built-in text surfaces.
For content that changes with component state, switch <span> elements with the component’s state attributes:
import { PlayButton } from '@videojs/react';
<PlayButton className="play-button">
<span className="play-text">Play video</span>
<span className="pause-text">Pause video</span>
<span className="replay-text">Watch again</span>
</PlayButton>.play-text,
.pause-text,
.replay-text { display: none; }
.play-button[data-paused]:not([data-ended]) .play-text { display: inline; }
.play-button:not([data-paused]) .pause-text { display: inline; }
.play-button[data-ended] .replay-text { display: inline; }The component still derives its accessible name from media state unless you also set its label API. Keep custom visible text consistent with that name.
Parametric translations
Keep required placeholders when overriding:
// ✅
registerI18n('es', { seek: { forward: 'Adelantar {seconds} segundos' } });
// ❌ The interpolated value is lost
registerI18n('es', { seek: { forward: 'Adelantar' } });What’s next?
- Switch locale dynamically
getI18nTranslations: Inspect the merged map