Skip to content

Add Russian localization#546

Open
psychosomat wants to merge 2 commits intosiddharthvaddem:mainfrom
psychosomat:feature/add-russian-localization
Open

Add Russian localization#546
psychosomat wants to merge 2 commits intosiddharthvaddem:mainfrom
psychosomat:feature/add-russian-localization

Conversation

@psychosomat
Copy link
Copy Markdown
Contributor

@psychosomat psychosomat commented May 6, 2026

Pull Request Template

Description

This PR adds Russian localization support to OpenScreen.

It introduces Russian translation files for the existing i18n namespaces and registers ru as a supported locale in the i18n configuration. It also updates the tutorial help translation test coverage to include the new Russian dialog translations.

Motivation

Russian-speaking users should be able to use OpenScreen in their native language. Adding Russian localization improves accessibility and makes the application more usable for a wider audience.

Type of Change

  • New Feature
  • Bug Fix
  • Refactor / Code Cleanup
  • Documentation Update
  • Other (please specify)

Testing

  • Added Russian dialog translations to the tutorial help translation coverage.
  • Verified that ru is included in the supported locale list.

Checklist

  • I have performed a self-review of my code.
  • I have added any necessary screenshots or videos.
  • I have linked related issue(s) and updated the changelog if applicable.

Summary by CodeRabbit

  • New Features
    • Added Russian language support across the app: translations for common UI actions and playback controls, dialogs and prompts, editor interface, launch/recording screens, settings, keyboard shortcuts, and timeline features.
    • Russian locale is now included in the app’s supported languages, enabling Russian UI for users.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 6, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 7a46b875-1659-4340-9d8e-1882a812a1a5

📥 Commits

Reviewing files that changed from the base of the PR and between 6130c66 and 9336e3d.

📒 Files selected for processing (2)
  • src/i18n/__tests__/tutorialHelpTranslations.test.ts
  • src/i18n/locales/ru/editor.json
✅ Files skipped from review due to trivial changes (1)
  • src/i18n/locales/ru/editor.json

📝 Walkthrough

Walkthrough

