Skip to content

docs(design): i18n#1122

Open
sampotts wants to merge 1 commit into
mainfrom
docs/i18n
Open

docs(design): i18n#1122
sampotts wants to merge 1 commit into
mainfrom
docs/i18n

Conversation

@sampotts
Copy link
Copy Markdown
Collaborator

@sampotts sampotts commented Mar 25, 2026

Ref: #222

Summary

Add a design document for the i18n (internationalization) system, capturing the architecture decisions and rationale for how Video.js 10 will handle localization across its monorepo packages.

Closes #1381

Changes

  • Architecture overview covering the i18n system design and package integration points
  • Decision log documenting tradeoffs and the reasoning behind chosen approaches
  • Index page tying the docs together

Testing

Documentation only — no code changes.


Note

Low Risk
Low risk documentation-only addition plus a minor .gitignore update; no runtime behavior or APIs are changed in this PR.

Overview
Adds a comprehensive draft design document (internal/design/i18n.md) specifying the proposed Video.js 10 internationalization architecture and APIs (registry-based translation packs, HTML/React provider patterns, locale fallback rules, and CDN-friendly locale modules).

Updates .gitignore to also ignore pnpm’s local store directory (.pnpm-store/).

Reviewed by Cursor Bugbot for commit fc2ca7e. Bugbot is set up for automated code reviews on this repo. Configure here.

@vercel
Copy link
Copy Markdown

vercel Bot commented Mar 25, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
v10-sandbox Ready Ready Preview, Comment Apr 20, 2026 6:16am

Request Review

@netlify
Copy link
Copy Markdown

netlify Bot commented Mar 25, 2026

Deploy Preview for vjs10-site ready!

Name Link
🔨 Latest commit fc2ca7e
🔍 Latest deploy log https://app.netlify.com/projects/vjs10-site/deploys/69e5c4aca46a5d0008476ef6
😎 Deploy Preview https://deploy-preview-1122--vjs10-site.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Mar 25, 2026

📦 Bundle Size Report

🎨 @videojs/html — no changes
Presets (7)
Entry Size
/video (default) 28.45 kB
/video (default + hls) 160.62 kB
/video (minimal) 25.98 kB
/video (minimal + hls) 158.15 kB
/audio (default) 26.36 kB
/audio (minimal) 23.95 kB
/background 4.15 kB
Media (8)
Entry Size
/media/background-video 1.04 kB
/media/container 1.73 kB
/media/dash-video 236.43 kB
/media/hls-video 133.51 kB
/media/mux-audio 159.60 kB
/media/mux-video 159.41 kB
/media/native-hls-video 3.50 kB
/media/simple-hls-video 15.78 kB
Players (3)
Entry Size
/video/player 6.98 kB
/audio/player 5.06 kB
/background/player 3.86 kB
Skins (17)
Entry Type Size
/video/minimal-skin.css css 3.50 kB
/video/skin.css css 3.52 kB
/video/minimal-skin js 25.95 kB
/video/minimal-skin.tailwind js 26.17 kB
/video/skin js 28.50 kB
/video/skin.tailwind js 28.56 kB
/audio/minimal-skin.css css 2.53 kB
/audio/skin.css css 2.50 kB
/audio/minimal-skin js 23.95 kB
/audio/minimal-skin.tailwind js 24.13 kB
/audio/skin js 26.35 kB
/audio/skin.tailwind js 26.51 kB
/background/skin.css css 117 B
/background/skin js 1.14 kB
/base.css css 157 B
/shared.css css 88 B
/skin-element js 1.35 kB
UI Components (25)
Entry Size
/ui/alert-dialog 981 B
/ui/alert-dialog-close 429 B
/ui/alert-dialog-description 375 B
/ui/alert-dialog-title 353 B
/ui/buffering-indicator 2.24 kB
/ui/captions-button 2.55 kB
/ui/cast-button 2.49 kB
/ui/compounds 3.89 kB
/ui/controls 2.19 kB
/ui/error-dialog 2.90 kB
/ui/fullscreen-button 2.54 kB
/ui/hotkey 2.53 kB
/ui/mute-button 2.51 kB
/ui/pip-button 2.52 kB
/ui/play-button 2.55 kB
/ui/playback-rate-button 2.54 kB
/ui/popover 1.77 kB
/ui/poster 2.05 kB
/ui/seek-button 2.54 kB
/ui/slider 1.44 kB
/ui/thumbnail 2.59 kB
/ui/time 2.41 kB
/ui/time-slider 3.84 kB
/ui/tooltip 1.99 kB
/ui/volume-slider 3.22 kB

Sizes are marginal over the root entry point.

