Skip to content

feat(sandbox): add i18n demos and e2e coverage#1593

Open
sampotts wants to merge 14 commits into
feat/i18n-reactfrom
feat/i18n-sandbox
Open

feat(sandbox): add i18n demos and e2e coverage#1593
sampotts wants to merge 14 commits into
feat/i18n-reactfrom
feat/i18n-sandbox

Conversation

@sampotts

@sampotts sampotts commented May 25, 2026

Copy link
Copy Markdown
Collaborator

Refs #222
Closes #1594

Summary

Adds locale switching to all sandbox presets (HTML, React, CDN) with shared helpers and e2e tests verifying translated control labels.

Changes

  • Language picker with shipped + browser-only locales; dev-mode model download logging
  • Shared sandbox i18n helpers for HTML, React, and CDN templates
  • E2e specs for HTML sandbox, CDN sandbox, and CDN bundle with locale=es
Stack info

PR 5 of 5 — stacks on React i18n PR. Final PR in the i18n stack.

Testing

pnpm -F @videojs/html build:cdn
pnpm build:sandbox
pnpm test:e2e:vite --grep i18n

Note

Medium Risk
Broad sandbox and Vite resolver changes around CDN i18n registries and template mirroring could affect local dev behavior; production player packages are largely untouched aside from a React package export re-export.

Overview
Adds locale switching across the sandbox shell and every HTML, React, and CDN preset, plus Playwright checks that Spanish (locale=es) shows Reproducir on the play control.

The shell gains a Language control in player settings (built-in packs vs Chrome Translator–only tags), keeps locale in the URL, and broadcasts locale-change to the preview iframe; CDN previews reload on locale change so chunks load cleanly.

Shared helpers load packs via @videojs/html/i18n (HTML/React) or @videojs/html/cdn/i18n and locale chunks (CDN), with optional browser translation prefetch. HTML templates wrap players in media-i18n-provider; React presets use SandboxI18nProvider. Vite plugins sync templates/src/ and force a single CDN i18n registry in dev. Setup now regenerates CDN locale loaders and overwrites differing mirrored files from templates.

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

@vercel

vercel Bot commented May 25, 2026

Copy link
Copy Markdown

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

Project Deployment Actions Updated (UTC)
v10-sandbox Ready Ready Preview, Comment Jul 3, 2026 4:15am

Request Review

Comment thread apps/sandbox/app/shell/preview.tsx Outdated
Comment thread apps/sandbox/app/shared/html/i18n.ts
Comment thread apps/sandbox/templates/cdn/index.html Outdated
Comment thread apps/e2e/tests/cdn-i18n.spec.ts Outdated
Comment thread apps/sandbox/app/shell/preview.tsx
@github-actions

github-actions Bot commented Jun 22, 2026

Copy link
Copy Markdown
Contributor

📦 Bundle Size Report

