Skip to main content

Internationalization (i18n)

note

Available from @admmedia/eveplayer 1.1.0.

Every label the player shows is English by default: control bar tooltips ("Play", "Mute", "Fullscreen"), the settings menu ("Quality", "Playback speed"), the PiP window. Each one is keyed by its English text, and you can change it in two ways:

  • register a language, and every player on the page shows it;
  • override single labels on one player, whatever the language.

Use a ready-made language​

The package ships one dictionary per language in its lang/ folder (53 of them, one per language Video.js is translated into). Each dictionary covers the labels the player inherits from Video.js and the player's own. Register the ones you need once, before creating any player:

import { EvePlayer } from '@admmedia/eveplayer';
import it from '@admmedia/eveplayer/lang/it.json';

EvePlayer.addLanguage('it', it);

new EvePlayer(container, { language: 'it' });

Leave language out and the player follows the browser's language. A regional code falls back to its base language (it-CH uses it), and any label the dictionary lacks stays in English.

info

The player's own labels (settings menu, PiP window) are translated in Italian so far. In the other languages, the Video.js labels are translated and the player's own stay English until someone contributes them: see Contribute a translation.

Import only the languages you use: each one is a separate file, so the others never reach your bundle.

Pick the language at runtime​

To choose the visitor's language at runtime, list the ones you support and load the right file on demand:

const dictionaries = {
it: () => import('@admmedia/eveplayer/lang/it.json'),
de: () => import('@admmedia/eveplayer/lang/de.json'),
fr: () => import('@admmedia/eveplayer/lang/fr.json'),
};

const code = navigator.language.split('-')[0];
const load = dictionaries[code as keyof typeof dictionaries];
if (load) EvePlayer.addLanguage(code, (await load()).default);
// Any other language: the labels stay in English.

new EvePlayer(container, { language: code });

Listing every language does not mean downloading every language. Your bundler (Vite, webpack, …) turns each () => import(...) into its own small file, kept out of your main bundle and fetched only when that function runs. With eight languages listed you ship eight small files, and each visitor downloads just the one for their language.

Spell each path out in full, as above: the bundler only knows which files to prepare when it can read the complete path in your code. Two alternatives, if you would rather not keep a list:

  • A template path, such as import(`@admmedia/eveplayer/lang/${code}.json`). Webpack accepts it, but prepares a file for every one of the 53 languages (visitors still download only one). Vite does not support a variable path into a package, so this is not portable.
  • Fetching from a CDN, outside your bundler: fetch(`https://cdn.jsdelivr.net/npm/@admmedia/eveplayer@1.1.0/dist/lang/${code}.json`), then addLanguage(code, await response.json()). Nothing to list and nothing in your build, but your page then depends on the CDN, and the version in the URL has to follow the version you install.

For a known set of languages, the list is the safest choice: it works with every bundler, and a typo in a path fails your build instead of your visitors' page.

note

The language is fixed when the player is created. Register the dictionary first, then create the player with that language. If the visitor switches language while a player already exists, create a new one (in React, change the component's key). To change only some labels on a running player, use setLabels() (see In React).

Change single labels​

Pass labels for one player. The keys are the English labels, and the values win over any registered language:

const player = new EvePlayer(container, {
labels: { Settings: 'Options', Play: 'Start' },
});

setLabels() changes them later and updates the labels already on screen. It replaces the whole set, so pass every override you want to keep (or {} to drop them all):

player.setLabels({ Settings: 'Preferences' });

To change a label for every player instead, register a partial dictionary: addLanguage() merges into the one already registered for that language.

EvePlayer.addLanguage('it', { Settings: 'Opzioni' });

When several sources define the same label, the player uses, in order:

  1. a dedicated option, such as pipPlaceholderText;
  2. the player's labels;
  3. the dictionary of the active language (then of its base language);
  4. the English text.

Labels with a value​

A few labels contain a placeholder that the player fills in. Automatic ({1}) becomes Automatic (1080p), for instance. Keep {1} in your text:

EvePlayer.addLanguage('it', { 'Automatic ({1})': 'Automatica ({1})' });

Which keys exist​

lang/en.json in the package lists every label the player itself shows; the labels inherited from Video.js are the keys of its English dictionary. Any of them works in labels and in addLanguage().

In React​

options is read once, when the player is created, so labels passed there apply from the start. To change them on a player that is already mounted, call setLabels() on the instance:

import { useEffect, useRef } from 'react';
import { EvePlayer, type EvePlayerCore } from '@admmedia/eveplayer-react';

const playerRef = useRef<EvePlayerCore | null>(null);

useEffect(() => {
playerRef.current?.setLabels(labels);
}, [labels]);

<EvePlayer ref={playerRef} options={{ labels }} source={source} />;

Contribute a translation​

Missing your language, or want to improve one? Translations are welcome: the contributing guide explains how to add one.