Skip to content

feat: add Russian translation for Live Mode UI#317

Open
Tom-Opencart wants to merge 3 commits into
pbakaus:mainfrom
Tom-Opencart:feat/russian-translation
Open

feat: add Russian translation for Live Mode UI#317
Tom-Opencart wants to merge 3 commits into
pbakaus:mainfrom
Tom-Opencart:feat/russian-translation

Conversation

@Tom-Opencart

@Tom-Opencart Tom-Opencart commented Jun 27, 2026

Copy link
Copy Markdown

Summary

  • Add skill/i18n/ directory for UI translations
  • Add en.json as base reference with all translatable strings
  • Add ru.json with complete Russian translation (54 strings)
  • Add README.md with usage instructions

Changes

This PR adds internationalization support for the Impeccable Live Mode UI panel. The Russian translation covers all UI elements including:

  • Picker bar buttons (Pick element, Accept, Discard, etc.)
  • Design command palette (Freeform, Bolder, Quieter, etc.)
  • Status messages (Variant applied, Applying variant..., etc.)
  • Annotation tools (Save, Cancel, Clear, etc.)
  • Voice input controls
  • DESIGN.md panel

Usage

Users can now copy skill/i18n/ru.json to their project root as live_translations.json to get a fully localized Live Mode experience.

Testing

Verified that all 54 translation keys match the strings used in live-browser.js.


Note

Low Risk
Additive, opt-in JSON loading with empty-object and key fallback; no auth or data-path changes.

Overview
Adds optional i18n for Impeccable Live Mode: projects can place live_translations.json at the repo root (documented under skill/i18n/), and the live server reads it when serving /live.js.

The assembled browser prelude now injects window.__IMPECCABLE_TRANSLATIONS__ and window.__IMPECCABLE_T__(key) (translate or fall back to the English key). Shipped catalogs include en.json as the key reference and ru.json with a full Russian UI pass (~60 strings: picker, commands, status copy, etc.).

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

- Add skill/i18n/ directory for translations
- Add en.json as base reference
- Add ru.json with complete Russian translation
- Add README with usage instructions
@Tom-Opencart Tom-Opencart requested a review from pbakaus as a code owner June 27, 2026 15:26
Comment thread skill/i18n/en.json

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: a84afcb9a1

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread skill/i18n/README.md
## Usage

1. Copy the desired translation file (e.g., `ru.json`) to your project root as `live_translations.json`
2. The Live Mode server will automatically load translations from this file

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Wire translations into live mode

When users copy ru.json as instructed, nothing consumes it: /live.js assembly in skill/scripts/live-server.mjs only injects token/port/vocabulary and concatenates the browser script parts, and repo-wide search for live_translations only hits this README. Since the new JSON files are never read or sent to live-browser.js, the Russian locale remains a no-op and Live Mode stays English.

Useful? React with 👍 / 👎.

@greptile-apps

greptile-apps Bot commented Jun 27, 2026

Copy link
Copy Markdown

Greptile Summary

This PR wires up optional i18n support for the Live Mode in-browser UI. Server-side, loadTranslations() reads live_translations.json from process.cwd() on each /live.js request (gracefully degrading to {} when absent or malformed). Browser-side, assembleLiveBrowserScript now injects window.__IMPECCABLE_TRANSLATIONS__ and a window.__IMPECCABLE_T__(key) helper into the script prelude.

  • New skill/i18n/ directory adds en.json (53-key English reference), ru.json (complete Russian translation), and a usage README describing the copy-to-project-root workflow.
  • live-server.mjs gains loadTranslations() — synchronous disk read on each /live.js request, matching the existing pattern used for script parts; errors are caught and logged as warnings.
  • browser-script-parts.mjs extends assembleLiveBrowserScript to accept and inject translations using JSON.stringify, consistent with how __IMPECCABLE_VOCAB__ is already injected.

Confidence Score: 5/5

Safe to merge — all changes are additive and isolated to dev-server infrastructure; the existing UI is unaffected, and missing or malformed translation files degrade gracefully to no-op.

The server-side loading and browser-side injection code is correct, well-bounded, and consistent with how IMPECCABLE_VOCAB is already handled. Translation loading fails safely with a console warning. No existing behaviour is altered.

skill/i18n/ru.json — singular/plural distinction between "Apply copy edit" and "Apply copy edits" is collapsed to the plural Russian form.

Important Files Changed

Filename Overview
skill/scripts/live-server.mjs Adds loadTranslations() that synchronously reads live_translations.json from process.cwd() on each /live.js request; error/missing-file handled gracefully; result forwarded to assembleLiveBrowserScript.
skill/scripts/live/browser-script-parts.mjs Accepts new translations parameter and injects window.IMPECCABLE_TRANSLATIONS and window.IMPECCABLE_T helper into the script prelude using JSON.stringify, consistent with the existing vocabulary injection pattern.
skill/i18n/en.json English reference file with 53 key-value pairs (identity mappings) covering Live Mode UI strings; serves as the canonical key set for translators.
skill/i18n/ru.json Russian translation with 53 entries; "Apply copy edit" and "Apply copy edits" both map to the same Russian string, losing the singular/plural distinction present in the English source.
skill/i18n/README.md Usage and contributing guide for the new i18n directory; describes copy-to-project-root workflow and translation format.

