
Netflix-Google-Translate
Translate Netflix captions with google translate.
Created Jul 2021
The project has been refactored to support installation as a Mozilla Firefox add-on, incorporating a new manifest.json along with necessary UI and script adjustments. This change transitions the project from a raw userscript to a formal browser extension, significantly improving the user onboarding and configuration experience.
The universal translator script has been updated to switch from Google Translate to the Yandex Translate API. This update adjusts the payload structure and API endpoint URL to match Yandex's requirements, ensuring continued functionality for automated language translations. You'll need to update your configuration with a valid Yandex API key to keep things running.
The main script file has been renamed from universalTranslator.js to universalTranslator.user.js. This change ensures that browser userscript managers like Tampermonkey correctly identify and handle the script for installation and updates. Users can now easily manage the script through their preferred extension dashboard.
Updated the MutationObserver in universalTranslator.js to track attribute changes on subtitle elements, ensuring translations re-trigger when the player resets or modifies caption properties (like font size or positioning). I also addressed an issue where subtitles were being improperly processed due to missing line endings during DOM extraction. These changes ensure captions remain consistently translated throughout the viewing experience.
This change abstracts the hardcoded player-timedtext selector out of setupObserver and passes the class name in as a parameter instead. It also updates the retry and logging paths so the observer setup is consistently scoped to whatever target class is being watched. The behavior stays the same for current Netflix captions, but the code is now cleaner and easier to adapt if the caption container changes or additional targets need to be supported later.
Previously, network or API problems during a fetch call could result in unhandled promise rejections, leaving users and developers clueless about the failure. A .catch() block has been introduced in universalTranslator.js to properly intercept these errors and log them to the console. This small improvement prevents silent failures and makes diagnosing translation service or connectivity issues far easier.
This change cleans up universalTranslator.js so translateCaption now consistently calls its callback with just the translated text, instead of passing an unused err argument first. The caller was already ignoring errors and only using the translated value, so this makes the async flow easier to follow and better matches how the function is actually used. Practical effect: less callback noise and slightly clearer subtitle translation logic.
This update addresses a compatibility issue regarding how HTTP requests are handled within Firefox WebExtension content scripts. By conditionally referencing the content environment and falling back to the standard global fetch API, the translator script ensures it can securely make POST requests under strict extension contexts. This minor adjustment prevents unexpected network request failures across different browser execution environments.
This change introduces a commented-out console.log right after translated text is normalized and cached, giving developers a quick way to inspect translation results during troubleshooting without changing runtime behavior by default. Itβs a small but practical debugging affordance in the translation flow, especially when validating output formatting like <br> replacement. The immediate effect is easier local debugging with no impact on production behavior.
The extension previously used a setInterval block to check for subtitle updates every 10 milliseconds, which created unnecessary CPU overhead. It now uses a MutationObserver attached to the persistent player-timedtext container, triggering the translation process only when new subtitle nodes are actually injected into the DOM. This provides a much more efficient, event-driven approach rather than constantly polling the page.
The universal translator script now provides the ability to explicitly define the source language for subtitles alongside the target language. The underlying Google Cloud Translation API integration has been updated to accept and pass a 2-letter source language code (langsrc). This update prevents translation ambiguities and gives users more reliable control over subtitle conversions.
This change refactors universalTranslator.js so the translation endpoint URL is passed into initTranslator instead of being hardcoded inside the function. Itβs a small cleanup, but it makes the userscript easier to adapt for different environments or future API endpoint changes without editing internal logic. Practical effect: configuration is a bit cleaner and the translator is easier to maintain.
The codebase has been modernized by replacing legacy XMLHttpRequest logic with the standard fetch API for Netflix caption translation requests. Alongside this update, the request payload was refactored to use URLSearchParams instead of raw JSON strings, and explicit promise-based error handling was added. This cleans up the code structure, reduces boilerplate, and aligns the translation engine with modern web development practices.
The plain text file description in universalTranslator.js has been replaced with a proper Tampermonkey metadata block. This update allows the script to be directly installed and executed via the Tampermonkey browser extension, specifically matching Netflix video URLs (https://www.netflix.com/watch/*). It's a quick update that significantly improves the setup experience for users wanting to translate Netflix captions on the fly.
Added an initial prototype for translating Netflix captions on the fly using the Google Translate API. The script relies on observing DOM elements for subtitle updates, caching common statements to reduce API cost, and actively swapping translated text back onto the player. It is currently designed to run directly from the developer console and serves as a clever starting point for an extension.