Russian locale support added: SUPPORTED_LOCALES updated, seven new src/i18n/locales/ru/*.json translation files added, and tests updated to include Russian dialogs in validation.

Changes

Russian Localization Support

Layer / File(s) Summary
Configuration
src/i18n/config.ts
Added "ru" to SUPPORTED_LOCALES.
Translation resources (data shape)
src/i18n/locales/ru/common.json, .../dialogs.json, .../editor.json, .../launch.json, .../settings.json, .../shortcuts.json, .../timeline.json
Seven new Russian locale JSON files added containing translated strings for actions, dialogs, editor, launch UI, settings, shortcuts, and timeline.
Tests / Validation
src/i18n/__tests__/tutorialHelpTranslations.test.ts
Imported ru/dialogs.json and added ru to dialogsByLocale so the tutorial-help translations test covers Russian.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

Possibly related PRs

Suggested reviewers

  • siddharthvaddem
  • FabLrc

Poem

at 2am the app learns to say "привет",
seven tiny jsons whisper in unicode,
config flips a switch, tests nod along —
translations deployed, lowkey proud and slightly cursed.

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed Title clearly and concisely describes the main change: adding Russian localization support across multiple i18n files and configuration.
Description check ✅ Passed Description covers all required template sections with clear motivation, change type, and testing details, though no screenshots are included (not critical for localization).
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
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.


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.

Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

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: 6130c66be6

ℹ️ 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".

"message": "У вас есть несохранённые изменения.",
"detail": "Хотите сохранить проект перед закрытием?",
"saveAndClose": "Сохранить и закрыть",
"discardAndClose": "Отменить и закрыть",
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 Badge Correct misleading discard action label in Russian dialog

dialogs.unsavedChanges.discardAndClose is translated as "Отменить и закрыть" (“Cancel and close”), but this label is bound to the destructive discard changes and close path in the close-confirmation flow (electron/main.ts, createEditorWindowWrapper, choice index 1). In the Russian UI, this can mislead users into clicking what looks like cancel and unintentionally losing unsaved work.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

disagree with that interpretation

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 3

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/i18n/__tests__/tutorialHelpTranslations.test.ts (1)

36-44: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

kinda risky: dialogsByLocale is missing zh-TW, ja-JP, and ar — test will TypeError for those locales.

SUPPORTED_LOCALES has 10 entries but dialogsByLocale only covers 7. Since Locale is typed as string, the satisfies Record<Locale, ...> constraint doesn't actually catch missing keys at compile time—TypeScript happily types every access as non-nullable, so the crash only surfaces at runtime when those locales are accessed. All three dialogs.json files already exist in the repo, so this is a straightforward fix.

🔧 Proposed fix — import and register the three missing locales
 import zhCNDialogs from "@/i18n/locales/zh-CN/dialogs.json";
+import arDialogs from "@/i18n/locales/ar/dialogs.json";
+import jaJPDialogs from "@/i18n/locales/ja-JP/dialogs.json";
+import zhTWDialogs from "@/i18n/locales/zh-TW/dialogs.json";
 const dialogsByLocale = {
 	en: enDialogs,
 	"zh-CN": zhCNDialogs,
+	"zh-TW": zhTWDialogs,
 	es: esDialogs,
 	fr: frDialogs,
 	tr: trDialogs,
 	"ko-KR": koKRDialogs,
+	"ja-JP": jaJPDialogs,
+	ar: arDialogs,
 	ru: ruDialogs,
 } satisfies Record<Locale, { tutorial: Record<string, unknown> }>;
🤖 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 `@src/i18n/__tests__/tutorialHelpTranslations.test.ts` around lines 36 - 44,
dialogsByLocale currently maps only seven locales and is missing ja-JP, zh-TW,
and ar which causes runtime TypeError when tests iterate SUPPORTED_LOCALES;
import the missing dialog modules (e.g., jaJPDialogs, zhTWDialogs, arDialogs)
and add entries "ja-JP": jaJPDialogs, "zh-TW": zhTWDialogs, and ar: arDialogs to
the dialogsByLocale object so it covers all SUPPORTED_LOCALES while keeping the
satisfies Record<Locale, { tutorial: Record<string, unknown> }> assertion.
🤖 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 `@src/i18n/__tests__/tutorialHelpTranslations.test.ts`:
- Line 9: Import ordering is incorrect: move the ruDialogs import (import
ruDialogs from "@/i18n/locales/ru/dialogs.json") so it is alphabetically between
koKRDialogs and trDialogs (i.e., koKRDialogs, ruDialogs, trDialogs, zh-CN...),
or simply run the project's organizeImports autofix; ensure ruDialogs is
positioned accordingly among the other locale imports in
tutorialHelpTranslations.test.ts.

In `@src/i18n/locales/ru/editor.json`:
- Line 38: The Russian string for the key "systemAudioUnavailable" uses
masculine agreement; change the message to use neuter agreement to match the
indeclinable neuter noun "аудио" — update the value of systemAudioUnavailable to
a neuter form such as "Системное аудио недоступно. Запись без системного аудио."
so both clauses use correct neuter agreement.

In `@src/i18n/locales/ru/timeline.json`:
- Around line 51-54: The Russian locale is missing the "few" plural form causing
wrong grammar for counts 2–4; add a new translation key
"addedZoomSuggestionsFew": "Добавлено {{count}} предложения" alongside the
existing "addedZoomSuggestions" and "addedZoomSuggestionsPlural", and update the
selection logic in TimelineEditor.tsx (the code using addedCount, key and
keyPlural at the call site) to choose among three forms (singular, few, many) —
i.e., use addedZoomSuggestions when count is 1, addedZoomSuggestionsFew for 2–4
(and 22–24 etc.), and addedZoomSuggestionsPlural for 0 and 5–20 etc., or
alternatively migrate the call site to i18next's built‑in pluralization keys
(_one/_few/_many) and switch the locale keys accordingly.

---

Outside diff comments:
In `@src/i18n/__tests__/tutorialHelpTranslations.test.ts`:
- Around line 36-44: dialogsByLocale currently maps only seven locales and is
missing ja-JP, zh-TW, and ar which causes runtime TypeError when tests iterate
SUPPORTED_LOCALES; import the missing dialog modules (e.g., jaJPDialogs,
zhTWDialogs, arDialogs) and add entries "ja-JP": jaJPDialogs, "zh-TW":
zhTWDialogs, and ar: arDialogs to the dialogsByLocale object so it covers all
SUPPORTED_LOCALES while keeping the satisfies Record<Locale, { tutorial:
Record<string, unknown> }> assertion.
🪄 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: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 1a4c9df6-be31-43e3-91a0-9ec563a572d6

📥 Commits

Reviewing files that changed from the base of the PR and between 899504f and 6130c66.

📒 Files selected for processing (9)
  • src/i18n/__tests__/tutorialHelpTranslations.test.ts
  • src/i18n/config.ts
  • src/i18n/locales/ru/common.json
  • src/i18n/locales/ru/dialogs.json
  • src/i18n/locales/ru/editor.json
  • src/i18n/locales/ru/launch.json
  • src/i18n/locales/ru/settings.json
  • src/i18n/locales/ru/shortcuts.json
  • src/i18n/locales/ru/timeline.json

Comment thread src/i18n/__tests__/tutorialHelpTranslations.test.ts Outdated
Comment thread src/i18n/locales/ru/editor.json Outdated
Comment on lines +51 to +54
"success": {
"addedZoomSuggestions": "Добавлено {{count}} предложение масштабирования на основе курсора",
"addedZoomSuggestionsPlural": "Добавлено {{count}} предложений масштабирования на основе курсора"
}
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot May 6, 2026

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

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Find all usages of addedZoomSuggestions to understand how plural selection is done
rg -n -C3 "addedZoomSuggestions"

Repository: siddharthvaddem/openscreen

Length of output: 6121


Missing Russian "few" plural form — shows wrong case for counts 2–4.

Russian needs three plural forms, but the code only branches on one vs. everything-else:

Count Correct form Your code Status
1, 21, 31… предложение ✓ correct working
2–4, 22–24, 32–34… предложения предложений ❌ kinda cursed
0, 5–20, 25–30… предложений ✓ correct working

The call site (TimelineEditor.tsx:1110–1112) uses addedCount === 1 ? key : keyPlural, so count=2 falls into the "other" branch and renders the plural genitive form instead of the plural nominative. Russian speakers will see grammatically wrong text like "Добавлено 3 предложений" instead of "Добавлено 3 предложения".

Fix: Either add addedZoomSuggestionsFew and update the call site to handle three cases, or switch the app's pluralization logic to use i18next's built-in _one/_few/_many suffixes instead of the custom base/Plural pattern.

🤖 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 `@src/i18n/locales/ru/timeline.json` around lines 51 - 54, The Russian locale
is missing the "few" plural form causing wrong grammar for counts 2–4; add a new
translation key "addedZoomSuggestionsFew": "Добавлено {{count}} предложения"
alongside the existing "addedZoomSuggestions" and "addedZoomSuggestionsPlural",
and update the selection logic in TimelineEditor.tsx (the code using addedCount,
key and keyPlural at the call site) to choose among three forms (singular, few,
many) — i.e., use addedZoomSuggestions when count is 1, addedZoomSuggestionsFew
for 2–4 (and 22–24 etc.), and addedZoomSuggestionsPlural for 0 and 5–20 etc., or
alternatively migrate the call site to i18next's built‑in pluralization keys
(_one/_few/_many) and switch the locale keys accordingly.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

In Russian, there is no single ending that applies to all numerals, so a minor fix is not possible in this case

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.

@psychosomat — yeah, you're 100% right, and that's exactly the root of the issue. The current addCount === 1 ? key : keyPlural pattern in TimelineEditor.tsx is inherently English-brained — it only knows two forms and will always give Russian speakers the wrong word for counts 2–4.

The clean long-term fix isn't a JSON tweak — it's migrating the call site to i18next's native pluralization. i18next supports all three Russian forms natively using the _one, _few, and _many suffix pattern with Intl.PluralRules under the hood. That means once the call site uses t('addedZoomSuggestions', { count }), i18next automatically picks the right form for 1, 2–4, and 5+:

// ru/timeline.json (after migration)
"success": {
  "addedZoomSuggestions_one":  "Добавлено {{count}} предложение масштабирования на основе курсора",
  "addedZoomSuggestions_few":  "Добавлено {{count}} предложения масштабирования на основе курсора",
  "addedZoomSuggestions_many": "Добавлено {{count}} предложений масштабирования на основе курсора"
}

This is a broader refactor of the pluralization infrastructure, not just the ru locale. Totally out of scope for this PR — would you like me to open a follow-up issue to track it?

( ´・・)ノ(._.`)


✏️ Learnings added
Learnt from: psychosomat
Repo: siddharthvaddem/openscreen PR: 546
File: src/i18n/locales/ru/timeline.json:51-54
Timestamp: 2026-05-06T10:21:30.696Z
Learning: In the OpenScreen codebase (siddharthvaddem/openscreen), the pluralization logic in TimelineEditor.tsx uses a custom binary pattern (`addCount === 1 ? key : keyPlural`) that only supports two plural forms and is incompatible with Russian, which requires three forms (one/few/many). The correct fix requires migrating the call site to i18next's native `t(key, { count })` with `_one`/`_few`/`_many` suffixed keys in the locale JSON, rather than the custom base/`Plural` suffix pattern.

Note: Learnings are effective only in the context of similar code segments. To apply general coding guidelines, please configure review instructions. You can manage existing learnings in the app.

@psychosomat
Copy link
Copy Markdown
Contributor Author

The errors related to the absence of zh-TW, ja-JP, and ar in the tests are not related to my PR. Regarding addedZoomSuggestions, I don't consider this a critical issue, but I will implement it if necessary.

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