Skip to content

feat: Russian localization + dynamic agent language#1990

Open
DrSeedon wants to merge 3 commits intoAndyMik90:developfrom
DrSeedon:feature/russian-localization
Open

feat: Russian localization + dynamic agent language#1990
DrSeedon wants to merge 3 commits intoAndyMik90:developfrom
DrSeedon:feature/russian-localization

Conversation

@DrSeedon
Copy link
Copy Markdown

@DrSeedon DrSeedon commented Mar 31, 2026

Summary

  • Add Russian (ru) as a supported UI language with full translation of all 11 i18n files (3544 lines)
  • Dynamic agent language injection: agents respond in the language selected in UI settings
  • Two injection paths: pipeline agents (planner/coder/QA) via injectContext(), utility runners via createSimpleClient()
  • No prompt files modified — language instruction injected at runtime, keeping upstream merge clean

AI Assistance Disclosure

This PR was built with AI assistance (Claude). Testing level: fully tested — TypeScript typecheck passes, dev build compiles and launches, UI manually verified, JSON validation passes.

Test plan

  • Select Russian in Settings → Language → verify UI switches to Russian
  • npm run typecheck passes with 0 errors
  • Create a task → verify planner/coder agents respond in Russian
  • Switch back to English → verify agents respond in English
  • Run insights/roadmap → verify runner output respects language setting

Summary by CodeRabbit

  • New Features

    • Added Russian language support across the app
    • AI agent responses can follow the user's selected UI language
  • Localization

    • Comprehensive Russian translations added for settings, navigation, onboarding, tasks, dialogs, terminal, task review, Git integrations, welcome, and error messages

- Add Russian (ru) to supported languages and UI language selector
- Translate all 11 i18n JSON files (3544 lines) to Russian
- Inject language instruction into agent prompts based on UI settings
  (pipeline agents via injectContext, runners via createSimpleClient)
- Language flows: settings.json → agent-manager → worker → prompt
@CLAassistant
Copy link
Copy Markdown

CLA assistant check
Thank you for your submission! We really appreciate it. Like many open source projects, we ask that you sign our Contributor License Agreement before we can accept your contribution.
You have signed the CLA already but the status is still pending? Let us recheck it.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Mar 31, 2026

📝 Walkthrough

Walkthrough

This PR adds Russian (ru) UI localization and threads a persisted language setting into agent sessions and prompt generation so agents can be instructed to respond in the selected language.

Changes