⚛️ @videojs/react — no changes
Presets (7)
Entry Size
/video (default) 23.28 kB
/video (default + hls) 154.28 kB
/video (minimal) 20.90 kB
/video (minimal + hls) 151.97 kB
/audio (default) 18.85 kB
/audio (minimal) 17.38 kB
/background 755 B
Media (7)
Entry Size
/media/background-video 575 B
/media/dash-video 234.89 kB
/media/hls-video 132.03 kB
/media/mux-audio 158.09 kB
/media/mux-video 158.16 kB
/media/native-hls-video 2.06 kB
/media/simple-hls-video 14.42 kB
Skins (14)
Entry Type Size
/video/minimal-skin.css css 3.43 kB
/video/skin.css css 3.45 kB
/video/minimal-skin js 20.80 kB
/video/minimal-skin.tailwind js 24.29 kB
/video/skin js 23.17 kB
/video/skin.tailwind js 24.38 kB
/audio/minimal-skin.css css 2.43 kB
/audio/skin.css css 2.39 kB
/audio/minimal-skin js 17.30 kB
/audio/minimal-skin.tailwind js 19.79 kB
/audio/skin js 18.77 kB
/audio/skin.tailwind js 19.81 kB
/background/skin.css css 90 B
/background/skin js 272 B
UI Components (20)
Entry Size
/ui/alert-dialog 1.13 kB
/ui/buffering-indicator 1.28 kB
/ui/captions-button 1.94 kB
/ui/cast-button 1.96 kB
/ui/controls 1.33 kB
/ui/error-dialog 1.77 kB
/ui/fullscreen-button 1.94 kB
/ui/mute-button 1.96 kB
/ui/pip-button 1.94 kB
/ui/play-button 1.92 kB
/ui/playback-rate-button 1.97 kB
/ui/popover 1.89 kB
/ui/poster 1.21 kB
/ui/seek-button 1.96 kB
/ui/slider 2.63 kB
/ui/thumbnail 1.54 kB
/ui/time 2.06 kB
/ui/time-slider 2.19 kB
/ui/tooltip 2.28 kB
/ui/volume-slider 2.26 kB

Sizes are marginal over the root entry point.

🧩 @videojs/core — no changes
Entries (9)
Entry Size
. 4.89 kB
/dom 11.62 kB
/dom/media/castable 4.05 kB
/dom/media/custom-media-element 1.90 kB
/dom/media/dash 234.24 kB
/dom/media/hls 131.37 kB
/dom/media/mux 157.51 kB
/dom/media/native-hls 1.32 kB
/dom/media/simple-hls 13.73 kB
🏷️ @videojs/element — no changes
Entries (2)
Entry Size
. 999 B
/context 943 B
📦 @videojs/store — no changes
Entries (3)
Entry Size
. 1.39 kB
/html 695 B
/react 360 B
🔧 @videojs/utils — no changes
Entries (10)
Entry Size
/array 104 B
/dom 1.92 kB
/events 319 B
/function 327 B
/object 275 B
/predicate 265 B
/string 148 B
/style 190 B
/time 478 B
/number 158 B
📦 @videojs/spf — no changes
Entries (3)
Entry Size
. 40 B
/dom 13.30 kB
/playback-engine 13.17 kB

ℹ️ How to interpret

All sizes are standalone totals (minified + brotli).

Icon Meaning
No change
🔺 Increased ≤ 10%
🔴 Increased > 10%
🔽 Decreased
🆕 New (no baseline)

Run pnpm size locally to check current sizes.

@sampotts sampotts marked this pull request as draft March 25, 2026 09:22
@sampotts sampotts requested a review from mihar-22 March 25, 2026 20:45
@sampotts sampotts marked this pull request as ready for review March 25, 2026 20:46
Comment thread internal/design/i18n/index.md Outdated
Copy link
Copy Markdown
Collaborator

@cjpillsbury cjpillsbury left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Although I threw out a few "blocking" comments, I trust the rest of the team to address/discuss sufficiently and I will be out for a long weekend and don't want to slow forward progress, so setting this review as "Comment" only.

Comment thread internal/design/i18n/index.md Outdated
Comment thread internal/design/i18n/index.md Outdated
Comment thread internal/design/i18n/index.md Outdated
Comment thread internal/design/i18n/decisions.md Outdated
Comment thread internal/design/i18n/decisions.md Outdated
Comment thread internal/design/i18n/decisions.md Outdated
Comment thread internal/design/i18n/decisions.md Outdated
Comment thread internal/design/i18n/decisions.md Outdated
Comment thread internal/design/i18n/decisions.md Outdated
Comment thread internal/design/i18n/decisions.md Outdated
Comment thread internal/design/i18n/architecture.md Outdated
Comment thread internal/design/i18n/decisions.md Outdated
Comment thread internal/design/i18n/architecture.md Outdated
Comment thread internal/design/i18n/architecture.md Outdated
Comment thread internal/design/i18n/decisions.md Outdated
@github-actions github-actions Bot mentioned this pull request Apr 3, 2026
10 tasks
@sampotts sampotts changed the title docs: add i18n design doc docs(design): i18n Apr 13, 2026
@mihar-22 mihar-22 requested review from cjpillsbury and luwes April 13, 2026 07:04
Comment thread internal/design/i18n.md
Comment thread internal/design/i18n.md Outdated
Copy link
Copy Markdown
Collaborator

