feat: Russian localization + dynamic agent language#1990
feat: Russian localization + dynamic agent language#1990DrSeedon wants to merge 3 commits intoAndyMik90:developfrom
Conversation
- 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
|
|
📝 WalkthroughWalkthroughThis PR adds Russian ( Changes
Sequence DiagramsequenceDiagram
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
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Suggested labels
Poem
🚥 Pre-merge checks | ✅ 3✅ Passed checks (3 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
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. Comment |
There was a problem hiding this comment.
🎉 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!
There was a problem hiding this comment.
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.
| 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 | ||
| ); | ||
| } |
There was a problem hiding this comment.
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.
| 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` | ||
| ); | ||
| } |
There was a problem hiding this comment.
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.
| "bulkDeleteSuccess": "{{count}} воркдерево успешно удалено", | ||
| "bulkDeleteSuccess_plural": "{{count}} воркдеревьев успешно удалено" |
There was a problem hiding this comment.
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.).
|
I have read the CLA Document and I hereby sign the CLA |
There was a problem hiding this comment.
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
📒 Files selected for processing (19)
apps/desktop/src/main/agent/agent-manager.tsapps/desktop/src/main/ai/agent/types.tsapps/desktop/src/main/ai/agent/worker.tsapps/desktop/src/main/ai/client/factory.tsapps/desktop/src/main/ai/prompts/prompt-loader.tsapps/desktop/src/main/ai/prompts/types.tsapps/desktop/src/shared/constants/i18n.tsapps/desktop/src/shared/i18n/index.tsapps/desktop/src/shared/i18n/locales/ru/common.jsonapps/desktop/src/shared/i18n/locales/ru/dialogs.jsonapps/desktop/src/shared/i18n/locales/ru/errors.jsonapps/desktop/src/shared/i18n/locales/ru/gitlab.jsonapps/desktop/src/shared/i18n/locales/ru/navigation.jsonapps/desktop/src/shared/i18n/locales/ru/onboarding.jsonapps/desktop/src/shared/i18n/locales/ru/settings.jsonapps/desktop/src/shared/i18n/locales/ru/taskReview.jsonapps/desktop/src/shared/i18n/locales/ru/tasks.jsonapps/desktop/src/shared/i18n/locales/ru/terminal.jsonapps/desktop/src/shared/i18n/locales/ru/welcome.json
| "bulkDeleteSuccess": "{{count}} воркдерево успешно удалено", | ||
| "bulkDeleteSuccess_plural": "{{count}} воркдеревьев успешно удалено" |
There was a problem hiding this comment.
🧩 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
doneRepository: 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 -20Repository: 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:
- 1: https://www.i18next.com/translation-function/plurals
- 2: http://www.i18next.com/translation-function/plurals
- 3: https://i18next.notmybase.com/plurals
- 4: Plurals: Passing 2 as a count selects translation key with suffix _1 for ru-RU i18next/i18next#1499
- 5: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/PluralRules
- 6: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/PluralRules/select
- 7: http://www.i18next.com/misc
🏁 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 -10Repository: 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 -20Repository: 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()
There was a problem hiding this comment.
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
📒 Files selected for processing (5)
apps/desktop/src/main/agent/agent-manager.tsapps/desktop/src/main/ai/client/factory.tsapps/desktop/src/main/ai/prompts/language-utils.tsapps/desktop/src/main/ai/prompts/prompt-loader.tsapps/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
|
|
||
| // 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` + |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
Actionable comments posted: 2
♻️ Duplicate comments (1)
apps/desktop/src/shared/i18n/locales/ru/common.json (1)
287-288:⚠️ Potential issue | 🟡 MinorConvert
prReview.newCommitsto proper plural forms across all languages and remove unusedprReview.newCommit.
newCommitscurrently 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. ThenewCommitkey is dead code and should be removed.Update all three language files:
- Add plural variants following the
_one/_few/_many/_otherpattern (e.g.,newCommits_one,newCommits_few,newCommits_many,newCommits_other)- Remove the unused
newCommitkey- 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
📒 Files selected for processing (2)
apps/desktop/src/main/ai/client/factory.tsapps/desktop/src/shared/i18n/locales/ru/common.json
| 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; | ||
| } |
There was a problem hiding this comment.
🧹 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.tsRepository: 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.jsonRepository: 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.tsRepository: 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().
| "bulkDeleteDescription": "Вы уверены, что хотите удалить {{count}} разговор(а/ов)? Это действие нельзя отменить.", | ||
| "bulkDeleteConfirm": "Удалить {{count}} разговор(а/ов)", |
There was a problem hiding this comment.
🧹 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.
Summary
injectContext(), utility runners viacreateSimpleClient()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
npm run typecheckpasses with 0 errorsSummary by CodeRabbit
New Features
Localization