Cohort / File(s) Summary
Agent session & types
apps/desktop/src/main/agent/agent-manager.ts, apps/desktop/src/main/ai/agent/types.ts, apps/desktop/src/main/ai/prompts/types.ts
Add optional language?: string to session/prompt types and read settings language in agent manager to include language in SerializableSessionConfig for worker processes.
Prompt assembly & language injection
apps/desktop/src/main/ai/agent/worker.ts, apps/desktop/src/main/ai/prompts/prompt-loader.ts, apps/desktop/src/main/ai/prompts/language-utils.ts, apps/desktop/src/main/ai/client/factory.ts
Thread session.language into prompt context; add buildLanguageInstruction() and injectLanguageInstruction() to produce/prepend a non-English language instruction when applicable and pass language into injectContext.
i18n config
apps/desktop/src/shared/constants/i18n.ts, apps/desktop/src/shared/i18n/index.ts
Extend SupportedLanguage to include ru and add ru resources entry to the exported resources mapping.
Russian locale files
apps/desktop/src/shared/i18n/locales/ru/*
Add comprehensive Russian translation JSONs across namespaces: common.json, dialogs.json, errors.json, gitlab.json, navigation.json, onboarding.json, settings.json, taskReview.json, tasks.json, terminal.json, welcome.json.

Sequence Diagram

sequenceDiagram
    participant Settings as Settings File
    participant AgentMgr as Agent Manager
    participant Worker as Agent Worker
    participant PromptLdr as Prompt Loader
    participant ClientFac as Client Factory
    participant Final as Final Prompt

    Settings->>AgentMgr: read settings (language)
    AgentMgr->>AgentMgr: getSettingsLanguage()
    AgentMgr->>Worker: startSpecCreation/startTaskExecution/startQAProcess\nSerializableSessionConfig{..., language}
    Worker->>Worker: assemblePrompt(session)
    Worker->>PromptLdr: injectContext(context with language)
    PromptLdr->>PromptLdr: buildLanguageInstruction(language) -> instruction
    PromptLdr-->>Worker: prompt with language instruction block
    Worker->>ClientFac: provide systemPrompt / context
    ClientFac->>ClientFac: injectLanguageInstruction(systemPrompt) (reads settings/builds instruction)
    ClientFac-->>Final: Final prompt with language enforcement
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Suggested labels

area/frontend, size/M

Poem

🐰 I hopped through files to weave a thread,
Adding "ru" where prompts are led.
From settings read to worker’s song,
Language guides replies all day long.
Прыгай со мной — the rabbit hums along.

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'feat: Russian localization + dynamic agent language' clearly summarizes the two main changes: adding Russian language support and implementing dynamic language injection for agents.
Docstring Coverage ✅ Passed Docstring coverage is 83.33% which is sufficient. The required threshold is 80.00%.

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

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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
Contributor

@github-actions github-actions bot left a comment

Choose a reason for hiding this comment

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

🎉 Thanks for your first PR!

A maintainer will review it soon. Please make sure:

  • Your branch is synced with develop
  • CI checks pass
  • You've followed our contribution guide

Welcome to the Auto Claude community!

Copy link
Copy Markdown
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

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

Code Review

This pull request introduces support for the Russian language across the desktop application, including comprehensive translation files and logic to inject language-specific instructions into AI prompts. Feedback focuses on refactoring duplicated language injection logic into a shared utility, avoiding inefficient synchronous I/O when reading settings, and correctly implementing Russian pluralization keys (_one, _few, _many) to ensure grammatical correctness in the UI.

Comment on lines +200 to +212
const LANG_NAMES: Record<string, string> = { ru: 'Russian', fr: 'French' };

function injectLanguageInstruction(prompt: string): string {
const settings = readSettingsFile();
const lang = (settings?.language as string | undefined) ?? 'en';
if (lang === 'en') return prompt;
const langName = LANG_NAMES[lang] ?? lang;
return (
`**LANGUAGE**: Always respond in ${langName}. All code comments, ` +
`documentation, commit messages, and explanations must be in ${langName}.\n\n` +
prompt
);
}
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.

medium

The language mapping and instruction string are duplicated here and in prompt-loader.ts. Additionally, readSettingsFile() is called synchronously inside injectLanguageInstruction, which is executed every time a client is created. This is inefficient as it performs I/O on every call.

Consider centralizing this logic into a shared helper (e.g., in prompt-loader.ts) and using the AVAILABLE_LANGUAGES constant from shared/constants/i18n.ts to retrieve language labels instead of hardcoding them.

Comment on lines +228 to +234
const langNames: Record<string, string> = { ru: 'Russian', fr: 'French' };
const langName = langNames[context.language] ?? context.language;
sections.push(
`**LANGUAGE**: Always respond in ${langName}. All code comments, ` +
`documentation, commit messages, and explanations must be in ${langName}.\n\n`
);
}
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.

medium

This logic is duplicated in factory.ts. Consider moving the language instruction generation to a shared utility function. Also, instead of hardcoding langNames, you can use the AVAILABLE_LANGUAGES constant from shared/constants/i18n.ts to dynamically resolve the English label for any supported language code.

Comment on lines +162 to +163
"bulkDeleteSuccess": "{{count}} воркдерево успешно удалено",
"bulkDeleteSuccess_plural": "{{count}} воркдеревьев успешно удалено"
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.

medium

Russian pluralization in i18next (v21+) typically requires three forms (_one, _few, _many) to be grammatically correct. For example:

  • _one: 1 воркдерево
  • _few: 2 воркдерева
  • _many: 5 воркдеревьев

Using only a single _plural suffix will result in incorrect grammar for counts like 2, 3, or 4 (e.g., it will show "2 воркдеревьев" instead of "2 воркдерева"). This issue is present throughout the new Russian translation files (e.g., postFindings, messageCount, etc.).

@DrSeedon
Copy link
Copy Markdown
Author

I have read the CLA Document and I hereby sign the CLA

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: 4

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@apps/desktop/src/main/agent/agent-manager.ts`:
- Around line 131-134: In getSettingsLanguage(), remove the redundant nullish
coalescing by returning the cast directly: replace the expression
"(settings?.language as string | undefined) ?? undefined" with
"settings?.language as string | undefined" so the function simply returns the
optional language value; update the getSettingsLanguage method accordingly.

In `@apps/desktop/src/main/ai/client/factory.ts`:
- Around line 196-212: The injectLanguageInstruction function duplicates
LANG_NAMES and language instruction text; extract that shared logic into a new
helper (e.g., export LANG_NAMES and a buildLanguageInstruction(lang: string):
string | null) and replace injectLanguageInstruction to call the shared
buildLanguageInstruction: keep injectLanguageInstruction (and other callers like
prompt-loader.ts) but import buildLanguageInstruction, call it with the detected
lang, prepend the returned instruction string when non-null, and remove the
local LANG_NAMES and inline text to avoid duplication.

In `@apps/desktop/src/shared/i18n/locales/ru/common.json`:
- Around line 406-407: The JSON contains untranslated English strings in the
Russian locale—replace the English values for keys like
"cleanReviewMessageStatus" and "cleanReviewMessageFooter" (and any other English
strings around the same area) with proper Russian translations while preserving
the existing Markdown/formatting and punctuation, ensure the JSON remains valid
(quotes/commas), and run the i18n/locales linter or tests to confirm
localization consistency.
- Around line 162-163: The Russian pluralization entries for bulkDeleteSuccess
are using a binary _plural suffix which won't match i18next's CLDR categories;
update the locale keys for bulkDeleteSuccess to the CLDR forms
(bulkDeleteSuccess_one, bulkDeleteSuccess_few, bulkDeleteSuccess_many, and
bulkDeleteSuccess_other) with the correct Russian grammatical forms for each
count category and keep the base key as the singular or fallback; apply the same
replacement pattern to the corresponding plural keys in the English and French
locale files so all locales use _one/_few/_many/_other categories expected by
i18next.
🪄 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: ASSERTIVE

Plan: Pro

Run ID: db651fec-c518-4cdc-8bba-a64832d5ec83

📥 Commits

Reviewing files that changed from the base of the PR and between cba7a02 and 7994fa6.

📒 Files selected for processing (19)
  • apps/desktop/src/main/agent/agent-manager.ts
  • apps/desktop/src/main/ai/agent/types.ts
  • apps/desktop/src/main/ai/agent/worker.ts
  • apps/desktop/src/main/ai/client/factory.ts
  • apps/desktop/src/main/ai/prompts/prompt-loader.ts
  • apps/desktop/src/main/ai/prompts/types.ts
  • apps/desktop/src/shared/constants/i18n.ts
  • apps/desktop/src/shared/i18n/index.ts
  • apps/desktop/src/shared/i18n/locales/ru/common.json
  • apps/desktop/src/shared/i18n/locales/ru/dialogs.json
  • apps/desktop/src/shared/i18n/locales/ru/errors.json
  • apps/desktop/src/shared/i18n/locales/ru/gitlab.json
  • apps/desktop/src/shared/i18n/locales/ru/navigation.json
  • apps/desktop/src/shared/i18n/locales/ru/onboarding.json
  • apps/desktop/src/shared/i18n/locales/ru/settings.json
  • apps/desktop/src/shared/i18n/locales/ru/taskReview.json
  • apps/desktop/src/shared/i18n/locales/ru/tasks.json
  • apps/desktop/src/shared/i18n/locales/ru/terminal.json
  • apps/desktop/src/shared/i18n/locales/ru/welcome.json

Comment on lines +162 to +163
"bulkDeleteSuccess": "{{count}} воркдерево успешно удалено",
"bulkDeleteSuccess_plural": "{{count}} воркдеревьев успешно удалено"
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

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Verify i18next plural configuration and Russian plural key usage.

echo "== i18n init settings =="
fd -i "index.ts" apps/desktop/src/shared/i18n -x sed -n '1,220p' {}

echo
echo "== Russian locale keys with plural suffixes =="
rg -n '"[^"]+_(plural|other|one|few|many)"\s*:' apps/desktop/src/shared/i18n/locales/ru/common.json apps/desktop/src/shared/i18n/locales/ru/tasks.json apps/desktop/src/shared/i18n/locales/ru/settings.json

echo
echo "== Compare with English/French key shapes for same namespace =="
for f in common tasks settings; do
  echo "--- $f ---"
  for lang in en fr ru; do
    p="apps/desktop/src/shared/i18n/locales/$lang/$f.json"
    [ -f "$p" ] && echo "$p"
  done
done

Repository: AndyMik90/Aperant

Length of output: 7773


🏁 Script executed:

# Check how plural translations are actually used in the codebase
echo "=== Searching for i18next pluralization usage ==="
rg "i18n\.t\(" apps/desktop/src/renderer -A 2 -B 2 | head -50

echo
echo "=== Look for useTranslation and plural parameter usage ==="
rg "useTranslation|\.t\(" apps/desktop/src/renderer -A 1 | grep -A 1 "count:" | head -40

echo
echo "=== Check English common.json plural key structure ==="
rg '"[^"]+_(plural|one|few|many|other)"\s*:' apps/desktop/src/shared/i18n/locales/en/common.json | head -20

echo
echo "=== Check French common.json plural key structure ==="
rg '"[^"]+_(plural|one|few|many|other)"\s*:' apps/desktop/src/shared/i18n/locales/fr/common.json | head -20

Repository: AndyMik90/Aperant

Length of output: 8522


🌐 Web query:

i18next default plural rules Russian language configuration

💡 Result:

i18next uses Intl.PluralRules API by default (since v21, JSON v4 format) for plural suffixes, which must be polyfilled if not supported (e.g., npm install intl-pluralrules). For Russian ('ru'), the categories are 'one', 'few', 'many', 'other'. Provide translation keys like "key_one", "key_few", "key_many", "key_other". Additionally, "zero" can be used specially for count: 0. Russian plural rules (Unicode CLDR): - one: absolute value 1 - few: absolute value 2-4 - many: absolute value ends in 5-9, 0, or 11-14, etc. - other: numbers ending in 0 (except 0?), but actually standard is: Standard Intl.PluralRules('ru') returns: - 0: 'many' - 1: 'one' - 2: 'few' - 5: 'many' - etc. No configuration needed beyond setting lng: 'ru' and providing the keys with correct suffixes. Default pluralSeparator is ''. Example JSON for Russian: { "items_one": "1 предмет", "items_few": "{{count}} предмета", "items_many": "{{count}} предметов", "items_other": "{{count}} предметов" // fallback if needed } Use i18next.t('items', { count: 2 }) -> "2 предмета" (few). To find exact suffixes for any language/count, use the official utility mentioned in docs: https://www.i18next.com/translation-function/plurals#how-to-find-the-correct-plural-suffix (source code linked there) or translation-check tool.

Citations:


🏁 Script executed:

# Search for actual pluralization calls with count parameter more broadly
echo "=== Search for t() calls with count parameter ==="
rg 'i18n?\.t\([^)]*count' apps/desktop -B 2 -A 1 | head -80

echo
echo "=== Search for useTranslation hook usage with count ==="
rg 'const\s+\{\s*t\s*\}\s*=\s*useTranslation' apps/desktop/src/renderer -A 10 | grep -B 5 -A 5 'count'

echo
echo "=== Check if plural keys are referenced anywhere ==="
rg 'bulkDeleteSuccess|postFindings|messageCount_other' apps/desktop/src

echo
echo "=== Look for actual t() invocations in component code ==="
rg 't\(["\x27][a-z]+:[a-zA-Z]+' apps/desktop/src/renderer/components -A 1 | head -60

echo
echo "=== Check git status/history of Russian locale file ==="
git log --oneline apps/desktop/src/shared/i18n/locales/ru/common.json 2>/dev/null | head -10

Repository: AndyMik90/Aperant

Length of output: 34200


🏁 Script executed:

# Verify the plural key patterns across flagged lines for all three languages
echo "=== Russian lines 162-163 (bulkDeleteSuccess) ==="
sed -n '162,163p' apps/desktop/src/shared/i18n/locales/ru/common.json

echo
echo "=== English equivalent ==="
sed -n '162,163p' apps/desktop/src/shared/i18n/locales/en/common.json

echo
echo "=== Check line 477 for messageCount_other pattern ==="
sed -n '477p' apps/desktop/src/shared/i18n/locales/ru/common.json
sed -n '477p' apps/desktop/src/shared/i18n/locales/en/common.json

echo
echo "=== Check if _other is used elsewhere ==="
rg '"[^"]+_other"\s*:' apps/desktop/src/shared/i18n/locales/ru/common.json

echo
echo "=== Verify count parameter is actually being used in PRDetail.tsx ==="
grep -B 5 -A 5 "count: selectedCount" apps/desktop/src/renderer/components/github-prs/components/PRDetail.tsx | head -20

Repository: AndyMik90/Aperant

Length of output: 1072


Russian pluralization keys won't render correct grammatical forms at runtime.

The current structure uses binary suffixes (_plural) across all languages, but i18next's default plural resolver for Russian requires the CLDR-compliant categories: _one, _few, _many, _other. When code invokes t('bulkDeleteSuccess', { count: 2 }), the resolver will look for bulkDeleteSuccess_few (or fallback), but only bulkDeleteSuccess and bulkDeleteSuccess_plural exist.

Change all flagged plural keys in the Russian locale files to use the correct suffixes:

  • For count=1: use _one
  • For count in [2–4]: use _few
  • For count in [0, 5–20, 25–30, ...]: use _many
  • Fallback: use _other

Note: English and French locale files have the same structural issue and should be corrected for consistency.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/desktop/src/shared/i18n/locales/ru/common.json` around lines 162 - 163,
The Russian pluralization entries for bulkDeleteSuccess are using a binary
_plural suffix which won't match i18next's CLDR categories; update the locale
keys for bulkDeleteSuccess to the CLDR forms (bulkDeleteSuccess_one,
bulkDeleteSuccess_few, bulkDeleteSuccess_many, and bulkDeleteSuccess_other) with
the correct Russian grammatical forms for each count category and keep the base
key as the singular or fallback; apply the same replacement pattern to the
corresponding plural keys in the English and French locale files so all locales
use _one/_few/_many/_other categories expected by i18next.

…n plurals

- Extract buildLanguageInstruction() into shared language-utils.ts
  (eliminates duplication between prompt-loader.ts and factory.ts)
- Use AVAILABLE_LANGUAGES from constants instead of hardcoded LANG_NAMES
- Fix Russian pluralization: replace _plural keys with CLDR-compliant
  _one/_few/_many/_other (27 plural groups, 108 keys)
- Translate remaining English strings in ru/common.json
- Remove redundant ?? undefined in getSettingsLanguage()
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: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@apps/desktop/src/main/ai/client/factory.ts`:
- Line 189: The systemPrompt is being passed through injectLanguageInstruction
in createAgentClient(), which duplicates/conflicts with language already
injected via injectContext(...) for pipeline agents and can diverge when
settings are re-read; change createAgentClient() so
injectLanguageInstruction(systemPrompt) is only applied for the simple/utility
agent path (not the pipeline path that uses injectContext), remove the
unconditional call for pipeline flows (also adjust the code around the block
that re-reads settings at the createAgentClient() call site to avoid
double-injection), and ensure pipeline code paths rely solely on
injectContext(...) for language injection.

In `@apps/desktop/src/shared/i18n/locales/ru/common.json`:
- Around line 439-441: The localization key cleanReviewMessageTitle contains an
English word ("PASSED") while related keys cleanReviewMessageStatus and
cleanReviewMessageFooter are in Russian; update the value of
cleanReviewMessageTitle to use a Russian equivalent (e.g., "## ✅ Aperant PR
Review - ПРОЙДЕНО" or "## ✅ Aperant PR Review - УСПЕШНО") so the title matches
the rest of the ru locale entries and maintains the same format/markup.
🪄 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: ASSERTIVE

Plan: Pro

Run ID: 9d4973ee-74e6-4a02-b4f9-14b5303bdc3e

📥 Commits

Reviewing files that changed from the base of the PR and between 7994fa6 and 25f17f4.

📒 Files selected for processing (5)
  • apps/desktop/src/main/agent/agent-manager.ts
  • apps/desktop/src/main/ai/client/factory.ts
  • apps/desktop/src/main/ai/prompts/language-utils.ts
  • apps/desktop/src/main/ai/prompts/prompt-loader.ts
  • apps/desktop/src/shared/i18n/locales/ru/common.json

…ate PASSED

- Remove injectLanguageInstruction() from createAgentClient() to avoid
  double injection (pipeline agents already get language via injectContext)
- Translate "PASSED" → "ПРОЙДЕНО" in cleanReviewMessageTitle
Comment on lines 226 to 236

// 3. Human input
// 3. Language instruction (non-English only)
if (context.language) {
const instruction = buildLanguageInstruction(context.language);
if (instruction) sections.push(instruction);
}

// 4. Human input
if (context.humanInput) {
sections.push(
`## HUMAN INPUT (READ THIS FIRST!)\n\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.

Bug: The QA status check in readQAStatus() only recognizes English, but the QA agent is instructed to respond in the user's selected language, causing a validation mismatch and build failure.
Severity: CRITICAL

Suggested Fix

Update the readQAStatus() function to support localized status keywords for all supported languages. Alternatively, explicitly instruct the QA agent to always write the status line in English, regardless of the user's language setting, or exclude the status line from the scope of the language instruction.

Prompt for AI Agent
Review the code at the location below. A potential bug has been identified by an AI
agent.
Verify if this is a real issue. If it is, propose a fix; if not, explain why it's not
valid.

Location: apps/desktop/src/main/ai/prompts/prompt-loader.ts#L224-L236

Potential issue: When a user selects a non-English language, a language instruction is
injected into the QA agent's prompt, causing it to write its status report in that
language (e.g., `Статус: ПРОЙДЕНО`). However, the `readQAStatus()` function in
`build-orchestrator.ts` only performs case-insensitive matching for hardcoded English
strings like `status: passed`. This mismatch causes the status to be read as `unknown`,
leading to repeated retries and an eventual build failure. This breaks the entire
automated build pipeline for any user operating in a non-English language.

Did we get this right? 👍 / 👎 to inform future reviews.

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: 2

♻️ Duplicate comments (1)
apps/desktop/src/shared/i18n/locales/ru/common.json (1)

287-288: ⚠️ Potential issue | 🟡 Minor

Convert prReview.newCommits to proper plural forms across all languages and remove unused prReview.newCommit.

newCommits currently lacks i18next plural suffixes (_one, _few, _many, _other). Russian renders incorrectly for count > 1 (singular form only), and English/French deviate from the established plural form pattern used throughout the codebase. The newCommit key is dead code and should be removed.

Update all three language files:

  • Add plural variants following the _one/_few/_many/_other pattern (e.g., newCommits_one, newCommits_few, newCommits_many, newCommits_other)
  • Remove the unused newCommit key
  • Match the Russian grammar rules for plural forms (one, 2-4, 5+)
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/desktop/src/shared/i18n/locales/ru/common.json` around lines 287 - 288,
Replace the single "newCommits" and remove the dead "newCommit" key; introduce
proper i18next plural keys "newCommits_one", "newCommits_few",
"newCommits_many", and "newCommits_other" in all language files so pluralization
follows the project's pattern: for Russian set forms for one (1), few (2–4),
many (5+ and 0) and other as fallback; for English/French provide singular
(_one) and plural (_other/_many) variants as appropriate; update any code
references to use "prReview.newCommits" (i18next will resolve the suffixes
automatically) and delete "prReview.newCommit".
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@apps/desktop/src/main/ai/client/factory.ts`:
- Around line 201-206: The helper injectLanguageInstruction currently reads
settings from disk each call; change it to accept a language parameter and stop
calling readSettingsFile() inside it (update signature
injectLanguageInstruction(prompt: string, language?: string)), use
buildLanguageInstruction(language ?? 'en') and remove the type assertion. Add
language?: string to the SimpleClientConfig interface and propagate that value
into createSimpleClient so callers pass config.language to
injectLanguageInstruction (fall back to 'en' where unspecified). Update all
callsites of injectLanguageInstruction/createSimpleClient to pass the new
language parameter and remove per-call reads of readSettingsFile().

In `@apps/desktop/src/shared/i18n/locales/ru/common.json`:
- Around line 507-508: The current keys bulkDeleteDescription and
bulkDeleteConfirm use manual “(а/ов)” hacks; replace them with i18next plural
keys (e.g., bulkDeleteDescription_one, bulkDeleteDescription_few,
bulkDeleteDescription_many, bulkDeleteDescription_other and same for
bulkDeleteConfirm) and move the count placeholder {{count}} into each pluralized
message with correct Russian morphology; ensure you follow the file’s existing
plural key naming and use react-i18next to render pluralization at runtime.

---

Duplicate comments:
In `@apps/desktop/src/shared/i18n/locales/ru/common.json`:
- Around line 287-288: Replace the single "newCommits" and remove the dead
"newCommit" key; introduce proper i18next plural keys "newCommits_one",
"newCommits_few", "newCommits_many", and "newCommits_other" in all language
files so pluralization follows the project's pattern: for Russian set forms for
one (1), few (2–4), many (5+ and 0) and other as fallback; for English/French
provide singular (_one) and plural (_other/_many) variants as appropriate;
update any code references to use "prReview.newCommits" (i18next will resolve
the suffixes automatically) and delete "prReview.newCommit".
🪄 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: ASSERTIVE

Plan: Pro

Run ID: 7bb473d4-6892-44ec-82bf-db5da719e036

📥 Commits

Reviewing files that changed from the base of the PR and between 25f17f4 and 10665da.

📒 Files selected for processing (2)
  • apps/desktop/src/main/ai/client/factory.ts
  • apps/desktop/src/shared/i18n/locales/ru/common.json

Comment on lines +201 to +206
function injectLanguageInstruction(prompt: string): string {
const settings = readSettingsFile();
const lang = (settings?.language as string | undefined) ?? 'en';
const instruction = buildLanguageInstruction(lang);
return instruction ? instruction + prompt : prompt;
}
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.

🧹 Nitpick | 🔵 Trivial

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Verify sync I/O and call-path coupling in current code.
rg -n -C3 '\breadSettingsFile\s*\(' apps/desktop/src/main/ai/client/factory.ts apps/desktop/src/main/settings-utils.ts
rg -n -C3 '\breadFileSync\s*\(' apps/desktop/src/main/settings-utils.ts
rg -n -C3 '\binjectLanguageInstruction\s*\(' apps/desktop/src/main/ai/client/factory.ts

Repository: AndyMik90/Aperant

Length of output: 2129


🏁 Script executed:

#!/bin/bash
# Find all usages of createSimpleClient, injectLanguageInstruction, and readSettingsFile
echo "=== createSimpleClient calls ==="
rg -n 'createSimpleClient\s*\(' apps/desktop/src/main/ai/ --type ts

echo "=== readSettingsFile calls ==="
rg -n 'readSettingsFile\s*\(' apps/desktop/src/main/ --type ts

echo "=== Check TypeScript strict mode ==="
jq '.compilerOptions.strict' apps/desktop/tsconfig.json

Repository: AndyMik90/Aperant

Length of output: 8762


🏁 Script executed:

#!/bin/bash
# Check file imports and dependencies to understand context
echo "=== Imports in factory.ts ==="
head -30 apps/desktop/src/main/ai/client/factory.ts | grep -E '^import|^export'

echo "=== Full function signature of createSimpleClient ==="
rg -A 15 'export\s+(?:async\s+)?function\s+createSimpleClient' apps/desktop/src/main/ai/client/factory.ts

Repository: AndyMik90/Aperant

Length of output: 1378


Consider passing language as a parameter instead of reading settings on each call.

Line 202 performs a synchronous disk read via readSettingsFile() on every createSimpleClient() invocation. With 29+ callsites across runners and validators, this adds unnecessary I/O. Additionally, line 203's type assertion (settings?.language as string | undefined) bypasses TypeScript's strict type checking.

The refactor is straightforward: accept language as a parameter in SimpleClientConfig and pass it down, avoiding the per-call settings read.

-function injectLanguageInstruction(prompt: string): string {
-  const settings = readSettingsFile();
-  const lang = (settings?.language as string | undefined) ?? 'en';
+function injectLanguageInstruction(prompt: string, lang: string): string {
   const instruction = buildLanguageInstruction(lang);
   return instruction ? instruction + prompt : prompt;
 }

 const result = await streamText({
   model,
   tools,
-  systemPrompt: injectLanguageInstruction(systemPrompt),
+  systemPrompt: injectLanguageInstruction(systemPrompt, language ?? 'en'),
 });

Add language?: string to SimpleClientConfig interface.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/desktop/src/main/ai/client/factory.ts` around lines 201 - 206, The
helper injectLanguageInstruction currently reads settings from disk each call;
change it to accept a language parameter and stop calling readSettingsFile()
inside it (update signature injectLanguageInstruction(prompt: string, language?:
string)), use buildLanguageInstruction(language ?? 'en') and remove the type
assertion. Add language?: string to the SimpleClientConfig interface and
propagate that value into createSimpleClient so callers pass config.language to
injectLanguageInstruction (fall back to 'en' where unspecified). Update all
callsites of injectLanguageInstruction/createSimpleClient to pass the new
language parameter and remove per-call reads of readSettingsFile().

Comment on lines +507 to +508
"bulkDeleteDescription": "Вы уверены, что хотите удалить {{count}} разговор(а/ов)? Это действие нельзя отменить.",
"bulkDeleteConfirm": "Удалить {{count}} разговор(а/ов)",
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.

🧹 Nitpick | 🔵 Trivial

Avoid manual (а/ов) grammar hacks; use i18next plurals.

These strings should use _one/_few/_many/_other keys for proper Russian morphology and consistency with the rest of this file.

♻️ Suggested key-shape refactor
-    "bulkDeleteDescription": "Вы уверены, что хотите удалить {{count}} разговор(а/ов)? Это действие нельзя отменить.",
-    "bulkDeleteConfirm": "Удалить {{count}} разговор(а/ов)",
+    "bulkDeleteDescription_one": "Вы уверены, что хотите удалить {{count}} разговор? Это действие нельзя отменить.",
+    "bulkDeleteDescription_few": "Вы уверены, что хотите удалить {{count}} разговора? Это действие нельзя отменить.",
+    "bulkDeleteDescription_many": "Вы уверены, что хотите удалить {{count}} разговоров? Это действие нельзя отменить.",
+    "bulkDeleteDescription_other": "Вы уверены, что хотите удалить {{count}} разговоров? Это действие нельзя отменить.",
+    "bulkDeleteConfirm_one": "Удалить {{count}} разговор",
+    "bulkDeleteConfirm_few": "Удалить {{count}} разговора",
+    "bulkDeleteConfirm_many": "Удалить {{count}} разговоров",
+    "bulkDeleteConfirm_other": "Удалить {{count}} разговоров",
...
-    "archiveConfirmButton": "Архивировать {{count}} разговор(а/ов)",
+    "archiveConfirmButton_one": "Архивировать {{count}} разговор",
+    "archiveConfirmButton_few": "Архивировать {{count}} разговора",
+    "archiveConfirmButton_many": "Архивировать {{count}} разговоров",
+    "archiveConfirmButton_other": "Архивировать {{count}} разговоров",

As per coding guidelines: “Use react-i18next for all translations.”

Also applies to: 514-514

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/desktop/src/shared/i18n/locales/ru/common.json` around lines 507 - 508,
The current keys bulkDeleteDescription and bulkDeleteConfirm use manual “(а/ов)”
hacks; replace them with i18next plural keys (e.g., bulkDeleteDescription_one,
bulkDeleteDescription_few, bulkDeleteDescription_many,
bulkDeleteDescription_other and same for bulkDeleteConfirm) and move the count
placeholder {{count}} into each pluralized message with correct Russian
morphology; ensure you follow the file’s existing plural key naming and use
react-i18next to render pluralization at runtime.

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.

2 participants