Skip to content

feat(l10n): Full i18n — 21 languages, auto-detection, splash language picker - #200

Merged
debpalash merged 1 commit into
mainfrom
debpalash/translation
May 31, 2026
Merged

feat(l10n): Full i18n — 21 languages, auto-detection, splash language picker#200
debpalash merged 1 commit into
mainfrom
debpalash/translation

Conversation

@debpalash

@debpalash debpalash commented May 31, 2026

Copy link
Copy Markdown
Owner

Summary

Complete internationalization (i18n) implementation for OmniVoice Studio with 21 languages at 100% coverage (837 keys each).

What's included

🌍 Language Support

# Language Code Keys
1 English en 837 (source)
2 Spanish es 837 ✅
3 French fr 837 ✅
4 German de 837 ✅
5 Japanese ja 837 ✅
6 Chinese (Simplified) zh-CN 837 ✅
7 Chinese (Traditional) zh-TW 837 ✅
8 Portuguese pt 837 ✅
9 Italian it 837 ✅
10 Russian ru 837 ✅
11 Korean ko 837 ✅
12 Hindi hi 837 ✅
13 Turkish tr 837 ✅
14 Polish pl 837 ✅
15 Dutch nl 837 ✅
16 Swedish sv 837 ✅
17 Thai th 837 ✅
18 Vietnamese vi 837 ✅
19 Indonesian id 837 ✅
20 Ukrainian uk 837 ✅
21 Arabic ar 837 ✅

🔧 Features

  • Auto-detection: Detects browser/OS language and sets locale automatically on first launch
  • Splash language picker: Users can switch language during the bootstrap splash screen
  • Language suggestion banner: Prompts user if system language differs from current app locale
  • Settings integration: Language selector in Settings for switching at any time
  • Full coverage: Every UI component translated — settings, dialogs, tooltips, errors, main interface

🛠 Tooling

  • scripts/translate_all.py — batch translation script using deep_translator with placeholder/HTML-tag masking for safe re-translation

Testing

  • Verified all 20 locale JSON files parse without errors
  • Confirmed 837/837 keys present in every locale (100% coverage)
  • Placeholder interpolations ({{count}}, {{name}}) and HTML tags (<1>, </0>) preserved intact

Summary by CodeRabbit

Release Notes

  • Localization
    • Expanded multi-language support across 19 languages with comprehensive translation coverage for navigation, settings, privacy controls, voice cloning, video dubbing, transcriptions, and more.
    • Added localized strings for new configuration options including proxy settings, FFmpeg path management, and UI scaling preferences.

Translate all UI keys across every component for 20 non-English locales:
ar, de, es, fr, hi, id, it, ja, ko, nl, pl, pt, ru, sv, th, tr, uk, vi, zh-CN, zh-TW

- 837 flattened keys per language (100% coverage)
- Covers settings, splash, main UI, dialogs, tooltips, errors
- Placeholders ({{var}}) and HTML tags (<1>) preserved
- Add translate_all.py batch script for future re-translations
@coderabbitai

coderabbitai Bot commented May 31, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

This PR expands internationalization coverage by adding comprehensive translation strings across 19 language locales (Arabic, German, Spanish, French, Hindi, Indonesian, Italian, Japanese, Korean, Dutch, Polish, Portuguese, Russian, Swedish, Thai, Turkish, Ukrainian, Vietnamese, and Traditional Chinese), and introduces a Python script to automate locale file generation and maintenance.

Changes

Internationalization Expansion

Layer / File(s) Summary
Navigation and settings baseline
frontend/src/i18n/locales/{ar,de,es,fr,hi,id,it,ja,ko,nl,pl,pt,ru,sv,th,tr,uk,vi,zh-TW}.json
Expands nav section across all locales with new menu items (stories, launchpad, gallery, transcripts, omnidrive). Extends settings section with privacy, UI scale, proxy configuration (HTTP/SOCKS), and FFmpeg path detection/configuration strings. Adds bootstrap language selection and pluralized line count strings in applicable locales.
Core feature translations
frontend/src/i18n/locales/{ar,de,es,fr,hi,id,it,ja,ko,nl,pl,pt,ru,sv,th,tr,uk,vi,zh-TW}.json
Adds comprehensive translation namespaces for story editor UI (characters, lines, export), common shared actions, launchpad onboarding, voice cloning workflows, application metadata (about), privacy descriptions, credential configuration (API keys, translator engines), engine status labels, capture/hotkey instructions, and logging messages. Applied consistently across all 19 locales.
Dubbing and content management translations
frontend/src/i18n/locales/{ar,de,es,fr,hi,id,it,ja,ko,nl,pl,pt,ru,sv,th,tr,uk,vi,zh-TW}.json
Adds translation coverage for voice profile management (test, generate, unlock, delete), video dubbing pipeline (transcribe/translate/generate/export workflow), glossary term management (auto-extraction, scanning, clearing), segment editor controls (time/speaker/text/language/voice, split/merge, direction), voice personality selection, AI directorial tools, project listing/export, and batch dubbing job status/progress states. Consistent structure across all locales.
Setup, monetization, and export translations
frontend/src/i18n/locales/{ar,de,es,fr,hi,id,it,ja,ko,nl,pl,pt,ru,sv,th,tr,uk,vi,zh-TW}.json
Adds translation coverage for transcription list management and export, initial setup wizard and system check flow, donation/support landing page content, enterprise/commercial licensing messaging and pricing information, export modal configuration (tracks, formats, subtitles, packaging), and demo/onboarding tutorial and dictation preview controls. Completes feature set across all 19 locales.
Translation automation script
scripts/translate_all.py
Implements Python utility to automate locale file generation and updates. Loads English source (en.json), flattens nested keys into dot-separated paths, detects missing keys per target language, translates in batches (40 keys/batch) using Google Translator, masks i18next interpolations ({{var}}) and numeric HTML tags before translation and restores them after, validates batch split counts and falls back to per-key translation on mismatch, and writes updated JSON files. Provides mask_text(), unmask_text(), get_flat_keys(), set_nested_value(), and main() entry point.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title 'feat(l10n): Full i18n — 21 languages, auto-detection, splash language picker' accurately summarizes the main change: implementing complete internationalization across 21 languages with key features like auto-detection and a language picker during bootstrap.
Description check ✅ Passed The PR description is comprehensive and complete. It includes a clear summary, detailed language support table (all 21 languages), feature list, tooling information, and testing validation. However, it lacks explicit confirmation of testing in the checklist section that the description template requires.
Docstring Coverage ✅ Passed Docstring coverage is 80.00% which is sufficient. The required threshold is 80.00%.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch debpalash/translation

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@greptile-apps