🎨 @videojs/html — no changes
Presets (7)
Entry Initial Lazy
/video (default) 51.11 kB 51.99 kB
/video (default + hls) 190.50 kB 51.99 kB
/video (minimal) 51.17 kB 51.99 kB
/video (minimal + hls) 190.63 kB 51.99 kB
/audio (default) 44.38 kB 51.99 kB
/audio (minimal) 43.38 kB 51.99 kB
/background 7.27 kB 51.99 kB
Media (10)
Entry Initial
/media/background-video 1.14 kB
/media/container 1.71 kB
/media/dash-video 214.70 kB
/media/hlsjs-video 141.51 kB
/media/mux-audio 164.02 kB
/media/mux-video 163.99 kB
/media/native-hls-video 9.09 kB
/media/simple-hls-audio-only 17.15 kB
/media/simple-hls-video 18.70 kB
/media/vimeo-video 12.32 kB
Players (5)
Entry Initial Lazy
/video/player 11.26 kB 51.99 kB
/audio/player 8.45 kB 51.99 kB
/background/player 7.01 kB 51.99 kB
/live-video/player 10.64 kB 51.99 kB
/live-audio/player 8.46 kB 51.99 kB
Skins (30)
Entry Type Initial Lazy
/video/minimal-skin.css css 5.70 kB
/video/skin.css css 5.66 kB
/video/minimal-skin js 51.12 kB 51.99 kB
/video/minimal-skin.tailwind js 51.83 kB 51.99 kB
/video/skin js 51.10 kB 51.99 kB
/video/skin.tailwind js 51.97 kB 51.99 kB
/audio/minimal-skin.css css 3.97 kB
/audio/skin.css css 3.87 kB
/audio/minimal-skin js 43.40 kB 51.99 kB
/audio/minimal-skin.tailwind js 43.94 kB 51.99 kB
/audio/skin js 44.39 kB 51.99 kB
/audio/skin.tailwind js 44.90 kB 51.99 kB
/background/skin.css css 133 B
/background/skin js 1.14 kB
/live-video/minimal-skin.css css 5.70 kB
/live-video/skin.css css 5.66 kB
/live-video/minimal-skin js 49.87 kB 51.99 kB
/live-video/minimal-skin.tailwind js 50.37 kB 51.99 kB
/live-video/skin js 49.65 kB 51.99 kB
/live-video/skin.tailwind js 50.27 kB 51.99 kB
/live-audio/minimal-skin.css css 3.97 kB
/live-audio/skin.css css 3.87 kB
/live-audio/minimal-skin js 35.74 kB 51.99 kB
/live-audio/minimal-skin.tailwind js 35.23 kB 51.99 kB
/live-audio/skin js 36.86 kB 51.99 kB
/live-audio/skin.tailwind js 36.39 kB 51.99 kB
/global.css css 183 B
/shared.css css 153 B
/tailwind.css css 161 B
/skin-element js 5.28 kB 51.99 kB
UI Components (39)
Entry Initial
/ui/airplay-button 2.55 kB
/ui/alert-dialog 2.88 kB
/ui/alert-dialog-close 2.39 kB
/ui/alert-dialog-description 2.36 kB
/ui/alert-dialog-title 2.36 kB
/ui/audio-track-radio-group 3.14 kB
/ui/buffering-indicator 2.60 kB
/ui/captions-button 2.63 kB
/ui/captions-radio-group 3.10 kB
/ui/cast-button 2.55 kB
/ui/compounds 3.04 kB
/ui/controls 2.88 kB
/ui/error-dialog 2.91 kB
/ui/fullscreen-button 2.57 kB
/ui/hotkey 2.47 kB
/ui/menu 2.92 kB
/ui/mute-button 2.56 kB
/ui/pip-button 2.58 kB
/ui/play-button 2.58 kB
/ui/playback-rate-button 2.67 kB
/ui/playback-rate-radio-group 2.95 kB
/ui/popover 3.13 kB
/ui/poster 2.44 kB
/ui/quality-radio-group 3.11 kB
/ui/seek-button 2.56 kB
/ui/seek-indicator 2.78 kB
/ui/seek-indicator-value 442 B
/ui/slider 2.91 kB
/ui/status-announcer 2.48 kB
/ui/status-indicator 2.61 kB
/ui/status-indicator-value 402 B
/ui/thumbnail 2.57 kB
/ui/time 2.90 kB
/ui/time-slider 2.94 kB
/ui/tooltip 2.92 kB
/ui/volume-indicator 2.57 kB
/ui/volume-indicator-fill 435 B
/ui/volume-indicator-value 408 B
/ui/volume-slider 2.91 kB

Sizes are marginal over the root entry point.

