HTML Subtitles
Your video speaks one language, but your visitors speak many. Subtitles are the bridge: the speech, translated and shown as text, in time with the video.
With HTML, you can offer subtitles in as many languages as you like. Each language is one small text file, and the viewer picks the one they want from the player's menu. This lesson shows how to set it up, and how to make translations that are good to read.
What You Will Learn
- How subtitles differ from captions
- Adding several languages with
<track kind="subtitles"> - Language codes, and labels in each language's own writing
- Translation tips for natural, readable subtitles
- Right-to-left, Chinese, Japanese, and other scripts
- Choosing a language with JavaScript
- Common mistakes
Subtitles or Captions?
| Subtitles | Captions | |
|---|---|---|
| For | Viewers who can hear, but do not understand the language | Viewers who cannot hear the audio |
| Language | Translated into the viewer's language | The same language as the audio |
| Includes sounds and speakers | Usually not | Yes |
| HTML | kind="subtitles" | kind="captions" |
A viewer who is deaf and reads Spanish needs Spanish captions, which are both: Spanish text, with sounds and speakers. For that, use kind="captions" with srclang="es". Choose the kind by what the viewer needs, not just by language. See Captions.
Adding Subtitles in Several Languages
- HTML Code
- Browser Output
<video controls width="640" height="360" src="lesson.mp4" crossorigin="anonymous">
<track kind="captions" src="lesson.en.vtt" srclang="en" label="English" default>
<track kind="subtitles" src="lesson.es.vtt" srclang="es" label="Español">
<track kind="subtitles" src="lesson.hi.vtt" srclang="hi" label="हिन्दी">
<track kind="subtitles" src="lesson.ar.vtt" srclang="ar" label="العربية">
</video>
WEBVTT
00:00.000 --> 00:02.500
Bienvenidos de nuevo. Hoy vamos a
crear un formulario de registro.
00:02.500 --> 00:05.000
Primero, abre el editor.
Preparing the sound and four subtitle files…
Four real track elements, one per language. Audio has no built-in subtitle display, so the page reads the active cue with cuechange and shows it in the box. On a video, the browser draws it for you.
The demo has four real <track> elements. Change the language while the sound plays, and the text changes at once, from the same moment. Look at the table to see what the browser read from your attributes.
On a <video>, the browser draws the chosen subtitles on top of the picture, and lists every track in the player's captions menu. You write only the files and the <track> lines.
Rules for the Attributes
| Attribute | For subtitles |
|---|---|
kind | subtitles (also the default if you leave kind out) |
src | One .vtt file per language |
srclang | Required. The language code of the text in the file |
label | The menu name, written in that language ("Español", not "Spanish") |
default | Optional. Turns a track on by default. Use sparingly |
Language Codes
srclang takes a BCP 47 language tag, the same kind of code as the lang attribute:
| Tag | Language | Notes |
|---|---|---|
en | English | en-GB, en-US for regional spelling |
es | Spanish | es-MX, es-ES for regional forms |
pt-BR | Portuguese (Brazil) | Differs from pt-PT in words and spelling |
hi | Hindi | |
ar | Arabic | Right to left |
he | Hebrew | Right to left |
ja | Japanese | |
zh-Hans, zh-Hant | Chinese, Simplified and Traditional | Two different writing systems |
Use the short tag (es) unless you really have a regional version.
Try It: Build the Track List
Pick the languages you plan to offer, and see the HTML and the things to watch out for.
- HTML Code
- Browser Output
<track kind="subtitles" src="lesson.es.vtt" srclang="es" label="Español">
<track kind="subtitles" src="lesson.hi.vtt" srclang="hi" label="हिन्दी">
Labels in Their Own Language
A visitor who reads only Japanese must be able to find "日本語" in a menu, even on an English page. If you write "Japanese", they may not recognise it.
<!-- Good: each language names itself -->
<track kind="subtitles" srclang="ja" label="日本語" src="lesson.ja.vtt">
<!-- Weaker: only readable if you know English -->
<track kind="subtitles" srclang="ja" label="Japanese" src="lesson.ja.vtt">
A good compromise for some sites is to put the language in both forms: "日本語 (Japanese)".
Writing Good Translations
Translating subtitles is not the same as translating a book. The viewer is listening and reading at the same time.
- Translate meaning, not words. A word-for-word version often sounds strange, or is wrong.
- Handle idioms and jokes with an equivalent in the target language, or a clear paraphrase.
- Keep it short. Many languages need more words than English. Make the text shorter and simpler so the viewer can read it in time.
- Keep the timing. Each cue should still match what is being said.
- Follow the same limits as for captions: about two lines, short lines, and a comfortable reading speed. Some languages need fewer characters per line.
- Use the language's own punctuation and number style. Quotation marks, decimals, dates, and units differ.
- Be consistent with names and terms, and keep a short glossary for your project.
- Keep names, product names, and code unchanged where translating them would cause confusion.
- Keep the tone (formal or friendly) that suits the audience. Some languages have formal and informal forms of "you".
- Have a native speaker review it. Machine translation is a draft, not a finished product.
Mixed Languages in One Cue
If a subtitle contains words from another language, mark them with the WebVTT language tag:
00:08.000 --> 00:10.000
La palabra <lang en>"hello"</lang> se usa en todo el mundo.
The <lang> tag lets assistive technology and fonts treat that part correctly.
Right-to-Left and Other Scripts
- Arabic, Hebrew, Persian, and Urdu run right to left. WebVTT supports them, but test the cues in your target browsers. Numbers, English names, and punctuation sometimes appear in a surprising order, and you may need to adjust the text.
- Chinese and Japanese do not use spaces between words, so a line break in the wrong place can change the meaning or read awkwardly. Have a native reader check where lines break.
- Indian scripts (Hindi, Tamil, Bengali) use joined letters and need a font that supports them. If characters look broken, the problem is usually the font or the file encoding.
- Save every
.vttfile as UTF-8. This is the most common cause of garbled text in subtitles. - Use a font that covers the script when you style captions with
::cue. The default system fonts are usually safe.
video::cue {
font-family: system-ui, "Noto Sans", sans-serif;
}
Choosing a Language with JavaScript
The player menu lets viewers choose. Sometimes you want your own control, or you want to pick a sensible default for the visitor.
const video = document.querySelector("video");
function showSubtitles(language) {
for (const track of video.textTracks) {
if (track.kind === "subtitles" || track.kind === "captions") {
track.mode = track.language === language ? "showing" : "disabled";
}
}
}
// A visitor's preferred languages, most wanted first
const wanted = navigator.languages.map((tag) => tag.split("-")[0]);
const offered = Array.from(video.textTracks).map((track) => track.language);
const match = wanted.find((code) => offered.includes(code));
if (match) showSubtitles(match);
Be careful with automatic choices:
- Do not turn subtitles on for a viewer who understands the audio. Show them only when the viewer's language differs from the audio's.
- Let the visitor override it, and remember their choice (a setting in
localStoragewrapped intry/catchis fine, as storage can be unavailable). - The
defaultattribute is a suggestion. Browsers may turn a subtitle track on by default only when its language matches the visitor's language settings, so do not depend on it to force a language.
Accessibility at a Glance
- Provide captions in the audio language for people who cannot hear. Subtitles alone are not enough.
- Set
srclangcorrectly, and write thelabelin the language itself. - Keep timing and reading speed comfortable in every language.
- Keep contrast high, and respect the viewer's own subtitle settings.
- Make the language menu keyboard-accessible. Native players already are. A custom menu needs real controls and labels.
- Mark mixed-language text with
lang, or the WebVTT<lang>tag. - Do not change the meaning during translation. Review sensitive content with an expert.
Security and Privacy Notes
- Translation files are public, and are part of your site's content. Do not leave private notes or internal comments in them.
- Treat translated cue text as plain text in your own scripts. Use
textContent, neverinnerHTML. - Only load subtitle files from sources you trust. A third-party file is words you did not write, appearing in front of your visitors.
- Be careful with online translation tools. Pasting a transcript into a free service may share the content with that company. Check the terms, especially for confidential or personal material.
- Review machine translations for mistakes that could mislead, offend, or cause harm in medical, legal, and safety content.
Global Audience Notes
- Start with the languages your visitors really use. Check your analytics, support emails, and your audience. Each new language is a file to maintain.
- Keep every file in step. If you edit the video, update all the subtitle files, or the wrong words appear at the wrong time.
- Use consistent file names:
lesson.es.vtt,lesson.hi.vtt. - Think about regions, not just languages. Spanish in Mexico, Spain, and Argentina uses different words. Choose a version your audience understands.
- Check the text on small screens, where long lines in some scripts can become hard to read.
- Also offer a translated transcript where you can, for people who prefer to read at their own pace.
- Avoid wordplay and local references in your source language, or add a note for translators.
Common Mistakes to Avoid
- Using subtitles for deaf viewers, with no sounds or speaker names. Use captions.
- A missing or wrong
srclang. - Labels in only one language, so viewers cannot find their own.
- Files not saved as UTF-8, so letters appear broken.
- Word-for-word machine translation with no review.
- Timing copied unchanged into a language that needs more reading time.
- Subtitles left out of date after the video was edited.
- More than one
default, or adefaultlanguage that does not suit your visitors. - Forcing subtitles on for viewers who understand the audio.
- Ignoring right-to-left or Asian line-break problems.
- Too many languages, so none gets properly maintained.
- Not testing in the player, with the keyboard.
Practice Time
Try these in your editor, with a short video and a friend who speaks another language:
- Add two
<track kind="subtitles">elements with differentsrclangvalues. - Write each
labelin its own language. - Translate three cues, and ask a native speaker to improve them.
- Save one file with the wrong encoding, and see how it breaks. Then fix it.
- Add a right-to-left language, and test numbers and names.
- List
video.textTracksin the console, with each track'slanguageandmode. - Write a function that turns on the subtitles that match
navigator.languages. - Add a button that turns subtitles on and off.
- Add a
<lang>tag around an English word in a Spanish cue. - Bonus: compare your English captions with your translation, and list the cues where the translation is too long to read in time.
Quick Recap
Click a question to check your answer.
1. How do subtitles differ from captions?
Subtitles translate the speech for viewers who can hear. Captions are in the audio's own language and also include sounds and speaker names, for viewers who cannot hear.
2. How do you offer several languages?
Add one track element per language, each with kind="subtitles", its own .vtt file, a srclang code, and a label.
3. Why write each label in its own language?
So a viewer can recognise their own language in the menu, even if they cannot read the rest of the page.
4. What makes a good subtitle translation?
It keeps the meaning rather than the words, is short enough to read in time, handles idioms and names well, follows the language's punctuation, and is reviewed by a native speaker.
5. What is the most common cause of broken characters?
A .vtt file that is not saved as UTF-8. Also check that the font supports the script.
6. Should subtitles always be on by default?
No. Turn them on only when they help, for example when the viewer's language differs from the audio. Let the visitor choose and remember it, and do not rely on default to force a language.
Key Takeaways
- Subtitles translate speech for viewers who can hear. For viewers who cannot hear, provide captions.
- Add one
<track kind="subtitles">per language, each withsrc,srclang, and alabelwritten in its own language. - Use BCP 47 codes (
es,pt-BR,zh-Hans), and save every file as UTF-8. - Translate meaning, not words: keep it short, keep the timing, and have a native speaker check it.
- Test right-to-left and Chinese or Japanese line breaks with real readers.
- Choose languages with
textTracksandnavigator.languages, but let viewers override, and remember their choice. - Keep all files up to date, and use
textContentwhen your script shows cue text. - Start with the languages your visitors need, and add more only when you can keep them correct.
Next, bring everything together for every viewer in Accessible Media, or return to the Audio and Video overview.