How to add multiple subtitle languages to HTML5 video
TL;DR — Add multiple subtitle languages to HTML5 video by preparing separate WebVTT files with language codes, labels, and track elements.
Related tool
HTML5 Video Subtitle Converter
HTML5 video uses one track element per subtitle language. This guide shows you how to set up multilingual subtitles correctly for maximum accessibility and user experience.
Quick answer
Create one WebVTT file per language, then add one <track> element for each file. Use proper language codes (srclang) and descriptive labels so users can easily switch between languages.
Use the HTML5 Video Subtitle Converter when source subtitles need to be converted to WebVTT first.
Why multiple subtitle languages matter
Offering subtitles in multiple languages:
- Expands your audience - Viewers who don’t speak the video’s language can still understand the content
- Improves accessibility - Users can choose their preferred language
- Boosts SEO - Search engines can index subtitle content in multiple languages
- Meets compliance requirements - Many regions require multilingual captions for public content
HTML5 video makes this easy with the <track> element, which browsers support natively without requiring JavaScript libraries.
Example
Here’s a complete example with three subtitle languages:
<video controls width="640" height="360">
<source src="video.mp4" type="video/mp4" />
<track kind="subtitles" src="captions.en.vtt" srclang="en" label="English" default />
<track kind="subtitles" src="captions.es.vtt" srclang="es" label="Español" />
<track kind="subtitles" src="captions.fr.vtt" srclang="fr" label="Français" />
<track kind="subtitles" src="captions.de.vtt" srclang="de" label="Deutsch" />
<track kind="subtitles" src="captions.ja.vtt" srclang="ja" label="日本語" />
</video>
Key points:
- Each
<track>points to a separate VTT file srclanguses ISO 639-1 language codes (en, es, fr, de, ja)labelis what users see in the subtitle menu (can be in the native language)- Only one track has
default(English in this example) - The browser automatically creates a language selector in the video controls
Each VTT file should contain subtitles for one language only. Don’t mix languages in a single file.
Step-by-step workflow
1. Prepare one subtitle file per language
Start with your source subtitle files. You might have:
- Original language subtitles (e.g., English SRT)
- Translated subtitles from a translation service
- Community-contributed subtitles in various formats
Organize your files:
/subtitles/
video-1.en.srt
video-1.es.srt
video-1.fr.srt
video-1.de.srt
2. Convert each file to WebVTT
HTML5 video requires WebVTT format. If your subtitles are in SRT, ASS, or another format, convert them first.
For each language:
- Open the HTML5 Video Subtitle Converter
- Upload or paste the subtitle file
- Convert to WebVTT
- Download the
.vttfile
Batch conversion tip: If you have many files, convert them all at once and save them with consistent naming.
3. Validate each VTT file
Before adding tracks to your video, validate each VTT file to catch syntax errors.
For each VTT file:
- Open the WebVTT Validator
- Upload the VTT file
- Fix any reported errors
- Re-validate until it passes
Common validation errors:
- Missing
WEBVTTheader - Malformed timestamps
- Invalid cue settings
- Character encoding issues (must be UTF-8)
4. Use clear, consistent filenames
Good naming conventions make maintenance easier and prevent mistakes.
Recommended pattern:
video-name.language-code.vtt
Examples:
product-demo.en.vtt- Englishproduct-demo.es.vtt- Spanish (Español)product-demo.fr.vtt- French (Français)product-demo.de.vtt- German (Deutsch)product-demo.pt-BR.vtt- Brazilian Portugueseproduct-demo.zh-CN.vtt- Simplified Chinese
Why this matters:
- Easy to identify which file is which
- Prevents accidentally using the wrong language
- Makes automated deployment scripts simpler
5. Add one track element per language
Now add the <track> elements to your HTML5 video.
Basic structure:
<video controls>
<source src="your-video.mp4" type="video/mp4" />
<track kind="subtitles"
src="path/to/captions.en.vtt"
srclang="en"
label="English"
default />
<track kind="subtitles"
src="path/to/captions.es.vtt"
srclang="es"
label="Español" />
</video>
Track attributes explained:
kind- Use"subtitles"for translations,"captions"for same-language accessibilitysrc- Path to the VTT file (can be relative or absolute URL)srclang- ISO 639-1 language code (en, es, fr, de, ja, etc.)label- Display name in the subtitle menu (can be in the native language)default- Makes this track active by default (use on only one track)
6. Test the language selector
After adding all tracks, test in multiple browsers.
Testing checklist:
- Load the page with the video
- Click the CC (closed captions) button or subtitle menu
- Verify all languages appear in the menu
- Select each language and confirm subtitles display correctly
- Check that the default language loads automatically
- Test on mobile devices (iOS Safari, Android Chrome)
Browser compatibility:
- Chrome, Firefox, Safari, Edge all support multiple subtitle tracks
- Mobile browsers support track selection through native controls
- Older browsers (IE11) have limited support
7. Configure CORS if needed
If your VTT files are hosted on a different domain than your video page, you need CORS headers.
Symptom: Subtitles don’t load, console shows CORS error.
Fix: Add this header to your subtitle file server:
Access-Control-Allow-Origin: *
Or restrict to your domain:
Access-Control-Allow-Origin: https://yourdomain.com
See How to fix CORS errors for VTT subtitles for detailed instructions.
Naming tips
Use language codes consistently across all your videos.
ISO 639-1 language codes (most common)
| Language | Code | Label Example |
|---|---|---|
| English | en | English |
| Spanish | es | Español |
| French | fr | Français |
| German | de | Deutsch |
| Italian | it | Italiano |
| Portuguese | pt | Português |
| Japanese | ja | 日本語 |
| Chinese (Simplified) | zh | 中文 |
| Korean | ko | 한국어 |
| Russian | ru | Русский |
| Arabic | ar | العربية |
| Hindi | hi | हिन्दी |
Regional variants
For languages with regional differences, use extended codes:
| Language | Code | Label Example |
|---|---|---|
| US English | en-US | English (US) |
| UK English | en-GB | English (UK) |
| Brazilian Portuguese | pt-BR | Português (Brasil) |
| European Portuguese | pt-PT | Português (Portugal) |
| Simplified Chinese | zh-CN | 中文(简体) |
| Traditional Chinese | zh-TW | 中文(繁體) |
| Latin American Spanish | es-419 | Español (Latinoamérica) |
| European Spanish | es-ES | Español (España) |
Best practice: The srclang value should match the actual language of the captions, not the video filename. The browser uses this for accessibility features and language detection.
Common mistakes
Combining multiple languages in one VTT track
Wrong approach:
WEBVTT
1
00:00:01.000 --> 00:00:03.000
Hello (English) / Hola (Spanish)
2
00:00:03.000 --> 00:00:05.000
Welcome (English) / Bienvenido (Spanish)
Why this fails:
- Users can’t choose their preferred language
- Clutters the screen with duplicate text
- Breaks accessibility features
- Search engines can’t index languages separately
Correct approach: Use separate tracks so the browser can expose each language cleanly. One VTT file = one language.
Forgetting labels
Without labels:
<track kind="subtitles" src="captions.en.vtt" srclang="en" />
<track kind="subtitles" src="captions.es.vtt" srclang="es" />
Problem: The subtitle menu shows language codes (en, es) instead of readable names. Users might not know what es means.
With labels:
<track kind="subtitles" src="captions.en.vtt" srclang="en" label="English" />
<track kind="subtitles" src="captions.es.vtt" srclang="es" label="Español" />
Result: The menu shows “English” and “Español” - much clearer for users.
Pro tip: Use the native language name in the label (e.g., “Español” not “Spanish”, “Français” not “French”). This helps non-English speakers find their language faster.
Setting every track as default
Wrong:
<track kind="subtitles" src="captions.en.vtt" srclang="en" label="English" default />
<track kind="subtitles" src="captions.es.vtt" srclang="es" label="Español" default />
<track kind="subtitles" src="captions.fr.vtt" srclang="fr" label="Français" default />
Problem: Only one track can be default. Browsers handle this inconsistently - some show the first track, others show the last, some show none.
Correct:
<track kind="subtitles" src="captions.en.vtt" srclang="en" label="English" default />
<track kind="subtitles" src="captions.es.vtt" srclang="es" label="Español" />
<track kind="subtitles" src="captions.fr.vtt" srclang="fr" label="Français" />
Best practice: Mark your primary audience’s language as default, or omit default entirely to let users choose.
Using wrong language codes
Wrong:
<track srclang="spanish" label="Spanish" />
<track srclang="eng" label="English" />
Problem: Browsers expect ISO 639-1 codes (es, en), not full language names or 3-letter codes.
Correct:
<track srclang="es" label="Español" />
<track srclang="en" label="English" />
Not testing on mobile
Desktop browsers often have better subtitle controls than mobile browsers. Always test on:
- iOS Safari (iPhone/iPad)
- Android Chrome
- Mobile Firefox
Mobile-specific issues:
- Some mobile browsers hide the subtitle menu in fullscreen mode
- Touch targets for subtitle selection might be too small
- Native video controls vary by device
Mixing kind=“subtitles” and kind=“captions”
Inconsistent:
<track kind="subtitles" src="captions.en.vtt" srclang="en" label="English" />
<track kind="captions" src="captions.es.vtt" srclang="es" label="Español" />
Problem: Some browsers group these separately in the menu, confusing users.
Consistent:
<track kind="subtitles" src="captions.en.vtt" srclang="en" label="English" />
<track kind="subtitles" src="captions.es.vtt" srclang="es" label="Español" />
When to use each:
kind="subtitles"- Translations of dialoguekind="captions"- Same-language text including sound effects and speaker IDs (for accessibility)
For multilingual content, use kind="subtitles" consistently.
Advanced: Programmatic track management
For dynamic subtitle loading or user preference storage, use JavaScript:
const video = document.querySelector('video');
// Add a track programmatically
const track = document.createElement('track');
track.kind = 'subtitles';
track.label = 'Português';
track.srclang = 'pt';
track.src = 'captions.pt.vtt';
video.appendChild(track);
// Listen for track changes
video.textTracks.addEventListener('change', () => {
const activeTrack = Array.from(video.textTracks)
.find(track => track.mode === 'showing');
if (activeTrack) {
console.log('Active language:', activeTrack.language);
// Save user preference to localStorage
localStorage.setItem('preferredSubtitleLang', activeTrack.language);
}
});
// Restore user's preferred language
const preferredLang = localStorage.getItem('preferredSubtitleLang');
if (preferredLang) {
Array.from(video.textTracks).forEach(track => {
track.mode = track.language === preferredLang ? 'showing' : 'disabled';
});
}
Frequently asked questions
How many subtitle languages should I offer?
Start with your primary audience’s languages. Common combinations:
- Global audience: English, Spanish, French, German, Japanese, Chinese
- European focus: English, German, French, Italian, Spanish
- Americas focus: English, Spanish (Latin American), Portuguese (Brazilian)
Add more languages based on your analytics data showing where viewers are located.
Can I use the same VTT file for multiple videos?
Only if the timing and dialogue are identical. Usually each video needs its own subtitle files, even if the language is the same.
Do subtitle files slow down page load?
No. Browsers load subtitle files on-demand when the user selects a language or when the default track is activated. They don’t block the initial page load.
Can I auto-detect the user’s language?
Yes, with JavaScript:
const userLang = navigator.language.split('-')[0]; // e.g., 'en' from 'en-US'
const matchingTrack = Array.from(video.textTracks)
.find(track => track.language === userLang);
if (matchingTrack) {
matchingTrack.mode = 'showing';
}
What if I don’t have translations yet?
Start with one language (usually English) and add more as you get translations. You can always add new <track> elements later without changing existing ones.
Related guides
- How to convert subtitles for HTML5 video
- How to validate WebVTT files
- Why subtitles do not show in HTML5 video
Related tools
Use the HTML5 Video Subtitle Converter
Convert SRT or ASS subtitles to WebVTT for HTML5 video tracks and browser playback. No signup, no upload, and everything runs locally in the browser.
Open HTML5 converter