⚛️ @videojs/react — no changes
Presets (7)
Entry Initial Lazy
/video (default) 42.92 kB 51.99 kB
/video (default + hls) 180.96 kB 51.99 kB
/video (minimal) 43.41 kB 51.99 kB
/video (minimal + hls) 181.43 kB 51.99 kB
/audio (default) 36.21 kB 51.99 kB
/audio (minimal) 36.21 kB 51.99 kB
/background 579 B
Media (9)
Entry Initial
/media/background-video 403 B
/media/dash-video 212.96 kB
/media/hlsjs-video 139.77 kB
/media/mux-audio 162.32 kB
/media/mux-video 162.31 kB
/media/native-hls-video 7.28 kB
/media/simple-hls-audio-only 15.40 kB
/media/simple-hls-video 16.96 kB
/media/vimeo-video 10.45 kB
Skins (27)
Entry Type Initial Lazy
/tailwind.css css 161 B
/video/minimal-skin.css css 5.55 kB
/video/skin.css css 5.52 kB
/video/minimal-skin js 43.28 kB 51.99 kB
/video/minimal-skin.tailwind js 49.27 kB 51.99 kB
/video/skin js 42.88 kB 51.99 kB
/video/skin.tailwind js 48.86 kB 51.99 kB
/audio/minimal-skin.css css 3.79 kB
/audio/skin.css css 3.68 kB
/audio/minimal-skin js 36.14 kB 51.99 kB
/audio/minimal-skin.tailwind js 38.30 kB 51.99 kB
/audio/skin js 36.09 kB 51.99 kB
/audio/skin.tailwind js 40.28 kB 51.99 kB
/background/skin.css css 90 B
/background/skin js 272 B
/live-video/minimal-skin.css css 5.55 kB
/live-video/skin.css css 5.52 kB
/live-video/minimal-skin js 37.86 kB 51.99 kB
/live-video/minimal-skin.tailwind js 43.79 kB 51.99 kB
/live-video/skin js 37.87 kB 51.99 kB
/live-video/skin.tailwind js 43.87 kB 51.99 kB
/live-audio/minimal-skin.css css 3.79 kB
/live-audio/skin.css css 3.68 kB
/live-audio/minimal-skin js 26.65 kB 51.99 kB
/live-audio/minimal-skin.tailwind js 29.81 kB 51.99 kB
/live-audio/skin js 26.73 kB 51.99 kB
/live-audio/skin.tailwind js 29.84 kB 51.99 kB
UI Components (33)
Entry Initial
/ui/airplay-button 2.45 kB
/ui/alert-dialog 2.53 kB
/ui/audio-track 2.29 kB
/ui/buffering-indicator 2.39 kB
/ui/captions-button 2.42 kB
/ui/captions-radio-group 2.32 kB
/ui/cast-button 2.41 kB
/ui/controls 2.43 kB
/ui/error-dialog 2.47 kB
/ui/fullscreen-button 2.45 kB
/ui/gesture 2.23 kB
/ui/hotkey 2.23 kB
/ui/live-button 2.36 kB
/ui/menu 2.62 kB
/ui/mute-button 2.39 kB
/ui/pip-button 2.43 kB
/ui/play-button 2.46 kB
/ui/playback-rate 2.39 kB
/ui/playback-rate-button 2.47 kB
/ui/popover 2.96 kB
/ui/poster 2.40 kB
/ui/quality 2.30 kB
/ui/seek-button 2.42 kB
/ui/seek-indicator 2.62 kB
/ui/slider 2.57 kB
/ui/status-announcer 2.29 kB
/ui/status-indicator 2.33 kB
/ui/thumbnail 2.32 kB
/ui/time 2.24 kB
/ui/time-slider 2.50 kB
/ui/tooltip 2.97 kB
/ui/volume-indicator 2.33 kB
/ui/volume-slider 2.48 kB

Sizes are marginal over the root entry point.

