Skip to main content

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?​

SubtitlesCaptions
ForViewers who can hear, but do not understand the languageViewers who cannot hear the audio
LanguageTranslated into the viewer's languageThe same language as the audio
Includes sounds and speakersUsually notYes
HTMLkind="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​

index.html
<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>
lesson.es.vtt
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.

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​

AttributeFor subtitles
kindsubtitles (also the default if you leave kind out)
srcOne .vtt file per language
srclangRequired. The language code of the text in the file
labelThe menu name, written in that language ("Español", not "Spanish")
defaultOptional. 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:

TagLanguageNotes
enEnglishen-GB, en-US for regional spelling
esSpanishes-MX, es-ES for regional forms
pt-BRPortuguese (Brazil)Differs from pt-PT in words and spelling
hiHindi
arArabicRight to left
heHebrewRight to left
jaJapanese
zh-Hans, zh-HantChinese, Simplified and TraditionalTwo 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.

index.html
<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.

  1. Translate meaning, not words. A word-for-word version often sounds strange, or is wrong.
  2. Handle idioms and jokes with an equivalent in the target language, or a clear paraphrase.
  3. Keep it short. Many languages need more words than English. Make the text shorter and simpler so the viewer can read it in time.
  4. Keep the timing. Each cue should still match what is being said.
  5. Follow the same limits as for captions: about two lines, short lines, and a comfortable reading speed. Some languages need fewer characters per line.
  6. Use the language's own punctuation and number style. Quotation marks, decimals, dates, and units differ.
  7. Be consistent with names and terms, and keep a short glossary for your project.
  8. Keep names, product names, and code unchanged where translating them would cause confusion.
  9. Keep the tone (formal or friendly) that suits the audience. Some languages have formal and informal forms of "you".
  10. 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 .vtt file 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 localStorage wrapped in try/catch is fine, as storage can be unavailable).
  • The default attribute 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 srclang correctly, and write the label in 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, never innerHTML.
  • 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​

  1. Using subtitles for deaf viewers, with no sounds or speaker names. Use captions.
  2. A missing or wrong srclang.
  3. Labels in only one language, so viewers cannot find their own.
  4. Files not saved as UTF-8, so letters appear broken.
  5. Word-for-word machine translation with no review.
  6. Timing copied unchanged into a language that needs more reading time.
  7. Subtitles left out of date after the video was edited.
  8. More than one default, or a default language that does not suit your visitors.
  9. Forcing subtitles on for viewers who understand the audio.
  10. Ignoring right-to-left or Asian line-break problems.
  11. Too many languages, so none gets properly maintained.
  12. 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:

  1. Add two <track kind="subtitles"> elements with different srclang values.
  2. Write each label in its own language.
  3. Translate three cues, and ask a native speaker to improve them.
  4. Save one file with the wrong encoding, and see how it breaks. Then fix it.
  5. Add a right-to-left language, and test numbers and names.
  6. List video.textTracks in the console, with each track's language and mode.
  7. Write a function that turns on the subtitles that match navigator.languages.
  8. Add a button that turns subtitles on and off.
  9. Add a <lang> tag around an English word in a Spanish cue.
  10. 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 with src, srclang, and a label written 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 textTracks and navigator.languages, but let viewers override, and remember their choice.
  • Keep all files up to date, and use textContent when 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.