Version Last Commit License Manifest Ask DeepWiki Chrome Web Store
DualSub is a powerful Chrome extension that enhances your streaming experience by displaying dual language subtitles simultaneously. Perfect for language learning, accessibility, or simply enjoying content in multiple languages at once.
- Documentation
- Highlights
- Installation & Quick Start
- Development Setup
- Architecture
- Contributing
- Testing
- License
- Changelog
- Dual subtitles on Netflix and Disney+
- Multiple translation providers with rate limiting and caching
- AI Context Analysis (OpenAI, Google Gemini)
- Flexible layouts, appearance controls, and timing offset
- Multi-language UI (EN, ES, JA, KO, ZH-CN, ZH-TW)
See details in: features.md, platforms.md, providers.md.
- Install from the Chrome Web Store or load unpacked (see installation.md).
- Open Netflix or Disney+ and enable subtitles.
- Click the DualSub icon β enable dual subtitles and choose target language.
- Optional: Configure AI Context (provider, API key, model) in Advanced Settings.
Configuration reference: configuration.md. AI docs: ai-context.md.
For Language Learning:
Translation Provider: Microsoft Translate (Free)
Layout: Top/Bottom
Display Order: Original First
Font Size: Large
AI Context: Enabled (OpenAI GPT-5.6 Luna)
Context Types: Cultural, Historical, Linguistic
For Performance:
Request Delay: 100ms
Translation Provider: Google Translate
AI Context: Enabled (Google Gemini Flash)
Context Cache: Enabled
For Advanced Users:
Translation Provider: OpenAI Compatible
AI Context Provider: OpenAI GPT-5.6 Luna
Context Types: All
Rate Limit: 60 requests/minute
Cache TTL: 1 hour
Debug Logging: Enabled
- Node.js 24 LTS and npm 11+
- Google Chrome 116+ with Developer mode enabled
- Git for version control
-
Clone and Install
git clone https://github.com/QuellaMC/DualSub.git cd DualSub npm ci -
Development Commands
# Type-check, lint, and verify formatting npm run compile npm run lint npm run format:check # Tests: once, in watch mode, or with the enforced coverage floors npm test npm run test:watch npm run test:coverage # Production build, release archive, and archive audit npm run build npm run zip npm run verify:release
-
Load Extension for Testing
- Run
npm run build(ornpm run devto rebuild on every change) - Open
chrome://extensions, enable Developer mode, click Load unpacked, and select.output/chrome-mv3 - Reload the extension after each build
- Run
DualSub/
βββ src/
β βββ entrypoints/ # Background worker, content scripts, popup, options, side panel
β βββ background/ # Subtitle pipeline, translation, AI context, side panel authority
β βββ content/ # Page bridge, player sessions, renderer, selection, platform adapters
β βββ messaging/ # Cross-context contracts, router, client, sender authentication
β βββ config/ # Settings schema, storage service, migrations
β βββ shared/ # Logger, fetch hardening, provider constants
β βββ ui/ # React popup, options, side panel, shared hooks
β βββ build/ # Manifest golden snapshot and locale parity tests
β βββ test-utils/ # Test helpers
βββ public/ # Locale catalogs and icons
βββ scripts/ # Release verification
βββ docs/ # User documentation (en, zh) and reference material
βββ wxt.config.ts # Manifest and build configuration (WXT)
DualSub 3 is a TypeScript extension built with WXT, React 19, zod, and Vitest.
- One session per video: the content orchestrator keeps exactly one player session for the video on the current route, and every listener, timer, and request of a session ends with one abort signal
- Page bridge: a declaratively registered main-world script reads subtitle tracks from the platform's own player and talks to the isolated world over a message channel
- Contract-first messaging: every cross-context message is a zod contract; the router snapshots the payload, authenticates the sender, gates by role, and parses before a typed handler runs
- Background services: a subtitle pipeline with a CDN allowlist and byte caps, a translation service with per-provider pacing and caching, a fail-closed AI context service, and a side panel authority that keeps the content script the single source of selection truth
- Platform adapters (
src/content/platform/): Netflix and Disney+ specifics behind one interface - Translation providers (
src/background/translation/providers/): one error taxonomy and one pacing seam for every provider - Configuration service (
src/config/): typed settings schema, strict reads, credentials kept device-local, idempotent migrations - Side panel (
src/ui/sidepanel/,src/background/sidepanel/): selection sync with two-phase removal
Reference material: audit report, smoke protocol, store review notes.
We welcome contributions! Please follow these guidelines:
- ESLint + Prettier: Code must pass linting and formatting checks
- TypeScript strict: no
any, exact message contracts, typed settings - Testing: All new features require comprehensive tests
- Documentation: Update relevant documentation for changes
- Fork the repository
- Create a feature branch (
git checkout -b feature/amazing-feature) - Write tests for your changes
- Ensure all tests pass (
npm test) - Format code (
npm run format) - Lint code (
npm run lint:fix) - Commit changes (
git commit -m 'Add amazing feature') - Push to branch (
git push origin feature/amazing-feature) - Open a Pull Request
- Add a provider module under
src/background/translation/providers/implementingTranslationProvider - Register it in
providers/index.tsand add its id toPROVIDER_IDSinsrc/shared/providers.ts - Add its options card under
src/ui/options/providers/and its strings to every catalog inpublic/_locales/ - Add tests next to the module
- Add a platform under
src/content/platform/with a descriptor and an adapter - Declare its content scripts in
src/entrypoints/ - Extend the subtitle policy and parsers in
src/background/subtitle/for its CDN - Update the golden manifest in
src/build/manifest.golden.jsonin a commit that explains the change - Run the smoke protocol on the platform
- All submissions require review
- Tests must pass CI/CD pipeline
- Documentation must be updated
- Breaking changes require discussion
DualSub includes a comprehensive testing framework:
# Run all tests npm test # Watch mode for development npm run test:watch # Run one directory or file npm test -- src/config # Run tests with coverage npm run test:coverage
- Unit Tests: Individual component testing
- Integration Tests: Cross-component functionality
- Mock Infrastructure: fake-browser for extension APIs, happy-dom for UI
- Test Utilities: Shared testing helpers and fixtures
- Coverage: Keep the enforced coverage floors green and add focused regressions for changed behavior
- Isolation: Tests should not depend on each other
- Mocking: Use provided mocks for Chrome APIs
- Assertions: Clear, descriptive test assertions
This project is licensed under the Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License (CC BY-NC-SA 4.0).
- β Share: Copy and redistribute the material
- β Adapt: Remix, transform, and build upon the material
- β Commercial Use: Not permitted
- π Attribution: Must give appropriate credit
- π ShareAlike: Must distribute under same license
For full license terms, see LICENSE file.
- π No empty subtitle box over the video between lines
- π The side panel keeps a tab's selected words, running analysis, and answer while you visit other tabs and come back
- ποΈ Rebuilt from the ground up in TypeScript on WXT, with contract-first messaging and one player session per video
- π¬ Netflix player API: subtitle tracks come from the player itself, so DualSub keeps working after Netflix's 2026 player change
- π Microsoft Translate moved to Edge's tokenless endpoint after Microsoft retired the free auth endpoint
- π€ Side panel: clickable words, selection sync, and AI analysis with the failure reason shown in the panel
- π Credentials never leave the device, provider requests carry no browser cookies, and the AI rate limiter survives worker restarts
- π€ Unified AI Experience: Integrated AI Context Analysis into the Side Panel for a seamless, persistent workspace.
- π Stability Improvements: Fixed desync issues when switching videos or deselecting words in the side panel.
- β¨ Better UX: Improved word selection ordering to always match sentence structure.
- π Full React Migration: Popup and options pages migrated to React with 100% functional parity
- β¨ Modern component-based architecture with custom hooks
- π¦ Vite build system for optimized production bundles
- π Fixed container width consistency and i18n translation keys
- π Comprehensive migration documentation
See CHANGELOG.md for detailed version history.
- Messaging reliability: Refactored messaging utilities to support both callback- and promise-style chrome.runtime.sendMessage, with wake-up retries for MV3 service worker.
- Unified resilient message sending across platform adapters (BasePlatformAdapter + Netflix), improving background communication stability and test determinism.
- AI Context: Provider metrics now correctly reflect success/error; tests updated to tolerate callback/promise messaging; dynamic chrome access prevents stale mocks between tests.
- Internal refactors and stability improvements.
- π§ Netflix next-episode preload-aware subtitles: buffers subtitle tracks detected before navigation and applies them immediately after SPA route change to the next episode, fixing cases where subtitles did not update on Next Episode.
- π§© Universal improvement: content script now notifies the platform on URL changes, laying the groundwork for cross-platform preload handling.
- π οΈ Netflix soft navigation fix: Resolves issue where moving to the next episode (SPA navigation) could continue showing previous episode subtitles. Subtitles now reset and rebind to the new video context.
- π― Disney+ progress bar update: Adjusted detection to the updated site UI; timing now reads directly from the progress-bar web componentβs shadow DOM via aria attributes for accurate sync.
- π§© Modularized documentation with English and Chinese docs under
docs/ - π§ AI Context UI/UX refinements (modal, transitions, selection persistence)
- π§Ή Internal refactors and minor fixes
- π Added vertical position control for precise subtitle placement on screen
- π¨ Enhanced appearance customization with new positioning options
- βοΈ Improved user interface with vertical position slider control
- π€ NEW: AI Context Analysis feature with OpenAI and Google Gemini support
- π― Interactive subtitle text selection with cultural, historical, and linguistic explanations
- π Comprehensive API key management and provider configuration
- π§ Advanced caching and rate limiting for AI context requests
- β¨ Added Netflix support with official subtitle integration
- π Implemented multiple selectable translation providers with bounded retries
- π Added multi-language UI support (6 languages)
- βοΈ Introduced advanced options page
- ποΈ Refactored architecture with Template Method pattern
- π§ͺ Added comprehensive testing framework
- π Implemented configurable logging system
- π§ Enhanced configuration management
For detailed version history, see GitHub Releases
- π Bug Reports: GitHub Issues
- π‘ Feature Requests: GitHub Discussions
- π Documentation: Wiki