🧩 @videojs/core — no changes
Entries (69)
Entry Initial Lazy
. 10.81 kB
/dom 17.56 kB
/dom/media/custom-media-element 2.09 kB
/dom/media/dash 208.96 kB
/dom/media/google-cast 4.03 kB
/dom/media/hls-js 135.88 kB
/dom/media/media-host 1.25 kB
/dom/media/media-played-ranges 576 B
/dom/media/mux 151.26 kB
/dom/media/native-hls 3.09 kB
/dom/media/simple-hls 16.51 kB
/dom/media/simple-hls-audio-only 14.92 kB
/dom/media/vimeo 9.86 kB
/media/predicate 563 B
/i18n 2.72 kB 51.99 kB
/i18n/runtime 1.32 kB
/i18n/locales/all 30.62 kB
/i18n/locales/ar 1.15 kB
/i18n/locales/az 1.04 kB
/i18n/locales/bg 1.21 kB
/i18n/locales/bn 1.23 kB
/i18n/locales/bs 981 B
/i18n/locales/ca 1.01 kB
/i18n/locales/cs 1019 B
/i18n/locales/cy 987 B
/i18n/locales/da 965 B
/i18n/locales/de 1.04 kB
/i18n/locales/el 1.39 kB
/i18n/locales/en 763 B
/i18n/locales/es 970 B
/i18n/locales/et 1.00 kB
/i18n/locales/eu 979 B
/i18n/locales/fa 1.15 kB
/i18n/locales/fi 1007 B
/i18n/locales/fr 1.01 kB
/i18n/locales/gd 1.05 kB
/i18n/locales/gl 965 B
/i18n/locales/he 1.07 kB
/i18n/locales/hi 1.24 kB
/i18n/locales/hr 1000 B
/i18n/locales/hu 1.04 kB
/i18n/locales/it 1004 B
/i18n/locales/ja 1.13 kB
/i18n/locales/ko 1.08 kB
/i18n/locales/lv 1.02 kB
/i18n/locales/mr 1.23 kB
/i18n/locales/nb 954 B
/i18n/locales/ne 1.23 kB
/i18n/locales/nl 976 B
/i18n/locales/nn 951 B
/i18n/locales/oc 1.02 kB
/i18n/locales/pl 1.07 kB
/i18n/locales/pt 981 B
/i18n/locales/pt-BR 981 B
/i18n/locales/pt-PT 954 B
/i18n/locales/ro 1.00 kB
/i18n/locales/ru 1.28 kB
/i18n/locales/sk 1.05 kB
/i18n/locales/sl 1008 B
/i18n/locales/sr 976 B
/i18n/locales/sv 978 B
/i18n/locales/te 1.26 kB
/i18n/locales/th 1.23 kB
/i18n/locales/tr 1.03 kB
/i18n/locales/uk 1.30 kB
/i18n/locales/vi 1.04 kB
/i18n/locales/zh 973 B
/i18n/locales/zh-CN 973 B
/i18n/locales/zh-TW 980 B
🏷️ @videojs/element — no changes
Entries (2)
Entry Initial
. 996 B
/context 943 B
📦 @videojs/store — no changes
Entries (3)
Entry Initial
. 1.39 kB
/html 696 B
/react 360 B
🔧 @videojs/utils — no changes
Entries (10)
Entry Initial
/array 104 B
/dom 2.71 kB
/events 319 B
/function 327 B
/object 275 B
/predicate 265 B
/string 231 B
/style 190 B
/time 792 B
/number 158 B
📦 @videojs/spf — no changes
Entries (4)
Entry Initial
. 4.45 kB
/dom 6.33 kB
/hls 15.37 kB
/background-video 12.89 kB

ℹ️ How to interpret

JS sizes are initial static graph totals (minified + brotli). Lazy dynamic chunks are shown separately when present.

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

Run pnpm size locally to check current initial sizes.

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Cursor Bugbot has reviewed your changes using default effort and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 2a4c08d. Configure here.

Comment thread apps/sandbox/templates/cdn/main.ts
sampotts and others added 14 commits July 3, 2026 13:53
Wire locale switching across HTML, React, and CDN sandbox presets with shared
locale helpers, browser-only locale prefetch, and i18n e2e tests.

Co-authored-by: Cursor <cursoragent@cursor.com>
Keep postMessage-driven toggles from forcing a cache-busted iframe reload
when autoplay, muted, or other shell controls change.

Co-authored-by: Cursor <cursoragent@cursor.com>
Drop the templates/cdn index override that produced an invalid relative
chunk path under Vite 8; setup already mirrors templates into src/cdn.

Co-authored-by: Cursor <cursoragent@cursor.com>
Serialize overlapping HTML/CDN locale updates, validate locale only in
shared listeners, and remove the vite e2e spec that referenced a missing page.

Co-authored-by: Cursor <cursoragent@cursor.com>
Track the previous locale so the CDN preview only cache-busts when locale
actually changes, not on the initial effect run.

Co-authored-by: Cursor <cursoragent@cursor.com>
Drop the readyLocale gate so locale switches and browser prefetch
failures no longer unmount the player preview.

Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Update preview iframe src when locale changes so embedded reloads keep
the selected language, not just the initial URL param.

Co-authored-by: Cursor <cursoragent@cursor.com>
Replace the misplaced "Media utilities" comment above the i18n re-exports.

Co-authored-by: Cursor <cursoragent@cursor.com>
…locale

Stop pinning lang on media-i18n-provider and I18nProvider locale props so
document.documentElement.lang and the locale picker both drive i18n through
the ambient observer as documented.

Co-authored-by: Cursor <cursoragent@cursor.com>
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.

3 participants