Sequence Diagram

%%{init: {'theme': 'neutral'}}%%
sequenceDiagram
    participant User as User (Browser)
    participant Server as live-server.mjs
    participant FS as Filesystem
    participant Assembler as browser-script-parts.mjs
    participant Window as window (Browser Global)

    User->>Server: GET /live.js
    Server->>FS: readLiveBrowserScriptParts()
    FS-->>Server: live-browser.js + parts
    Server->>FS: loadTranslations() → live_translations.json
    FS-->>Server: "translations {} (or {} if missing/invalid)"
    Server->>Assembler: "assembleLiveBrowserScript({ token, port, vocabulary, translations, parts })"
    Assembler-->>Server: prelude + body JS string
    Server-->>User: application/javascript response
    User->>Window: "window.__IMPECCABLE_TRANSLATIONS__ = { ... }"
    User->>Window: "window.__IMPECCABLE_T__ = function(key) { ... }"
Loading
%%{init: {'theme': 'base', 'themeVariables': {"darkMode": true, "background": "#0d1117", "primaryColor": "#21262d", "primaryTextColor": "#e6edf3", "primaryBorderColor": "#8b949e", "lineColor": "#8b949e", "textColor": "#e6edf3", "edgeLabelBackground": "#161b22", "actorBkg": "#21262d", "actorBorder": "#8b949e", "actorTextColor": "#e6edf3", "actorLineColor": "#8b949e", "signalColor": "#8b949e", "signalTextColor": "#e6edf3", "noteBkgColor": "#373320", "noteBorderColor": "#d4a72c", "noteTextColor": "#f0e6c0", "labelBoxBkgColor": "#21262d", "labelBoxBorderColor": "#8b949e", "labelTextColor": "#e6edf3", "loopTextColor": "#e6edf3", "activationBkgColor": "#30363d", "activationBorderColor": "#8b949e"}}}%%
sequenceDiagram
    participant User as User (Browser)
    participant Server as live-server.mjs
    participant FS as Filesystem
    participant Assembler as browser-script-parts.mjs
    participant Window as window (Browser Global)

    User->>Server: GET /live.js
    Server->>FS: readLiveBrowserScriptParts()
    FS-->>Server: live-browser.js + parts
    Server->>FS: loadTranslations() → live_translations.json
    FS-->>Server: "translations {} (or {} if missing/invalid)"
    Server->>Assembler: "assembleLiveBrowserScript({ token, port, vocabulary, translations, parts })"
    Assembler-->>Server: prelude + body JS string
    Server-->>User: application/javascript response
    User->>Window: "window.__IMPECCABLE_TRANSLATIONS__ = { ... }"
    User->>Window: "window.__IMPECCABLE_T__ = function(key) { ... }"
Loading

Reviews (3): Last reviewed commit: "fix: add missing translation strings for..." | Re-trigger Greptile

Comment thread skill/i18n/README.md
Comment on lines +7 to +8
1. Copy the desired translation file (e.g., `ru.json`) to your project root as `live_translations.json`
2. The Live Mode server will automatically load translations from this file

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 No translation-loading mechanism exists in the codebase

The README states "The Live Mode server will automatically load translations from live_translations.json," but no such loading code exists. Searches across live-browser.js, live-server.mjs, and live-inject.mjs find zero references to live_translations, translations, or any i18n dispatch. The UI strings (e.g., 'Applying variant...', ariaLabel: 'Pick element') are plain string literals hardcoded in live-browser.js. Until an implementation is added to read live_translations.json and substitute those literals at runtime, copying ru.json to the project root has no effect whatsoever.

Fix in Codex Fix in Claude Code