greptile-apps Bot commented May 31, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR adds 20 machine-translated locale JSON files (bringing coverage to 21 languages including English) and the translate_all.py script that produced them via Google Translate with placeholder masking. All 837 keys are present in every locale and the vast majority of interpolations were preserved correctly.

  • ar.json broken chapter placeholder: The {{n}} in stories.chapterN was mangled to __الخامس_0__ (Google Translate mistook the internal mask token V for an Arabic word), so Arabic chapter headings will display raw garbage text at runtime.
  • de.json protocol typo: proxy_desc contains sock5:// instead of socks5:// — one s was silently dropped during translation.
  • scripts/translate_all.py hardcoded path: LOCALES_DIR is set to an absolute path on the author's local machine, so the script immediately fails with FileNotFoundError on any other machine or in CI.

Confidence Score: 3/5

Safe to merge once the Arabic chapterN placeholder, the German socks5 typo, and the hardcoded script path are fixed; the remaining 18 locales are clean.

Two locale files carry real runtime defects: Arabic chapter headings will render a raw internal mask token instead of the chapter number, and German users reading the proxy settings tooltip see an invalid sock5:// scheme. The translation script also ships with a path pointing at a single developer workstation, making it immediately non-functional for anyone else.

frontend/src/i18n/locales/ar.json (broken {{n}} in stories.chapterN), frontend/src/i18n/locales/de.json (sock5:// typo in proxy_desc), and scripts/translate_all.py (hardcoded local machine path).

Important Files Changed

Filename Overview
frontend/src/i18n/locales/ar.json 837-key Arabic locale; stories.chapterN has a corrupted {{n}} placeholder (mangled to الخامس_0 by Google Translate), breaking chapter number rendering at runtime.
frontend/src/i18n/locales/de.json 837-key German locale; settings.proxy_desc contains sock5:// (missing an s) instead of the correct socks5:// scheme.
scripts/translate_all.py Batch translation helper using deep_translator; LOCALES_DIR is hardcoded to a developer local absolute path, making the script unusable on any other machine as-is.
frontend/src/i18n/locales/es.json 837-key Spanish locale; all placeholders and plural forms verified intact.
frontend/src/i18n/locales/fr.json 837-key French locale; all placeholders and plural forms verified intact.
frontend/src/i18n/locales/ja.json 837-key Japanese locale; all placeholders intact; plural forms correctly added to bootstrap section.
frontend/src/i18n/locales/zh-TW.json 837-key Traditional Chinese locale; no issues detected.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A[App Launch] --> B{First run?}
    B -- Yes --> C[Splash Language Picker]
    B -- No --> D{Saved locale in settings?}
    C --> E[User selects language]
    E --> F[Save locale preference]
    D -- Yes --> G[Load saved locale]
    D -- No --> H[Auto-detect browser/OS language]
    H --> I{Detected lang supported?}
    I -- Yes --> J[Apply detected locale]
    I -- No --> K[Fall back to English]
    J --> L{Detected != current locale?}
    L -- Yes --> M[Show suggestion banner]
    L -- No --> N[No banner]
    G --> O[Load i18n JSON]
    F --> O
    K --> O
    M --> O
    N --> O
    O --> P[Render UI in selected language]
    P --> Q[Settings: language selector available anytime]
Loading

Fix All in Claude Code

Reviews (1): Last reviewed commit: "feat(l10n): complete translations for al..." | Re-trigger Greptile

"autocastEmpty": "لا يوجد شيء للإرسال التلقائي — قم بلصق قصة أو استيرادها أولاً.",
"autocastDone": "إرسال تلقائي {{lines}} خطوط عبر {{voices}} صوت (أصوات)",
"importFailed": "لا يمكن قراءة هذا الملف.",
"addLine": "إضافة خط",

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

P1 Corrupted interpolation placeholder in stories.chapterN

The {{n}} placeholder was mangled during machine translation — Google Translate turned the internal mask token __V_0__ into __الخامس_0__ ("الخامس" = "fifth" in Arabic) because the mask letter V looked like a translatable word in context. The unmasking regex only searches for the literal string __V_0__, so it never matched the Arabic-corrupted form and left the raw mask in the output.

At runtime, chapter headings in Arabic will display as "الفصل __الخامس_0__" (literal garbage) instead of "الفصل 1", "الفصل 2", etc. This is the only locale affected; all 19 others correctly carry {{n}}.

Fix in Claude Code

"title": "Einstellungen",
"ui_scale": "UI-Skala",
"proxy": "Stellvertreter",
"proxy_desc": "HTTP/SOCKS5-Proxy für Downloads (yt-dlp, HuggingFace). Unterstützt http://, https://, sock5://. Bei Änderung nach dem Backend-Start ist ein Neustart erforderlich.",

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

P1 socks5:// protocol scheme misspelled in German proxy_desc

Google Translate dropped one s, rendering sock5:// — an invalid protocol scheme. Every other locale correctly preserves socks5://. Any German-locale user who copies this string verbatim will end up with a broken proxy configuration that silently fails.

Suggested change
"proxy_desc": "HTTP/SOCKS5-Proxy für Downloads (yt-dlp, HuggingFace). Unterstützt http://, https://, sock5://. Bei Änderung nach dem Backend-Start ist ein Neustart erforderlich.",
"proxy_desc": "HTTP/SOCKS5-Proxy für Downloads (yt-dlp, HuggingFace). Unterstützt http://, https://, socks5://. Bei Änderung nach dem Backend-Start ist ein Neustart erforderlich.",

Fix in Claude Code

Comment thread scripts/translate_all.py
import time
from deep_translator import GoogleTranslator

LOCALES_DIR = "/Users/user4/orca/workspaces/OmniVoice/translation/frontend/src/i18n/locales"

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

P1 Hardcoded absolute path to a developer's local machine

LOCALES_DIR is pinned to /Users/user4/orca/workspaces/..., so running this script on any other machine immediately raises FileNotFoundError before any translation work begins. The path needs to be derived at runtime relative to the script's own location so that contributors and CI can use it without modification.

Suggested change
LOCALES_DIR = "/Users/user4/orca/workspaces/OmniVoice/translation/frontend/src/i18n/locales"
LOCALES_DIR = os.path.join(os.path.dirname(os.path.abspath(__file__)), "..", "frontend", "src", "i18n", "locales")

Fix in Claude Code

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 19

🧹 Nitpick comments (2)
scripts/translate_all.py (2)

139-143: 💤 Low value

Add strict=True to zip() for safety.

While the length check on line 139 ensures the iterables are the same length, adding strict=True to the zip() call on line 140 provides an additional safety guarantee and makes the intent explicit (requires Python 3.10+).

🔒 Suggested improvement
                 # Check if the split parts match the batch keys length
                 if len(parts) == len(batch_keys):
-                    for k, translated_val, (vars_found, tags_found) in zip(batch_keys, parts, masks_metadata):
+                    for k, translated_val, (vars_found, tags_found) in zip(batch_keys, parts, masks_metadata, strict=True):
                         final_val = unmask_text(translated_val, vars_found, tags_found)
                         set_nested_value(lang_data, k, final_val)
                     success = True
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@scripts/translate_all.py` around lines 139 - 143, The zip over batch_keys,
parts, and masks_metadata should be made strict to ensure all three iterables
have identical lengths at iteration time; update the zip call in the loop that
currently iterates "for k, translated_val, (vars_found, tags_found) in
zip(batch_keys, parts, masks_metadata):" to include strict=True so it becomes
zip(batch_keys, parts, masks_metadata, strict=True), keeping the existing
len(parts) == len(batch_keys) check and preserving the use of unmask_text and
set_nested_value and the success flag.

88-93: 💤 Low value

Consider logging JSON parse errors for debugging.

The broad exception catch on line 92 silently swallows JSON parsing errors. While falling back to an empty dict is reasonable, logging the exception would help maintainers debug corrupted locale files.

📝 Suggested improvement
         if os.path.exists(lang_path):
             with open(lang_path, "r", encoding="utf-8") as f:
                 try:
                     lang_data = json.load(f)
-                except Exception:
+                except json.JSONDecodeError as e:
+                    print(f"  Warning: Failed to parse {lang_path}: {e}. Reinitializing...", flush=True)
                     lang_data = {}
         else:
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@scripts/translate_all.py` around lines 88 - 93, The try/except around
json.load(lang_path) silently swallows JSON parse errors; modify the block in
translate_all.py that reads lang_path so the except captures the exception as e
(e.g., except Exception as e) and logs the error before falling back to
lang_data = {} — use the module logger (or add import logging and getLogger) and
include the exception message/traceback in the log so corrupted locale files are
visible when json.load fails.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@frontend/src/i18n/locales/ar.json`:
- Line 86: The value for the localization key "chapterN" (stories.chapterN)
contains a corrupted placeholder ("الخامس_0") which breaks runtime
interpolation; update the "chapterN" string to use the same placeholder token
format used across other locale entries (i.e., replace the corrupted segment
with the project's interpolation token convention such as the {0} or __{n}__
style used elsewhere) so the chapter number will be rendered at runtime.

In `@frontend/src/i18n/locales/de.json`:
- Line 30: Update the German translation for the settings help text: replace the
incorrect proxy scheme token "sock5://" with the correct "socks5://" in the
"proxy_desc" value (JSON key "proxy_desc" in frontend/src/i18n/locales/de.json)
so the help string correctly lists http://, https://, socks5:// and keep the
rest of the sentence intact.

In `@frontend/src/i18n/locales/es.json`:
- Line 30: The Spanish translation for the "proxy_desc" JSON key incorrectly
localizes the protocol scheme to "calcetines5://" making the example proxy URI
invalid; update the value of "proxy_desc" so the protocol literal remains
"socks5://" (i.e., keep "http://, https://, socks5://") instead of the
translated form, preserving the literal URI schemes in the string.

In `@frontend/src/i18n/locales/fr.json`:
- Line 30: The French translation for the proxy help text localized the URI
scheme "socks5://" as "chaussettes5://", which is invalid; update the
"proxy_desc" value to keep URI schemes untranslated (http://, https://,
socks5://) by replacing "chaussettes5://" with "socks5://", ensuring the rest of
the sentence remains French but all URI schemes remain in their original form.

In `@frontend/src/i18n/locales/hi.json`:
- Line 305: The helper text for the DeepL base URL (key "deepl_base_url_help")
contains a typo in the default endpoint; update the string value to use the
correct domain "https://api.deepl.com/v2" instead of "https://api.depl.com/v2"
so the displayed default DeepL API endpoint is accurate.

In `@frontend/src/i18n/locales/id.json`:
- Line 30: The "proxy_desc" translation contains an incorrect localized
technical scheme "kaus kaki5://" which should preserve the original protocol
string; update the value of "proxy_desc" to use "socks5://" instead of "kaus
kaki5://" so the technical URI scheme remains accurate (edit the "proxy_desc"
JSON entry).

In `@frontend/src/i18n/locales/it.json`:
- Line 30: The Italian translation for the proxy description incorrectly
localizes the protocol token; update the "proxy_desc" entry so the protocol
scheme remains "socks5://" (not "calzini5://") — locate the "proxy_desc" key in
frontend/src/i18n/locales/it.json and replace the translated protocol token with
the literal "socks5://", leaving the rest of the sentence intact.

In `@frontend/src/i18n/locales/ja.json`:
- Line 10: The JSON key "transcripts" currently maps to the academic term
"成績証明書" which is incorrect for speech-transcription UI; update the value for the
"transcripts" key (and the other occurrences of the same key in this locale) to
the proper speech-transcription term such as "文字起こし" (or "書き起こし" if preferred)
so all transcription screens and fields use the correct Japanese wording; locate
the "transcripts" entries in frontend/src/i18n/locales/ja.json and replace their
values consistently.

In `@frontend/src/i18n/locales/ko.json`:
- Line 30: The translation for the "proxy_desc" string incorrectly replaced the
literal protocol prefix socks5:// with a translated form ("양말5://"); revert that
piece so the value contains the exact protocol literals "http://", "https://",
and "socks5://". Edit the "proxy_desc" entry to replace "양말5://" with
"socks5://" and leave the rest of the Korean text unchanged so users see valid
scheme names when configuring the download proxy.

In `@frontend/src/i18n/locales/nl.json`:
- Line 30: The Dutch translation for the proxy description incorrectly changed
the proxy scheme "socks5://" to "sokken5://"; update the "proxy_desc" value to
use the correct, untranslated scheme "socks5://", keeping the rest of the Dutch
text intact so the app can accept the documented proxy prefix.

In `@frontend/src/i18n/locales/pl.json`:
- Line 30: The translation for the "proxy_desc" key contains an invalid scheme
"skarpetki5://"; revert that token to the literal "socks5://" (leave the scheme
untranslated) so the proxy help text reads with the correct "socks5://" scheme
and does not break users following the example.

In `@frontend/src/i18n/locales/pt.json`:
- Line 30: The Portuguese translation for the "proxy_desc" string contains an
incorrect proxy scheme "meias5://" — update the value to use the correct scheme
"socks5://" so the string reads "Suporta http://, https://, socks5://." and
preserve the rest of the message (including the key "proxy_desc") unchanged.

In `@frontend/src/i18n/locales/ru.json`:
- Line 429: The localization string "export_srt" currently has the value "СТО"
which obscures the .srt subtitle format; update the value of the "export_srt"
key to the literal "SRT" so the label matches the file-format and the
surrounding .srt strings, preserving consistency in
frontend/src/i18n/locales/ru.json and any UI text that references export_srt.

In `@frontend/src/i18n/locales/sv.json`:
- Line 156: The "greeting" localization entry currently uses the Swedish
farewell "hej då"; update the value of the "greeting" key in sv.json to a proper
Swedish greeting such as "hej" or "välkommen" so the launchpad shows a greeting
instead of a goodbye (locate the "greeting" key in
frontend/src/i18n/locales/sv.json and replace its value).

In `@frontend/src/i18n/locales/vi.json`:
- Line 88: Several Vietnamese translation entries use the corrupted placeholder
`_V_0__` which will render literally; replace them with the correct i18next
interpolation tokens: change the value for "stemsDone" to use {{count}}, the key
at line ~361 to use {{message}}, the key at ~511 to use {{engine}}, the key at
~531 to use {{count}}, and the key at ~674 to use {{duration}}; locate each JSON
property (e.g. "stemsDone") and update its string to use the matching {{...}}
placeholder so i18next can interpolate properly.

In `@frontend/src/i18n/locales/zh-TW.json`:
- Line 450: The zh-TW locale contains Simplified Chinese characters; update the
affected JSON values to Traditional Chinese for consistent locale
display—specifically change the "pull_captions_title" string replacing 当→當, 带→帶,
还→還, 为→為, 运行→運行, 对→對 (and any other simplified tokens in that value); change
"desc" value replacing 音频→音訊 or 音頻 and 实用程序→實用程式; change "speech_rate_desc"
replacing 检查→檢查 and 与→與; and change "probe_placeholder" replacing 用户→使用者 and
电影→電影; ensure each JSON value uses proper Traditional Chinese phrasing and
punctuation while preserving the existing keys and structure.

In `@scripts/translate_all.py`:
- Line 7: LOCALES_DIR is set to a hardcoded absolute user home path; change it
to a repository-relative or script-relative path instead (e.g., build
LOCALES_DIR using pathlib.Path(__file__).resolve().parent /
"relative/path/to/frontend/src/i18n/locales" or use a path from the repo root)
so the script no longer contains /Users/user4/...; update the LOCALES_DIR
assignment to compute the path at runtime and ensure any downstream uses of
LOCALES_DIR continue to work with the new Path object.
- Around line 151-156: The loop is redundantly calling mask_text(val) and
unpacking unused (vars_found, tags_found) from masks_metadata; change the
for-loop over batch_keys, batch_values, masks_metadata to accept the
already-computed masks (e.g., for k, val, (vars_found, tags_found) in
zip(batch_keys, batch_values, masks_metadata, strict=True)): remove the extra
call to mask_text(val) and instead use the existing vars_found and tags_found
when calling unmask_text after translator.translate, and if any unpacked names
are unused replace them with _ to avoid confusion; ensure you keep
set_nested_value(lang_data, k, final_val) and add strict=True to zip() for
safety.
- Line 5: scripts/translate_all.py currently unconditionally imports and calls
GoogleTranslator.translator.translate (causing outbound network requests) and
uses a hardcoded absolute LOCALES_DIR; fix by gating any external-API usage
behind an explicit opt-in env flag (e.g., ENABLE_GOOGLE_TRANSLATE) or CLI flag
so that GoogleTranslator is only imported and translator.translate invoked when
that flag is true, performing the import lazily inside the guarded branch and
wrapping calls in try/except with a clear log on failure; also remove the
absolute path by computing LOCALES_DIR relative to the repository (use pathlib
and __file__ to build a path) or read it from an environment variable (e.g.,
LOCALES_DIR) so the script is portable across machines.

---

Nitpick comments:
In `@scripts/translate_all.py`:
- Around line 139-143: The zip over batch_keys, parts, and masks_metadata should
be made strict to ensure all three iterables have identical lengths at iteration
time; update the zip call in the loop that currently iterates "for k,
translated_val, (vars_found, tags_found) in zip(batch_keys, parts,
masks_metadata):" to include strict=True so it becomes zip(batch_keys, parts,
masks_metadata, strict=True), keeping the existing len(parts) == len(batch_keys)
check and preserving the use of unmask_text and set_nested_value and the success
flag.
- Around line 88-93: The try/except around json.load(lang_path) silently
swallows JSON parse errors; modify the block in translate_all.py that reads
lang_path so the except captures the exception as e (e.g., except Exception as
e) and logs the error before falling back to lang_data = {} — use the module
logger (or add import logging and getLogger) and include the exception
message/traceback in the log so corrupted locale files are visible when
json.load fails.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: dcdd05ff-017c-4b80-84bf-be1eab34bad1

📥 Commits

Reviewing files that changed from the base of the PR and between 672f106 and e5bdb5e.

📒 Files selected for processing (20)
  • frontend/src/i18n/locales/ar.json
  • frontend/src/i18n/locales/de.json
  • frontend/src/i18n/locales/es.json
  • frontend/src/i18n/locales/fr.json
  • frontend/src/i18n/locales/hi.json
  • frontend/src/i18n/locales/id.json
  • frontend/src/i18n/locales/it.json
  • frontend/src/i18n/locales/ja.json
  • frontend/src/i18n/locales/ko.json
  • frontend/src/i18n/locales/nl.json
  • frontend/src/i18n/locales/pl.json
  • frontend/src/i18n/locales/pt.json
  • frontend/src/i18n/locales/ru.json
  • frontend/src/i18n/locales/sv.json
  • frontend/src/i18n/locales/th.json
  • frontend/src/i18n/locales/tr.json
  • frontend/src/i18n/locales/uk.json
  • frontend/src/i18n/locales/vi.json
  • frontend/src/i18n/locales/zh-TW.json
  • scripts/translate_all.py

"importFailed": "لا يمكن قراءة هذا الملف.",
"addLine": "إضافة خط",
"addChapter": "إضافة الفصل",
"chapterN": "الفصل __الخامس_0__",

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Fix broken interpolation placeholder in stories.chapterN.

"chapterN" no longer contains the runtime placeholder token and appears corrupted, which will break chapter number rendering.

Proposed fix
-    "chapterN": "الفصل __الخامس_0__",
+    "chapterN": "الفصل {{n}}",
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
"chapterN": "الفصل __الخامس_0__",
"chapterN": "الفصل {{n}}",
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@frontend/src/i18n/locales/ar.json` at line 86, The value for the localization
key "chapterN" (stories.chapterN) contains a corrupted placeholder ("الخامس_0")
which breaks runtime interpolation; update the "chapterN" string to use the same
placeholder token format used across other locale entries (i.e., replace the
corrupted segment with the project's interpolation token convention such as the
{0} or __{n}__ style used elsewhere) so the chapter number will be rendered at
runtime.

"title": "Einstellungen",
"ui_scale": "UI-Skala",
"proxy": "Stellvertreter",
"proxy_desc": "HTTP/SOCKS5-Proxy für Downloads (yt-dlp, HuggingFace). Unterstützt http://, https://, sock5://. Bei Änderung nach dem Backend-Start ist ein Neustart erforderlich.",

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Correct proxy scheme typo in help text.

settings.proxy_desc lists sock5://, but the supported scheme is socks5://.

Proposed fix
-    "proxy_desc": "HTTP/SOCKS5-Proxy für Downloads (yt-dlp, HuggingFace). Unterstützt http://, https://, sock5://. Bei Änderung nach dem Backend-Start ist ein Neustart erforderlich.",
+    "proxy_desc": "HTTP/SOCKS5-Proxy für Downloads (yt-dlp, HuggingFace). Unterstützt http://, https://, socks5://. Bei Änderung nach dem Backend-Start ist ein Neustart erforderlich.",
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
"proxy_desc": "HTTP/SOCKS5-Proxy für Downloads (yt-dlp, HuggingFace). Unterstützt http://, https://, sock5://. Bei Änderung nach dem Backend-Start ist ein Neustart erforderlich.",
"proxy_desc": "HTTP/SOCKS5-Proxy für Downloads (yt-dlp, HuggingFace). Unterstützt http://, https://, socks5://. Bei Änderung nach dem Backend-Start ist ein Neustart erforderlich.",
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@frontend/src/i18n/locales/de.json` at line 30, Update the German translation
for the settings help text: replace the incorrect proxy scheme token "sock5://"
with the correct "socks5://" in the "proxy_desc" value (JSON key "proxy_desc" in
frontend/src/i18n/locales/de.json) so the help string correctly lists http://,
https://, socks5:// and keep the rest of the sentence intact.

"title": "Configuración",
"ui_scale": "Escala de interfaz de usuario",
"proxy": "apoderado",
"proxy_desc": "Proxy HTTP/SOCKS5 para descargas (yt-dlp, HuggingFace). Admite http://, https://, calcetines5://. Se requiere reinicio si se cambia después del inicio del backend.",

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Keep protocol literal socks5:// in proxy description.

The scheme is translated to calcetines5://, which is not a valid proxy URI scheme.

Proposed fix
-    "proxy_desc": "Proxy HTTP/SOCKS5 para descargas (yt-dlp, HuggingFace). Admite http://, https://, calcetines5://. Se requiere reinicio si se cambia después del inicio del backend.",
+    "proxy_desc": "Proxy HTTP/SOCKS5 para descargas (yt-dlp, HuggingFace). Admite http://, https://, socks5://. Se requiere reinicio si se cambia después del inicio del backend.",
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@frontend/src/i18n/locales/es.json` at line 30, The Spanish translation for
the "proxy_desc" JSON key incorrectly localizes the protocol scheme to
"calcetines5://" making the example proxy URI invalid; update the value of
"proxy_desc" so the protocol literal remains "socks5://" (i.e., keep "http://,
https://, socks5://") instead of the translated form, preserving the literal URI
schemes in the string.

"title": "Paramètres",
"ui_scale": "Échelle de l'interface utilisateur",
"proxy": "Procuration",
"proxy_desc": "Proxy HTTP/SOCKS5 pour les téléchargements (yt-dlp, HuggingFace). Prend en charge http://, https://, chaussettes5://. Redémarrage requis en cas de modification après le démarrage du backend.",

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Do not localize URI schemes in proxy help text.

chaussettes5:// is invalid; this must stay socks5://.

Proposed fix
-    "proxy_desc": "Proxy HTTP/SOCKS5 pour les téléchargements (yt-dlp, HuggingFace). Prend en charge http://, https://, chaussettes5://. Redémarrage requis en cas de modification après le démarrage du backend.",
+    "proxy_desc": "Proxy HTTP/SOCKS5 pour les téléchargements (yt-dlp, HuggingFace). Prend en charge http://, https://, socks5://. Redémarrage requis en cas de modification après le démarrage du backend.",
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
"proxy_desc": "Proxy HTTP/SOCKS5 pour les téléchargements (yt-dlp, HuggingFace). Prend en charge http://, https://, chaussettes5://. Redémarrage requis en cas de modification après le démarrage du backend.",
"proxy_desc": "Proxy HTTP/SOCKS5 pour les téléchargements (yt-dlp, HuggingFace). Prend en charge http://, https://, socks5://. Redémarrage requis en cas de modification après le démarrage du backend.",
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@frontend/src/i18n/locales/fr.json` at line 30, The French translation for the
proxy help text localized the URI scheme "socks5://" as "chaussettes5://", which
is invalid; update the "proxy_desc" value to keep URI schemes untranslated
(http://, https://, socks5://) by replacing "chaussettes5://" with "socks5://",
ensuring the rest of the sentence remains French but all URI schemes remain in
their original form.

"deepl_key": "डीपएल एपीआई कुंजी",
"deepl_help": "डीपएल अनुवाद इंजन के लिए। अपनी कुंजी Deepl.com/pro-api पर प्राप्त करें।",
"deepl_base_url": "डीपएल बेस यूआरएल",
"deepl_base_url_help": "कस्टम डीपएल एपीआई एंडपॉइंट (डिफ़ॉल्ट: https://api.depl.com/v2)। प्रॉक्सी/स्वयं-होस्टेड के लिए परिवर्तन।",

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Fix incorrect default DeepL endpoint in helper text.

The URL uses api.depl.com, but the correct default is api.deepl.com.

Proposed fix
-    "deepl_base_url_help": "कस्टम डीपएल एपीआई एंडपॉइंट (डिफ़ॉल्ट: https://api.depl.com/v2)। प्रॉक्सी/स्वयं-होस्टेड के लिए परिवर्तन।",
+    "deepl_base_url_help": "कस्टम डीपएल एपीआई एंडपॉइंट (डिफ़ॉल्ट: https://api.deepl.com/v2)। प्रॉक्सी/स्वयं-होस्टेड के लिए परिवर्तन।",
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@frontend/src/i18n/locales/hi.json` at line 305, The helper text for the DeepL
base URL (key "deepl_base_url_help") contains a typo in the default endpoint;
update the string value to use the correct domain "https://api.deepl.com/v2"
instead of "https://api.depl.com/v2" so the displayed default DeepL API endpoint
is accurate.

"addChapter": "Thêm chương",
"chapterN": "Chương {{n}}",
"stems": "thân cây",
"stemsDone": "Đã xuất _V_0__ gốc ký tự",

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical | ⚡ Quick win

Critical: Corrupted interpolation placeholders in Vietnamese locale

Multiple translation strings contain _V_0__ instead of the correct i18next placeholder syntax. These will render literally as "V_0_" text instead of interpolating the actual values, breaking the UI for Vietnamese users.

Affected lines and required fixes:

  • Line 88: _V_0__{{count}}
  • Line 361: _V_0__{{message}}
  • Line 511: _V_0__{{engine}}
  • Line 531: _V_0__{{count}}
  • Line 674: _V_0__{{duration}}

Example:
Current (line 88):

"stemsDone": "Đã xuất _V_0__ gốc ký tự"

Should be:

"stemsDone": "Đã xuất {{count}} gốc ký tự"

This appears to be a batch translation tool artifact that corrupted the placeholder syntax during processing.

Also applies to: 361-361, 511-511, 531-531, 674-674

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@frontend/src/i18n/locales/vi.json` at line 88, Several Vietnamese translation
entries use the corrupted placeholder `_V_0__` which will render literally;
replace them with the correct i18next interpolation tokens: change the value for
"stemsDone" to use {{count}}, the key at line ~361 to use {{message}}, the key
at ~511 to use {{engine}}, the key at ~531 to use {{count}}, and the key at ~674
to use {{duration}}; locate each JSON property (e.g. "stemsDone") and update its
string to use the matching {{...}} placeholder so i18next can interpolate
properly.

"sidebar_toggle": "切換側邊欄",
"retry_transcription": "重試轉錄",
"supported_formats": "MP4·MOV·MKV·WEBM·MP3·WAV·FLAC·M4A",
"pull_captions_title": "当 URL 是带有字幕的主机(YouTube、Vimeo、TED...)时,还要提取原始字幕和任何 YouTube 自动翻译。在不运行 Whisper 的情况下为编辑器播种;对于 YouTube 已涵盖的语言,请跳过“全部翻译”。",

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Major: Simplified Chinese characters in Traditional Chinese locale

The zh-TW.json file (Traditional Chinese) contains multiple strings using Simplified Chinese characters instead of Traditional. This breaks character set consistency and will appear incorrect to Traditional Chinese users.

Affected examples:

Line 604:

"desc": "音频处理、格式转换和实用程序"
  • 音频 (simplified) should be 音訊 or 音頻 (traditional)
  • 实用程序 (simplified) should be 實用程式 (traditional)

Line 450:
Contains multiple simplified characters: , , , , 运行,
Should use traditional equivalents: , , , , 運行,

Line 617:

"speech_rate_desc": "检查翻译后的线路与其时隙的比较。"
  • 检查 should be 檢查
  • should be

Line 628:

"probe_placeholder": "/用户/你/电影/sample.mp4"
  • 用户 should be 使用者
  • 电影 should be 電影

These strings need to be re-translated using proper Traditional Chinese characters to maintain locale consistency.

Also applies to: 604-604, 617-617, 628-628

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@frontend/src/i18n/locales/zh-TW.json` at line 450, The zh-TW locale contains
Simplified Chinese characters; update the affected JSON values to Traditional
Chinese for consistent locale display—specifically change the
"pull_captions_title" string replacing 当→當, 带→帶, 还→還, 为→為, 运行→運行, 对→對 (and any
other simplified tokens in that value); change "desc" value replacing 音频→音訊 or
音頻 and 实用程序→實用程式; change "speech_rate_desc" replacing 检查→檢查 and 与→與; and change
"probe_placeholder" replacing 用户→使用者 and 电影→電影; ensure each JSON value uses
proper Traditional Chinese phrasing and punctuation while preserving the
existing keys and structure.

Comment thread scripts/translate_all.py
import json
import re
import time
from deep_translator import GoogleTranslator

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Check if the script is referenced in any user-facing documentation or UI

rg -n -C3 "translate_all\.py" --type=md --type=rst --type=txt

Repository: debpalash/OmniVoice-Studio

Length of output: 52


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# 1) Inspect the script to see whether/when network calls happen
echo "=== scripts/translate_all.py (first 200 lines) ==="
wc -l scripts/translate_all.py
sed -n '1,200p' scripts/translate_all.py
echo
echo "=== scripts/translate_all.py (last 120 lines) ==="
tail -n 120 scripts/translate_all.py

# 2) Find where translate_all.py is referenced
echo
echo "=== References to translate_all.py across repo ==="
rg -n --hidden --no-ignore-vcs "translate_all\.py" .

# 3) Find where GoogleTranslator/deep_translator is used
echo
echo "=== Usages of GoogleTranslator / deep_translator ==="
rg -n "GoogleTranslator|deep_translator" .

# 4) Look for any mention of this script in packaging/CI-like files
echo
echo "=== References in workflow/config files ==="
rg -n --hidden --no-ignore-vcs "translate_all|scripts/translate_all\.py" .github . || true

Repository: debpalash/OmniVoice-Studio

Length of output: 12004


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "=== Search for translate_all.py references (all file types) ==="
rg -n --hidden --no-ignore-vcs "translate_all\.py|scripts/translate_all\.py|translate_all" . || true

echo
echo "=== Search for deep_translator / GoogleTranslator usage ==="
rg -n --hidden --no-ignore-vcs "deep_translator|GoogleTranslator" . || true

echo
echo "=== List scripts/ directory (quick sanity) ==="
ls -la scripts || true

echo
echo "=== Check for script usage in common config/workflow/build files ==="
rg -n --hidden --no-ignore-vcs "translate_all\.py|translate_all" package.json pyproject.toml requirements*.txt setup*.py .github/workflows . || true

Repository: debpalash/OmniVoice-Studio

Length of output: 10655


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "=== scripts/translate_all.py: show LOCALES_DIR + translator usage ==="
rg -n "LOCALES_DIR|GoogleTranslator|translate\(" scripts/translate_all.py
echo
sed -n '1,40p' scripts/translate_all.py
echo
sed -n '90,170p' scripts/translate_all.py

echo
echo "=== backend/services/translation_engines.py ==="
sed -n '1,130p' backend/services/translation_engines.py

echo
echo "=== frontend/src/pages/DubTab.jsx around translate_all button(s) ==="
# Print around first occurrences from earlier search results
for line in 500 720 860; do
  echo "--- Around line ~$line ---"
  sed -n "${line},$((line+80))p" frontend/src/pages/DubTab.jsx
done

echo
echo "=== backend/api/routers for dub_translate/batch: find where GoogleTranslator/deep_translator is used ==="
rg -n "GoogleTranslator|deep_translator|translate_all" backend/api/routers/dub_translate.py backend/api/routers/batch.py frontend/src/pages/DubTab.jsx || true

echo
echo "=== backend/api/routers/dub_translate.py: show GoogleTranslator block ==="
rg -n "from deep_translator import GoogleTranslator|return GoogleTranslator" backend/api/routers/dub_translate.py
sed -n '330,430p' backend/api/routers/dub_translate.py

echo
echo "=== backend/api/routers/batch.py: show GoogleTranslator usage ==="
rg -n "GoogleTranslator" backend/api/routers/batch.py
sed -n '160,260p' backend/api/routers/batch.py

Repository: debpalash/OmniVoice-Studio

Length of output: 35369


Gate Google Translate network access (and remove absolute home path) in scripts/translate_all.py

  • scripts/translate_all.py imports GoogleTranslator and unconditionally calls translator.translate(...) for missing i18n strings, creating outbound requests to Google Translate via deep_translator with no explicit opt-in flag/env guard.
  • LOCALES_DIR is hardcoded to /Users/user4/... (absolute user home path), violating portability guidelines.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@scripts/translate_all.py` at line 5, scripts/translate_all.py currently
unconditionally imports and calls GoogleTranslator.translator.translate (causing
outbound network requests) and uses a hardcoded absolute LOCALES_DIR; fix by
gating any external-API usage behind an explicit opt-in env flag (e.g.,
ENABLE_GOOGLE_TRANSLATE) or CLI flag so that GoogleTranslator is only imported
and translator.translate invoked when that flag is true, performing the import
lazily inside the guarded branch and wrapping calls in try/except with a clear
log on failure; also remove the absolute path by computing LOCALES_DIR relative
to the repository (use pathlib and __file__ to build a path) or read it from an
environment variable (e.g., LOCALES_DIR) so the script is portable across
machines.

Comment thread scripts/translate_all.py
import time
from deep_translator import GoogleTranslator

LOCALES_DIR = "/Users/user4/orca/workspaces/OmniVoice/translation/frontend/src/i18n/locales"

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical | ⚡ Quick win

Remove hardcoded absolute user home path.

The path /Users/user4/orca/workspaces/OmniVoice/translation/frontend/src/i18n/locales contains an absolute user home path, which violates the coding guidelines. As per coding guidelines, code must not persist or log absolute user home paths like /Users/<name>/ or C:\Users\<name>\.

🔧 Proposed fix

Use a relative path from the repository root:

-LOCALES_DIR = "/Users/user4/orca/workspaces/OmniVoice/translation/frontend/src/i18n/locales"
+LOCALES_DIR = os.path.join(os.path.dirname(__file__), "..", "frontend", "src", "i18n", "locales")

Or use a path relative to the script's location:

-LOCALES_DIR = "/Users/user4/orca/workspaces/OmniVoice/translation/frontend/src/i18n/locales"
+SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__))
+LOCALES_DIR = os.path.join(SCRIPT_DIR, "..", "frontend", "src", "i18n", "locales")
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
LOCALES_DIR = "/Users/user4/orca/workspaces/OmniVoice/translation/frontend/src/i18n/locales"
LOCALES_DIR = os.path.join(os.path.dirname(__file__), "..", "frontend", "src", "i18n", "locales")
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@scripts/translate_all.py` at line 7, LOCALES_DIR is set to a hardcoded
absolute user home path; change it to a repository-relative or script-relative
path instead (e.g., build LOCALES_DIR using
pathlib.Path(__file__).resolve().parent /
"relative/path/to/frontend/src/i18n/locales" or use a path from the repo root)
so the script no longer contains /Users/user4/...; update the LOCALES_DIR
assignment to compute the path at runtime and ensure any downstream uses of
LOCALES_DIR continue to work with the new Path object.

Comment thread scripts/translate_all.py
Comment on lines +151 to +156
for k, val, (vars_found, tags_found) in zip(batch_keys, batch_values, masks_metadata):
try:
masked, v_f, t_f = mask_text(val)
trans_val = translator.translate(masked)
final_val = unmask_text(trans_val, v_f, t_f)
set_nested_value(lang_data, k, final_val)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion | 🟠 Major | ⚡ Quick win

Remove redundant masking and unused loop variables.

Lines 151-153 unpack (vars_found, tags_found) from masks_metadata but never use them. Instead, line 153 immediately re-calls mask_text(val), duplicating the work already done on lines 122-125. This is inefficient and confusing.

♻️ Proposed fix
             if not success:
                 # Fallback to translating one-by-one for this batch
-                for k, val, (vars_found, tags_found) in zip(batch_keys, batch_values, masks_metadata):
+                for k, masked_val, (vars_found, tags_found) in zip(batch_keys, masked_values, masks_metadata, strict=True):
                     try:
-                        masked, v_f, t_f = mask_text(val)
-                        trans_val = translator.translate(masked)
-                        final_val = unmask_text(trans_val, v_f, t_f)
+                        trans_val = translator.translate(masked_val)
+                        final_val = unmask_text(trans_val, vars_found, tags_found)
                         set_nested_value(lang_data, k, final_val)
                         time.sleep(0.05)
                     except Exception as ie:
                         print(f"      Individual error for key {k}: {ie}", flush=True)
-                        set_nested_value(lang_data, k, val) # Fallback to original English
+                        set_nested_value(lang_data, k, batch_values[batch_keys.index(k)]) # Fallback to original English

Note: Also added strict=True to zip() for safety.

🧰 Tools
🪛 Ruff (0.15.14)

[warning] 151-151: Loop control variable vars_found not used within loop body

(B007)


[warning] 151-151: Loop control variable tags_found not used within loop body

(B007)


[warning] 151-151: zip() without an explicit strict= parameter

Add explicit value for parameter strict=

(B905)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@scripts/translate_all.py` around lines 151 - 156, The loop is redundantly
calling mask_text(val) and unpacking unused (vars_found, tags_found) from
masks_metadata; change the for-loop over batch_keys, batch_values,
masks_metadata to accept the already-computed masks (e.g., for k, val,
(vars_found, tags_found) in zip(batch_keys, batch_values, masks_metadata,
strict=True)): remove the extra call to mask_text(val) and instead use the
existing vars_found and tags_found when calling unmask_text after
translator.translate, and if any unpacked names are unused replace them with _
to avoid confusion; ensure you keep set_nested_value(lang_data, k, final_val)
and add strict=True to zip() for safety.

@debpalash
debpalash merged commit 52d7321 into main May 31, 2026
15 checks passed
@debpalash
debpalash deleted the debpalash/translation branch May 31, 2026 05:38
debpalash added a commit that referenced this pull request May 31, 2026
…202)

PR #200 added 18 new locale files, but they predated #199 (auto-update badge +
Stable/Preview channel toggle), so they were missing the `update.*` namespace
(6 keys) and `about.channel_*` (5 keys) — those strings fell back to English in
ar/de/es/fr/hi/id/it/ja/ko/nl/pl/pt/ru/sv/th/tr/uk/vi/zh-TW.

Backfill all 11 keys in every one of those languages so the updater UI is fully
localized. en.json / zh-CN.json already had them and are untouched. Placeholders
({{version}}, {{pct}}, {{channel}}) preserved verbatim; files re-emitted in the
exact format scripts/translate_all.py writes (ensure_ascii=False, indent=2) so
the diff is additions only (+13 lines/file, 0 deletions).

Also fix scripts/translate_all.py: LOCALES_DIR was hardcoded to a contributor's
absolute path (/Users/.../orca/...) — make it repo-relative so the generator
actually runs for anyone.

Verified: all 21 locales valid JSON + key-complete, placeholders intact;
tsc clean; vitest 162/162; build OK; CJK guard passes (locales are the
allowlisted translation layer).

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.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.

1 participant