@cjpillsbury cjpillsbury left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Only one documentation-centric callout. Otherwise I feel like this addresses all of my major concerns. Looking good.

Comment thread internal/design/i18n.md Outdated
Comment thread internal/design/i18n.md
Comment thread internal/design/i18n.md
Comment thread internal/design/i18n.md Outdated
Comment thread internal/design/i18n.md Outdated
mihar-22
mihar-22 previously approved these changes Apr 14, 2026
Copy link
Copy Markdown
Member

@mihar-22 mihar-22 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Awesome 😎 I've left a bunch of comments but overall looking really good. In large I was just pressing on where this should live and stronger types.

I might've missed it but I didn't catch how this will all tie into updating primitive component language (say label on a play button). I can imagine few obvious ways off the top of my head so not concerned.

Comment thread internal/design/i18n.md Outdated
Comment thread internal/design/i18n.md Outdated
Comment thread internal/design/i18n.md Outdated
Comment thread internal/design/i18n.md Outdated
Comment thread internal/design/i18n.md Outdated
Comment thread internal/design/i18n.md Outdated
Comment thread internal/design/i18n.md Outdated
Comment thread internal/design/i18n.md Outdated
Comment thread internal/design/i18n.md Outdated
Comment thread internal/design/i18n.md Outdated
@sampotts
Copy link
Copy Markdown
Collaborator Author

I've created tickets based on the current state of the document but I can incorporate any further feedback as required.

Comment thread internal/design/i18n.md
import es from '@videojs/html/i18n/locales/es';

// React
import { registerI18n } from '@videojs/react';
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nitpick: import path inconsistencies between react vs. html (assuming a typo)

Comment thread internal/design/i18n.md
import es from '@videojs/react/i18n/locales/es';

<Provider>
<I18nProvider locale="es" translations={es}>
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

question(non-blocking): Is there a reason for the lang vs. locale discrepancy?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As per our discussions, the lang attribute makes more sense in HTML but in the React world, locale seems to be more used. I'm happy to make it lang to be consistent though if you'd prefer? I don't feel super strongly, Claude just suggested it was more idiomatic for React devs.

Comment thread internal/design/i18n.md

```ts
// @videojs/core/i18n/registry.ts
const registry = new Map<string, Partial<Translations>>();
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

suggestion(non-blocking): If we're going to have stateful/mutative modules (roughly equivalent to a "capital S Singleton"), let's make sure minimally we can easily remove registered languages for testing?

Comment thread internal/design/i18n.md
if (!locale) { setBuiltIn({}); return; }
const tags = [...new Set([locale, locale.split('-')[0]])];
const load = (i = 0): Promise<void> =>
import(`@videojs/core/i18n/locales/${tags[i]}`)
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thought(non-blocking): We may need to do some validation of this strategy in real world app build setups, but I don't see any problem starting with this hope/dream. Let's just make sure we do enough smoke testing of this that we don't think it will break folks doing normal crud with normal frameworks/build tools in the wild.

Comment thread internal/design/i18n.md
/** Resolve effective locale: explicit lang attribute → nearest ancestor[lang] → documentElement.lang → undefined. */
get #effectiveLocale(): Locale | undefined {
if (this.lang) return this.lang;
const ancestor = this.parentElement?.closest('[lang]');
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thought(non-blocking): Can't remember if we need to account for shadow dom boundaries with this, but we have prior art for that kinda stuff, so we can always update accordingly if/when needed.

Copy link
Copy Markdown
Collaborator

@cjpillsbury cjpillsbury left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This all looks great. Some nb callouts, but I'm comfortable with moving forward here. One high level callout, re: implementation - we may be able to pull out some of this functionality on the react and html side into shareable code (e.g. the MutationObserver stuff). I don't think that needs to be updated in the RFC, but food for thought on maintainability and/or bundle size considerations (though, for the later, it's unlikely there will be a mix and match of html + react usages in real world examples in the wild).

@ronald-urbina
Copy link
Copy Markdown
Collaborator

I left this issue of elements that might be related to this discussion.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Design: Internationalization

7 participants