Comment thread skill/i18n/en.json
Comment on lines +1 to +55
{
"Pick element": "Pick element",
"Generate variants": "Generate variants",
"Create variants": "Create variants",
"Steer the page": "Steer the page",
"Steer": "Steer",
"Accept": "Accept",
"Discard": "Discard",
"Discard all variants": "Discard all variants",
"Done": "Done",
"Cancel": "Cancel",
"Clear": "Clear",
"Apply": "Apply",
"Applying ": "Applying ",
"Apply copy edits": "Apply copy edits",
"Saved. Click ": "Saved. Click ",
"Toggle DESIGN.md panel": "Toggle DESIGN.md panel",
"Edit copy": "Edit copy",
"Detect anti-patterns": "Detect anti-patterns",
"Voice input": "Voice input",
"Stop voice input": "Stop voice input",
"Impeccable live mode": "Impeccable live mode",
"Selected element: ": "Selected element: ",
"Clear selection": "Clear selection",
"Variant applied": "Variant applied",
"Exit live mode": "Exit live mode",
"No detector issues found.": "No detector issues found.",
"Describe the change": "Describe the change",
"Describe the new element": "Describe the new element",
"Insert new element": "Insert new element",
"Save": "Save",
"Insert": "Insert",
"Pick": "Pick",
"Tune": "Tune",
"Applying variant...": "Applying variant...",
"Keep fixing": "Keep fixing",
"Note…": "Note…",
"apply is running...": "apply is running...",
"Resize placeholder": "Resize placeholder",
"Close panel": "Close panel",
"Variants ready. If the picked element isn't visible, retrace the path that revealed it - they'll appear automatically.": "Variants ready. If the picked element isn't visible, retrace the path that revealed it - they'll appear automatically.",
"Do's and Don'ts": "Do's and Don'ts",
"Freeform": "Freeform",
"Bolder": "Bolder",
"Quieter": "Quieter",
"Distill": "Distill",
"Polish": "Polish",
"Typeset": "Typeset",
"Colorize": "Colorize",
"Layout": "Layout",
"Adapt": "Adapt",
"Animate": "Animate",
"Delight": "Delight",
"Overdrive": "Overdrive"
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 String count in PR description is incorrect

The PR description states "54 strings," but both en.json and ru.json contain 53 key-value pairs. This is a minor discrepancy, but it suggests the files were not carefully verified before submission.

Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!

Fix in Codex Fix in Claude Code

Comment thread skill/i18n/en.json
Comment on lines +13 to +15
"Apply": "Apply",
"Applying ": "Applying ",
"Apply copy edits": "Apply copy edits",

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Trailing-space keys are a fragile pattern for any future implementation

Three keys — "Applying ", "Saved. Click ", and "Selected element: " — have trailing spaces, indicating they are partial strings meant to be concatenated with dynamic content at runtime. A translation system that does a simple key lookup on the full UI string would need to reconstruct those dynamic parts after the translated prefix, which isn't documented anywhere. Any future implementation will need explicit handling for these partial-string keys, or the approach needs to change (e.g., using a placeholder like "Applying {{name}}").

Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!

Fix in Codex Fix in Claude Code

- Add loadTranslations() function to read live_translations.json from project root
- Add translations parameter to assembleLiveBrowserScript()
- Inject window.__IMPECCABLE_TRANSLATIONS__ into browser script prelude
- Add window.__IMPECCABLE_T__() helper function for string translation
- Translations are now loaded and available in the browser UI

@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.

There are 2 total unresolved issues (including 1 from previous review).

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 cc5c5c5. Configure here.

// UI translations for i18n support
`window.__IMPECCABLE_TRANSLATIONS__ = ${JSON.stringify(translations || {})};\n` +
// Translation helper: returns translated string or falls back to key
`window.__IMPECCABLE_T__ = function(key) { return (window.__IMPECCABLE_TRANSLATIONS__ && window.__IMPECCABLE_TRANSLATIONS__[key]) || key; };\n`;

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Translations never reach live UI

High Severity

This change loads live_translations.json, injects window.__IMPECCABLE_TRANSLATIONS__, and defines window.__IMPECCABLE_T__, but none of the assembled live browser script parts call that helper or read those translations. Copying ru.json therefore leaves the Live Mode UI in English despite the PR’s localized UI goal.

Additional Locations (1)
Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit cc5c5c5. Configure here.

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: cc5c5c515e

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +43 to +45
`window.__IMPECCABLE_TRANSLATIONS__ = ${JSON.stringify(translations || {})};\n` +
// Translation helper: returns translated string or falls back to key
`window.__IMPECCABLE_T__ = function(key) { return (window.__IMPECCABLE_TRANSLATIONS__ && window.__IMPECCABLE_TRANSLATIONS__[key]) || key; };\n`;

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Route UI strings through the translation helper

With live_translations.json present, /live.js now emits the translations and helper here, but the browser UI never calls it: repo-wide search for __IMPECCABLE_T__ only finds this prelude, while skill/scripts/live-browser.js still assigns hard-coded labels/status text and command labels from LIVE_COMMANDS. As a result copying ru.json still leaves Live Mode in English. Fresh evidence after the prior review is that the helper was added, but it has zero call sites; the UI strings need to be wrapped at render time.

Useful? React with 👍 / 👎.

@github-actions github-actions Bot added blocked: ci Latest commit has failing required checks blocked: review threads Unresolved review feedback or requested changes remain stale Inactive PR that may be closed soon waiting on contributor Waiting for the PR author to respond or make changes blocked: merge conflicts PR cannot merge until conflicts are resolved labels Jul 9, 2026
Repository owner deleted a comment from github-actions Bot Jul 10, 2026
@pbakaus pbakaus removed the stale Inactive PR that may be closed soon label Jul 10, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

blocked: ci Latest commit has failing required checks blocked: merge conflicts PR cannot merge until conflicts are resolved blocked: review threads Unresolved review feedback or requested changes remain waiting on contributor Waiting for the PR author to respond or make changes

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants