diff --git a/apps/desktop/src/main/agent/agent-manager.ts b/apps/desktop/src/main/agent/agent-manager.ts
index 21a538490c..b60f6dd907 100644
--- a/apps/desktop/src/main/agent/agent-manager.ts
+++ b/apps/desktop/src/main/agent/agent-manager.ts
@@ -128,6 +128,11 @@ export class AgentManager extends EventEmitter {
return accounts.length > 0;
}
+ private getSettingsLanguage(): string | undefined {
+ const settings = readSettingsFile();
+ return settings?.language as string | undefined;
+ }
+
/**
* Resolve auth using the provider accounts priority queue.
* Falls back to legacy Claude profile if no provider accounts exist.
@@ -389,6 +394,7 @@ export class AgentManager extends EventEmitter {
maxSteps: 1000,
specDir: resolvedSpecDir,
projectDir: projectPath,
+ language: this.getSettingsLanguage(),
provider: resolved.provider,
modelId: resolved.modelId,
apiKey: resolved.auth?.apiKey,
@@ -510,6 +516,7 @@ export class AgentManager extends EventEmitter {
maxSteps: 1000,
specDir: worktreeSpecDir,
projectDir: effectiveProjectDir,
+ language: this.getSettingsLanguage(),
// When running in a worktree, sourceSpecDir points to the main project spec dir
// so the subtask iterator can sync phase updates in real time (not just on exit).
sourceSpecDir: worktreePath ? specDir : undefined,
@@ -616,6 +623,7 @@ export class AgentManager extends EventEmitter {
maxSteps: 1000,
specDir: effectiveSpecDir,
projectDir: effectiveProjectDir,
+ language: this.getSettingsLanguage(),
provider: resolved.provider,
modelId: resolved.modelId,
apiKey: resolved.auth?.apiKey,
diff --git a/apps/desktop/src/main/ai/agent/types.ts b/apps/desktop/src/main/ai/agent/types.ts
index 0f7f453055..2ccf8ea097 100644
--- a/apps/desktop/src/main/ai/agent/types.ts
+++ b/apps/desktop/src/main/ai/agent/types.ts
@@ -77,6 +77,8 @@ export interface SerializableSessionConfig {
};
/** Enable agentic orchestration mode where the AI drives the pipeline via SpawnSubagent tool */
useAgenticOrchestration?: boolean;
+ /** UI language code for agent response language (e.g., 'en', 'ru') */
+ language?: string;
/** Tool context serialized fields */
toolContext: {
cwd: string;
diff --git a/apps/desktop/src/main/ai/agent/worker.ts b/apps/desktop/src/main/ai/agent/worker.ts
index f03bb19d20..4644297bda 100644
--- a/apps/desktop/src/main/ai/agent/worker.ts
+++ b/apps/desktop/src/main/ai/agent/worker.ts
@@ -230,6 +230,7 @@ async function assemblePrompt(
specDir: session.specDir,
projectDir: session.projectDir,
projectInstructions: cachedProjectInstructions,
+ language: session.language,
});
}
diff --git a/apps/desktop/src/main/ai/client/factory.ts b/apps/desktop/src/main/ai/client/factory.ts
index e1acc75719..e615ad1d21 100644
--- a/apps/desktop/src/main/ai/client/factory.ts
+++ b/apps/desktop/src/main/ai/client/factory.ts
@@ -15,6 +15,8 @@
import type { Tool as AITool } from 'ai';
import { resolveAuth, resolveAuthFromQueue, buildDefaultQueueConfig } from '../auth/resolver';
+import { readSettingsFile } from '../../settings-utils';
+import { buildLanguageInstruction } from '../prompts/language-utils';
import {
getDefaultThinkingLevel,
getRequiredMcpServers,
@@ -192,6 +194,17 @@ export async function createAgentClient(
};
}
+// =============================================================================
+// Language Injection
+// =============================================================================
+
+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;
+}
+
// =============================================================================
// createSimpleClient
// =============================================================================
@@ -289,7 +302,7 @@ export async function createSimpleClient(
model,
resolvedModelId,
tools,
- systemPrompt,
+ systemPrompt: injectLanguageInstruction(systemPrompt),
maxSteps,
thinkingLevel: resolvedThinkingLevel,
...(queueAuth ? { queueAuth } : {}),
diff --git a/apps/desktop/src/main/ai/prompts/language-utils.ts b/apps/desktop/src/main/ai/prompts/language-utils.ts
new file mode 100644
index 0000000000..a1fcc2a1aa
--- /dev/null
+++ b/apps/desktop/src/main/ai/prompts/language-utils.ts
@@ -0,0 +1,11 @@
+import { AVAILABLE_LANGUAGES } from '../../../shared/constants/i18n';
+
+export function buildLanguageInstruction(language: string): string | null {
+ if (!language || language === 'en') return null;
+ const entry = AVAILABLE_LANGUAGES.find((l) => l.value === language);
+ const langName = entry?.label ?? language;
+ return (
+ `**LANGUAGE**: Always respond in ${langName}. All code comments, ` +
+ `documentation, commit messages, and explanations must be in ${langName}.\n\n`
+ );
+}
diff --git a/apps/desktop/src/main/ai/prompts/prompt-loader.ts b/apps/desktop/src/main/ai/prompts/prompt-loader.ts
index 6ad1ff34fe..d7072baf81 100644
--- a/apps/desktop/src/main/ai/prompts/prompt-loader.ts
+++ b/apps/desktop/src/main/ai/prompts/prompt-loader.ts
@@ -15,6 +15,7 @@ import { join } from 'node:path';
import { execSync } from 'node:child_process';
import type { ProjectCapabilities, PromptContext, PromptValidationResult } from './types';
+import { buildLanguageInstruction } from './language-utils';
// =============================================================================
// Expected prompt files (used for startup validation)
@@ -223,7 +224,13 @@ export function injectContext(promptTemplate: string, context: PromptContext): s
sections.push(context.recoveryContext);
}
- // 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` +
@@ -234,7 +241,7 @@ export function injectContext(promptTemplate: string, context: PromptContext): s
);
}
- // 4. Project instructions (AGENTS.md or CLAUDE.md fallback)
+ // 5. Project instructions (AGENTS.md or CLAUDE.md fallback)
if (context.projectInstructions) {
sections.push(
`## PROJECT INSTRUCTIONS\n\n` +
@@ -243,7 +250,7 @@ export function injectContext(promptTemplate: string, context: PromptContext): s
);
}
- // 5. Base prompt
+ // 6. Base prompt
sections.push(promptTemplate);
return sections.join('');
diff --git a/apps/desktop/src/main/ai/prompts/types.ts b/apps/desktop/src/main/ai/prompts/types.ts
index 335bca3f9b..c1ab4bef76 100644
--- a/apps/desktop/src/main/ai/prompts/types.ts
+++ b/apps/desktop/src/main/ai/prompts/types.ts
@@ -32,6 +32,8 @@ export interface PromptContext {
recoveryHints?: string[];
/** Phase-specific planning retry context */
planningRetryContext?: string;
+ /** UI language code for agent response language (e.g., 'en', 'ru') */
+ language?: string;
}
// =============================================================================
diff --git a/apps/desktop/src/shared/constants/i18n.ts b/apps/desktop/src/shared/constants/i18n.ts
index 5f4ebbde38..5d29eafde3 100644
--- a/apps/desktop/src/shared/constants/i18n.ts
+++ b/apps/desktop/src/shared/constants/i18n.ts
@@ -3,11 +3,12 @@
* Available languages and display labels
*/
-export type SupportedLanguage = 'en' | 'fr';
+export type SupportedLanguage = 'en' | 'fr' | 'ru';
export const AVAILABLE_LANGUAGES = [
{ value: 'en' as const, label: 'English', nativeLabel: 'English' },
- { value: 'fr' as const, label: 'French', nativeLabel: 'Français' }
+ { value: 'fr' as const, label: 'French', nativeLabel: 'Français' },
+ { value: 'ru' as const, label: 'Russian', nativeLabel: 'Русский' }
] as const;
export const DEFAULT_LANGUAGE: SupportedLanguage = 'en';
diff --git a/apps/desktop/src/shared/i18n/index.ts b/apps/desktop/src/shared/i18n/index.ts
index 095b0b1188..e53f02035d 100644
--- a/apps/desktop/src/shared/i18n/index.ts
+++ b/apps/desktop/src/shared/i18n/index.ts
@@ -27,6 +27,19 @@ import frTaskReview from './locales/fr/taskReview.json';
import frTerminal from './locales/fr/terminal.json';
import frErrors from './locales/fr/errors.json';
+// Import Russian translation resources
+import ruCommon from './locales/ru/common.json';
+import ruNavigation from './locales/ru/navigation.json';
+import ruSettings from './locales/ru/settings.json';
+import ruTasks from './locales/ru/tasks.json';
+import ruWelcome from './locales/ru/welcome.json';
+import ruOnboarding from './locales/ru/onboarding.json';
+import ruDialogs from './locales/ru/dialogs.json';
+import ruGitlab from './locales/ru/gitlab.json';
+import ruTaskReview from './locales/ru/taskReview.json';
+import ruTerminal from './locales/ru/terminal.json';
+import ruErrors from './locales/ru/errors.json';
+
export const defaultNS = 'common';
export const resources = {
@@ -55,6 +68,19 @@ export const resources = {
taskReview: frTaskReview,
terminal: frTerminal,
errors: frErrors
+ },
+ ru: {
+ common: ruCommon,
+ navigation: ruNavigation,
+ settings: ruSettings,
+ tasks: ruTasks,
+ welcome: ruWelcome,
+ onboarding: ruOnboarding,
+ dialogs: ruDialogs,
+ gitlab: ruGitlab,
+ taskReview: ruTaskReview,
+ terminal: ruTerminal,
+ errors: ruErrors
}
} as const;
diff --git a/apps/desktop/src/shared/i18n/locales/ru/common.json b/apps/desktop/src/shared/i18n/locales/ru/common.json
new file mode 100644
index 0000000000..cb60cfac97
--- /dev/null
+++ b/apps/desktop/src/shared/i18n/locales/ru/common.json
@@ -0,0 +1,1012 @@
+{
+ "competitorAnalysis": {
+ "addCompetitor": "Добавить конкурента",
+ "manualBadge": "Вручную",
+ "noCompetitorsYet": "Конкуренты ещё не добавлены",
+ "addCompetitorToStart": "Добавьте конкурента, чтобы начать",
+ "analysisResults": "Результаты анализа конкурентов",
+ "analysisDescription": "Проанализировано {{count}} конкурентов для выявления рыночных пробелов и возможностей",
+ "visit": "Перейти",
+ "identifiedPainPoints": "Выявленные болевые точки ({{count}})",
+ "noPainPointsIdentified": "Болевые точки не выявлены",
+ "source": "Источник:",
+ "frequency": "Частота:",
+ "opportunity": "Возможность:",
+ "marketInsightsSummary": "Сводка рыночных инсайтов",
+ "topPainPoints": "Ключевые болевые точки:",
+ "differentiatorOpportunities": "Возможности для дифференциации:",
+ "marketTrends": "Рыночные тренды:"
+ },
+ "projectTab": {
+ "settings": "Настройки проекта",
+ "showArchived": "Показать архивные",
+ "hideArchived": "Скрыть архивные",
+ "showArchivedTasks": "Показать архивные задачи",
+ "hideArchivedTasks": "Скрыть архивные задачи",
+ "closeTab": "Закрыть вкладку",
+ "closeTabAriaLabel": "Закрыть вкладку (удаляет проект из приложения)",
+ "addProjectAriaLabel": "Добавить проект"
+ },
+ "accessibility": {
+ "deleteFeatureAriaLabel": "Удалить функцию",
+ "archiveFeatureAriaLabel": "Архивировать функцию",
+ "closeFeatureDetailsAriaLabel": "Закрыть детали функции",
+ "regenerateRoadmapAriaLabel": "Перегенерировать дорожную карту",
+ "repositoryOwnerAriaLabel": "Владелец репозитория",
+ "repositoryVisibilityAriaLabel": "Видимость репозитория",
+ "opensInNewWindow": "открывается в новом окне",
+ "visitExternalLink": "Открыть {{name}} (открывается в новом окне)",
+ "upgradeSubscriptionAriaLabel": "Улучшить подписку (открывается в новом окне)",
+ "learnMoreAriaLabel": "Узнать больше (открывается в новом окне)",
+ "toggleFolder": "Переключить папку {{name}}",
+ "expandFolder": "Развернуть папку {{name}}",
+ "collapseFolder": "Свернуть папку {{name}}",
+ "newConversationAriaLabel": "Новый разговор",
+ "saveEditAriaLabel": "Сохранить",
+ "cancelEditAriaLabel": "Отменить",
+ "moreOptionsAriaLabel": "Дополнительные параметры",
+ "closePanelAriaLabel": "Закрыть панель",
+ "openOnGitHubAriaLabel": "Открыть на GitHub (открывается в новом окне)",
+ "openOnGitLabAriaLabel": "Открыть на GitLab (открывается в новом окне)",
+ "toggleShowArchivedAriaLabel": "Переключить отображение архивных задач",
+ "clearSelectionAriaLabel": "Сбросить выделение",
+ "selectAllAriaLabel": "Выбрать всё",
+ "showDismissedAriaLabel": "Показать отклонённые",
+ "hideDismissedAriaLabel": "Скрыть отклонённые",
+ "configureAriaLabel": "Настроить",
+ "addMoreAriaLabel": "Добавить ещё",
+ "dismissAllAriaLabel": "Отклонить все идеи",
+ "regenerateIdeasAriaLabel": "Перегенерировать идеи",
+ "dismissAriaLabel": "Отклонить",
+ "browseFilesAriaLabel": "Обзор файлов",
+ "renameAriaLabel": "Переименовать",
+ "deleteAriaLabel": "Удалить",
+ "refreshAriaLabel": "Обновить",
+ "expandAriaLabel": "Развернуть",
+ "collapseAriaLabel": "Свернуть",
+ "selectIdeaAriaLabel": "Выбрать идею: {{title}}",
+ "convertToTaskAriaLabel": "Преобразовать в задачу",
+ "goToTaskAriaLabel": "Перейти к задаче",
+ "reAuthenticateProfileAriaLabel": "Повторная аутентификация профиля",
+ "hideTokenEntryAriaLabel": "Скрыть ввод токена",
+ "enterTokenManuallyAriaLabel": "Ввести токен вручную",
+ "renameProfileAriaLabel": "Переименовать профиль",
+ "deleteProfileAriaLabel": "Удалить профиль"
+ },
+ "buttons": {
+ "save": "Сохранить",
+ "cancel": "Отменить",
+ "skip": "Пропустить",
+ "next": "Далее",
+ "back": "Назад",
+ "close": "Закрыть",
+ "initialize": "Инициализировать",
+ "delete": "Удалить",
+ "confirm": "Подтвердить",
+ "retry": "Повторить",
+ "create": "Создать",
+ "createPR": "Создать PR",
+ "openPR": "Открыть PR",
+ "open": "Открыть",
+ "start": "Запустить",
+ "stop": "Остановить",
+ "refresh": "Обновить",
+ "refreshing": "Обновление...",
+ "merge": "Смержить",
+ "discard": "Отклонить",
+ "switch": "Переключить",
+ "add": "Добавить",
+ "apply": "Применить",
+ "gotIt": "Понятно",
+ "continue": "Продолжить",
+ "saving": "Сохранение...",
+ "deleting": "Удаление..."
+ },
+ "actions": {
+ "save": "Сохранить",
+ "apply": "Применить",
+ "delete": "Удалить",
+ "settings": "Настройки"
+ },
+ "os": {
+ "windows": "Windows",
+ "macos": "macOS",
+ "linux": "Linux",
+ "unknown": "вашу ОС"
+ },
+ "labels": {
+ "loading": "Загрузка...",
+ "error": "Ошибка",
+ "success": "Успешно",
+ "initializing": "Инициализация...",
+ "saving": "Сохранение...",
+ "creating": "Создание...",
+ "noData": "Нет данных",
+ "optional": "Необязательно",
+ "required": "Обязательно",
+ "dismiss": "Отклонить",
+ "important": "Важно",
+ "orphaned": "(осиротевший)"
+ },
+ "selection": {
+ "select": "Выбрать",
+ "done": "Готово",
+ "selected": "Выбрано: {{count}}",
+ "selectAll": "Выбрать все",
+ "clearSelection": "Сбросить выбор",
+ "deleteSelected": "Удалить выбранные",
+ "archiveSelected": "Архивировать выбранные",
+ "selectedOfTotal": "{{selected}} из {{total}} выбрано"
+ },
+ "time": {
+ "justNow": "Только что",
+ "minutesAgo": "{{count}} мин назад",
+ "hoursAgo": "{{count}} ч назад",
+ "daysAgo": "{{count}} д назад"
+ },
+ "errors": {
+ "generic": "Произошла ошибка",
+ "unknownError": "Произошла неизвестная ошибка",
+ "operationFailed": "Операция завершилась неудачно",
+ "networkError": "Ошибка сети",
+ "notFound": "Не найдено",
+ "unauthorized": "Нет доступа",
+ "bulkDeletePartialFailure": "Некоторые воркдеревья не удалось удалить:",
+ "taskNotFoundForWorktree": "Задача не найдена для воркдерева: {{specName}}",
+ "failedToDeleteTaskWorktree": "Не удалось удалить воркдерево задачи: {{specName}}",
+ "terminalWorktreeNotFound": "Воркдерево терминала не найдено: {{name}}",
+ "failedToDeleteTerminalWorktree": "Не удалось удалить воркдерево терминала: {{name}}"
+ },
+ "worktrees": {
+ "deleteSuccess": "Воркдерево '{{branch}}' успешно удалено",
+ "bulkDeleteSuccess_one": "{{count}} воркдерево успешно удалено",
+ "bulkDeleteSuccess_few": "{{count}} воркдерева успешно удалено",
+ "bulkDeleteSuccess_many": "{{count}} воркдеревьев успешно удалено",
+ "bulkDeleteSuccess_other": "{{count}} воркдеревьев успешно удалено"
+ },
+ "notification": {
+ "accountSwitched": "Аккаунт переключён",
+ "swapFrom": "Переключено с",
+ "swapTo": "на",
+ "swapReason": "(переключение: {{reason}})"
+ },
+ "rateLimit": {
+ "title": "Превышен лимит запросов",
+ "resetsAt": "Сбросится {{time}}",
+ "hitLimit": "{{source}} достиг лимита использования",
+ "clickToManage": "Нажмите для управления →",
+ "modalTitle": "Достигнут лимит использования Claude Code",
+ "modalDescription": "Вы достигли лимита использования Claude Code за этот период.",
+ "profile": "Профиль: {{name}}",
+ "autoSwitching": "Автопереключение на {{name}}",
+ "autoSwitchingDescription": "Claude автоматически перезапустится с другим аккаунтом",
+ "resetsTime": "Сбросится {{time}}",
+ "usageRestored": "Ваш лимит будет восстановлен в это время",
+ "switchAccount": "Переключить аккаунт Claude",
+ "useAnotherAccount": "Использовать другой аккаунт",
+ "recommended": "Рекомендуется: у {{name}} доступно больше ресурсов.",
+ "otherSubscriptions": "У вас настроены другие подписки Claude. Переключитесь, чтобы продолжить работу:",
+ "selectAccount": "Выбрать аккаунт...",
+ "switching": "Переключение...",
+ "addNewAccount": "Добавить новый аккаунт...",
+ "addAnotherSubscription": "Добавьте ещё одну подписку Claude для автоматического переключения при достижении лимита.",
+ "addAnotherAccount": "Добавить другой аккаунт:",
+ "connectAccount": "Подключить аккаунт Claude:",
+ "accountNamePlaceholder": "Название аккаунта (например, Работа, Личный)",
+ "willOpenLogin": "Откроется страница входа в Claude для аутентификации нового аккаунта.",
+ "autoSwitchOnRateLimit": "Автопереключение при лимите",
+ "upgradeTitle": "Улучшите план для большего использования",
+ "upgradeDescription": "Улучшите подписку Claude для повышенных лимитов использования.",
+ "upgradeSubscription": "Улучшить подписку",
+ "sources": {
+ "changelog": "Журнал изменений",
+ "task": "Задача",
+ "roadmap": "Дорожная карта",
+ "ideation": "Идеация",
+ "titleGenerator": "Генератор заголовков",
+ "claude": "Claude"
+ },
+ "toast": {
+ "authenticating": "Аутентификация \"{{profileName}}\"",
+ "checkTerminal": "Проверьте раздел «Терминалы агентов» на боковой панели для завершения OAuth-входа.",
+ "authStartFailed": "Не удалось запустить аутентификацию",
+ "addProfileFailed": "Не удалось добавить профиль",
+ "tryAgain": "Пожалуйста, попробуйте снова."
+ },
+ "sdk": {
+ "title": "Лимит Claude Code",
+ "interrupted": "{{source}} был прерван из-за превышения лимита использования.",
+ "proactiveSwap": "✓ Проактивное переключение",
+ "reactiveSwap": "⚡ Реактивное переключение",
+ "proactiveSwapDesc": "Автоматически переключено с {{from}} на {{to}} до достижения лимита.",
+ "reactiveSwapDesc": "Достигнут лимит на {{from}}. Автоматически переключено на {{to}} и перезапущено.",
+ "continueWithoutInterruption": "Ваша работа продолжилась без прерываний.",
+ "rateLimitReached": "Достигнут лимит запросов",
+ "operationStopped": "Операция была остановлена, так как {{account}} достиг лимита использования.",
+ "switchBelow": "Переключитесь на другой аккаунт ниже, чтобы продолжить.",
+ "addAccountToContinue": "Добавьте ещё один аккаунт Claude для продолжения работы.",
+ "upgradeToProButton": "Улучшить до Pro для повышенных лимитов",
+ "resetsLabel": "Сбросится {{time}}",
+ "weeklyLimit": "Недельный лимит — сбрасывается примерно через неделю",
+ "sessionLimit": "Лимит сессии — сбрасывается через несколько часов",
+ "switchAccountRetry": "Переключить аккаунт и повторить",
+ "retrying": "Повтор...",
+ "retry": "Повторить",
+ "autoSwitchRetryLabel": "Автопереключение и повтор при лимите",
+ "add": "Добавить",
+ "whatHappened": "Что произошло:",
+ "whatHappenedDesc": "Операция {{source}} была остановлена, так как ваш аккаунт Claude ({{account}}) достиг лимита использования.",
+ "switchRetryOrAdd": "Вы можете переключиться на другой аккаунт и повторить попытку, или добавить ещё аккаунты выше.",
+ "addOrWait": "Добавьте ещё один аккаунт Claude выше для продолжения работы или подождите сброса лимита.",
+ "close": "Закрыть"
+ }
+ },
+ "prReview": {
+ "reviewing": "Проверяется",
+ "reviewed": "Проверено",
+ "approved": "Одобрено",
+ "changesRequested": "Запрошены изменения",
+ "commented": "Прокомментировано",
+ "readyForFollowup": "Готово к повторной проверке",
+ "readyToMerge": "Готово к слиянию",
+ "pendingPost": "Ожидает публикации",
+ "posted": "Опубликовано",
+ "notReviewed": "Не проверено",
+ "allStatuses": "Все статусы",
+ "allContributors": "Все участники",
+ "searchPlaceholder": "Поиск PR...",
+ "contributors": "Участники",
+ "contributorsSelected": "Участники ({{count}})",
+ "status": "Статус",
+ "filters": "Фильтры",
+ "clearFilters": "Сбросить",
+ "clearSearch": "Очистить поиск",
+ "searchContributors": "Поиск участников...",
+ "selectedCount": "Выбрано: {{count}}",
+ "noResultsFound": "Результаты не найдены",
+ "reset": "Сбросить",
+ "sort": {
+ "label": "Сортировка",
+ "newest": "Новые",
+ "oldest": "Старые",
+ "largest": "Большие"
+ },
+ "pullRequests": "Pull Requests",
+ "open": "открыто",
+ "selectPRToView": "Выберите pull request для просмотра деталей",
+ "loadingPRs": "Загрузка pull requests...",
+ "noOpenPRs": "Нет открытых pull requests",
+ "notConnected": "GitHub не подключён",
+ "connectPrompt": "Подключите аккаунт GitHub для просмотра и проверки pull requests.",
+ "openSettings": "Открыть настройки",
+ "runAIReview": "Запустить AI-проверку",
+ "reviewStarted": "Проверка начата",
+ "analysisInProgress": "AI-анализ в процессе...",
+ "analysisComplete": "Анализ завершён ({{count}} находок)",
+ "findingsPostedToGitHub": "Находки опубликованы на GitHub",
+ "newCommits": "{{count}} новый коммит",
+ "newCommit": "{{count}} новый коммит",
+ "runFollowup": "Запустить повторную проверку",
+ "aiReviewInProgress": "AI-проверка в процессе",
+ "waitingForChanges": "Ожидание изменений",
+ "reviewComplete": "Проверка завершена",
+ "reviewStatus": "Статус проверки",
+ "files": "файлы",
+ "filesChanged": "Изменено файлов: {{count}}",
+ "clickToViewFiles": "Нажмите для просмотра изменённых файлов",
+ "loadingFiles": "Загрузка файлов...",
+ "noFilesAvailable": "Список файлов недоступен",
+ "posting": "Публикация...",
+ "postingApproval": "Публикация одобрения...",
+ "postFindings_one": "Опубликовать {{count}} находку",
+ "postFindings_few": "Опубликовать {{count}} находки",
+ "postFindings_many": "Опубликовать {{count}} находок",
+ "postFindings_other": "Опубликовать {{count}} находок",
+ "approve": "Одобрить",
+ "merge": "Смержить",
+ "mergeViaGitHub": "Слияние через GitHub CLI. Может завершиться неудачей, если правила защиты ветки требуют дополнительных проверок.",
+ "autoApprovePR": "Одобрить PR",
+ "suggestions": "с {{count}} предложениями",
+ "postedFindings_one": "Опубликована {{count}} находка",
+ "postedFindings_few": "Опубликовано {{count}} находки",
+ "postedFindings_many": "Опубликовано {{count}} находок",
+ "postedFindings_other": "Опубликовано {{count}} находок",
+ "resolved_one": "{{count}} решено",
+ "resolved_few": "{{count}} решено",
+ "resolved_many": "{{count}} решено",
+ "resolved_other": "{{count}} решено",
+ "stillOpen_one": "{{count}} ещё открыто",
+ "stillOpen_few": "{{count}} ещё открыто",
+ "stillOpen_many": "{{count}} ещё открыто",
+ "stillOpen_other": "{{count}} ещё открыто",
+ "newIssue_one": "{{count}} новая проблема",
+ "newIssue_few": "{{count}} новые проблемы",
+ "newIssue_many": "{{count}} новых проблем",
+ "newIssue_other": "{{count}} новых проблем",
+ "reviewFailed": "Проверка не удалась",
+ "externalReviewDetected": "Обнаружена внешняя проверка",
+ "reviewStartedExternally": "Эта проверка была запущена из другой сессии",
+ "description": "Описание",
+ "noDescription": "Описание отсутствует.",
+ "followupReviewDetails": "Детали повторной проверки",
+ "aiAnalysisResults": "Результаты AI-анализа",
+ "cancel": "Отменить",
+ "previousReview": "Предыдущая проверка ({{count}} находок)",
+ "findingsPosted": "Опубликовано: {{count}}",
+ "followupInProgress": "Повторный анализ в процессе...",
+ "severity": {
+ "critical": "Блокер",
+ "high": "Обязательно",
+ "medium": "Рекомендуется",
+ "low": "Предложение",
+ "criticalDesc": "Нужно исправить",
+ "highDesc": "Стоит исправить",
+ "mediumDesc": "Улучшить качество",
+ "lowDesc": "К рассмотрению"
+ },
+ "category": {
+ "security": "Безопасность",
+ "logic": "Логика",
+ "quality": "Качество",
+ "performance": "Производительность",
+ "style": "Стиль",
+ "documentation": "Документация",
+ "testing": "Тестирование",
+ "other": "Прочее"
+ },
+ "state": {
+ "open": "Открыто",
+ "closed": "Закрыто",
+ "merged": "Смержено"
+ },
+ "selectCriticalHigh": "Выбрать блокеры/обязательные ({{count}})",
+ "selectAll": "Выбрать все",
+ "clear": "Сбросить",
+ "noIssuesFound": "Проблем не обнаружено! Код выглядит хорошо.",
+ "allFindingsPosted": "Все находки опубликованы на GitHub",
+ "findingsPostedCount_one": "{{count}} находка опубликована на GitHub",
+ "findingsPostedCount_few": "{{count}} находки опубликовано на GitHub",
+ "findingsPostedCount_many": "{{count}} находок опубликовано на GitHub",
+ "findingsPostedCount_other": "{{count}} находок опубликовано на GitHub",
+ "selectedOfTotal": "{{selected}}/{{total}} выбрано",
+ "suggestedFix": "Предлагаемое исправление:",
+ "runAIReviewDesc": "Запустите AI-проверку для анализа этого PR",
+ "newCommitsSinceFollowup_one": "{{count}} новый коммит с момента повторной проверки. Запустите ещё одну повторную проверку.",
+ "newCommitsSinceFollowup_few": "{{count}} новых коммита с момента повторной проверки. Запустите ещё одну повторную проверку.",
+ "newCommitsSinceFollowup_many": "{{count}} новых коммитов с момента повторной проверки. Запустите ещё одну повторную проверку.",
+ "newCommitsSinceFollowup_other": "{{count}} новых коммитов с момента повторной проверки. Запустите ещё одну повторную проверку.",
+ "allIssuesResolved_one": "Все {{count}} проблема решена. Этот PR можно смержить.",
+ "allIssuesResolved_few": "Все {{count}} проблемы решены. Этот PR можно смержить.",
+ "allIssuesResolved_many": "Все {{count}} проблем решены. Этот PR можно смержить.",
+ "allIssuesResolved_other": "Все {{count}} проблем решены. Этот PR можно смержить.",
+ "nonBlockingSuggestions_one": "{{resolved}} решено. Осталось {{suggestions}} не блокирующее предложение.",
+ "nonBlockingSuggestions_few": "{{resolved}} решено. Осталось {{suggestions}} не блокирующих предложения.",
+ "nonBlockingSuggestions_many": "{{resolved}} решено. Осталось {{suggestions}} не блокирующих предложений.",
+ "nonBlockingSuggestions_other": "{{resolved}} решено. Осталось {{suggestions}} не блокирующих предложений.",
+ "blockingIssues": "Блокирующие проблемы",
+ "blockingIssuesDesc_one": "{{resolved}} решено, {{unresolved}} блокирующая проблема ещё открыта.",
+ "blockingIssuesDesc_few": "{{resolved}} решено, {{unresolved}} блокирующих проблемы ещё открыто.",
+ "blockingIssuesDesc_many": "{{resolved}} решено, {{unresolved}} блокирующих проблем ещё открыто.",
+ "blockingIssuesDesc_other": "{{resolved}} решено, {{unresolved}} блокирующих проблем ещё открыто.",
+ "newCommitsSinceReview_one": "{{count}} новый коммит с момента проверки. Запустите повторную проверку, чтобы убедиться в устранении проблем.",
+ "newCommitsSinceReview_few": "{{count}} новых коммита с момента проверки. Запустите повторную проверку, чтобы убедиться в устранении проблем.",
+ "newCommitsSinceReview_many": "{{count}} новых коммитов с момента проверки. Запустите повторную проверку, чтобы убедиться в устранении проблем.",
+ "newCommitsSinceReview_other": "{{count}} новых коммитов с момента проверки. Запустите повторную проверку, чтобы убедиться в устранении проблем.",
+ "noBlockingIssues": "Блокирующих проблем не обнаружено. Этот PR можно смержить.",
+ "findingsPostedWaiting_one": "{{count}} находка опубликована. Ожидание устранения проблем участником.",
+ "findingsPostedWaiting_few": "{{count}} находки опубликовано. Ожидание устранения проблем участником.",
+ "findingsPostedWaiting_many": "{{count}} находок опубликовано. Ожидание устранения проблем участником.",
+ "findingsPostedWaiting_other": "{{count}} находок опубликовано. Ожидание устранения проблем участником.",
+ "findingsPostedNoBlockers_one": "{{count}} находка опубликована. Блокирующих проблем не осталось.",
+ "findingsPostedNoBlockers_few": "{{count}} находки опубликовано. Блокирующих проблем не осталось.",
+ "findingsPostedNoBlockers_many": "{{count}} находок опубликовано. Блокирующих проблем не осталось.",
+ "findingsPostedNoBlockers_other": "{{count}} находок опубликовано. Блокирующих проблем не осталось.",
+ "needsAttention": "Требует внимания",
+ "findingsNeedPosting_one": "{{count}} находку необходимо опубликовать на GitHub.",
+ "findingsNeedPosting_few": "{{count}} находки необходимо опубликовать на GitHub.",
+ "findingsNeedPosting_many": "{{count}} находок необходимо опубликовать на GitHub.",
+ "findingsNeedPosting_other": "{{count}} находок необходимо опубликовать на GitHub.",
+ "findingsFoundSelectPost_one": "Найдена {{count}} находка. Выберите и опубликуйте на GitHub.",
+ "findingsFoundSelectPost_few": "Найдено {{count}} находки. Выберите и опубликуйте на GitHub.",
+ "findingsFoundSelectPost_many": "Найдено {{count}} находок. Выберите и опубликуйте на GitHub.",
+ "findingsFoundSelectPost_other": "Найдено {{count}} находок. Выберите и опубликуйте на GitHub.",
+ "reviewLogs": "Логи проверки",
+ "followup": "Повторная проверка",
+ "initial": "Первичная",
+ "rerunFollowup": "Перезапустить повторную проверку",
+ "retryReview": "Повторить проверку",
+ "rerunReview": "Перезапустить проверку",
+ "updateBranch": "Обновить ветку",
+ "updatingBranch": "Обновление...",
+ "branchUpdated": "Ветка обновлена",
+ "branchUpdateFailed": "Не удалось обновить ветку",
+ "allPRsLoaded": "Все PR загружены",
+ "maxPRsShown": "Показаны первые 100 PR",
+ "loadMore": "Загрузить ещё",
+ "loadingMore": "Загрузка...",
+ "workflowsAwaitingApproval_one": "{{count}} воркфлоу ожидает одобрения",
+ "workflowsAwaitingApproval_few": "{{count}} воркфлоу ожидают одобрения",
+ "workflowsAwaitingApproval_many": "{{count}} воркфлоу ожидают одобрения",
+ "workflowsAwaitingApproval_other": "{{count}} воркфлоу ожидают одобрения",
+ "blockedByWorkflows": "Заблокировано",
+ "workflowsAwaitingDescription": "Этот PR из форка и требует одобрения воркфлоу перед запуском CI-проверок. Одобрите воркфлоу для продолжения.",
+ "viewOnGitHub": "Просмотр",
+ "approveWorkflow": "Одобрить",
+ "approveAllWorkflows": "Одобрить все воркфлоу",
+ "postCleanReview": "Опубликовать чистую проверку",
+ "postingCleanReview": "Публикация...",
+ "cleanReviewPosted": "Чистая проверка опубликована",
+ "cleanReviewMessageTitle": "## ✅ Aperant PR Review - ПРОЙДЕНО",
+ "cleanReviewMessageStatus": "**Статус:** Весь код в порядке",
+ "cleanReviewMessageFooter": "*Автоматическая проверка не обнаружила проблем. Сгенерировано Aperant.*",
+ "failedPostCleanReview": "Не удалось опубликовать чистую проверку",
+ "viewErrorDetails": "Показать детали",
+ "hideErrorDetails": "Скрыть детали",
+ "postBlockedStatus": "Опубликовать статус",
+ "postingBlockedStatus": "Публикация...",
+ "blockedStatusPosted": "Статус опубликован в PR",
+ "blockedStatusMessageTitle": "## 🤖 Aperant PR Review",
+ "blockedStatusMessageFooter": "*Проверка выявила блокирующие проблемы, которые необходимо устранить перед мержем. Сгенерировано Aperant.*",
+ "failedPostBlockedStatus": "Не удалось опубликовать статус",
+ "branchSynced_one": "Ветка синхронизирована ({{count}} коммит от базовой)",
+ "branchSynced_few": "Ветка синхронизирована ({{count}} коммита от базовой)",
+ "branchSynced_many": "Ветка синхронизирована ({{count}} коммитов от базовой)",
+ "branchSynced_other": "Ветка синхронизирована ({{count}} коммитов от базовой)",
+ "newCommitsOverlap_one": "{{count}} новый коммит ({{files}} файл(ов) с находками изменён)",
+ "newCommitsOverlap_few": "{{count}} новых коммита ({{files}} файл(ов) с находками изменено)",
+ "newCommitsOverlap_many": "{{count}} новых коммитов ({{files}} файл(ов) с находками изменено)",
+ "newCommitsOverlap_other": "{{count}} новых коммитов ({{files}} файл(ов) с находками изменено)",
+ "newCommitsNoOverlap_one": "{{count}} новый коммит (пересечений с находками нет)",
+ "newCommitsNoOverlap_few": "{{count}} новых коммита (пересечений с находками нет)",
+ "newCommitsNoOverlap_many": "{{count}} новых коммитов (пересечений с находками нет)",
+ "newCommitsNoOverlap_other": "{{count}} новых коммитов (пересечений с находками нет)",
+ "verifyChanges": "Проверить изменения",
+ "verifyAnyway": "Проверить",
+ "runFollowupAnyway": "Запустить повторную проверку, даже если файлы не пересекаются",
+ "disputed": "Оспорено",
+ "disputedByValidator": "Оспорено валидатором ({{count}})",
+ "crossValidatedBy": "Подтверждено {{count}} агентами",
+ "disputedSectionHint": "Эти находки были сообщены специалистами, но оспорены валидатором. Вы всё равно можете выбрать и опубликовать их.",
+ "logs": {
+ "agentActivity": "Активность агента",
+ "showMore": "Показать ещё {{count}}",
+ "hideMore": "Скрыть {{count}}"
+ }
+ },
+ "downloads": {
+ "toggleExpand": "Переключить детали загрузки",
+ "downloading_one": "Загрузка {{count}} модели",
+ "downloading_few": "Загрузка {{count}} моделей",
+ "downloading_many": "Загрузка {{count}} моделей",
+ "downloading_other": "Загрузка {{count}} моделей",
+ "complete_one": "{{count}} загрузка завершена",
+ "complete_few": "{{count}} загрузки завершено",
+ "complete_many": "{{count}} загрузок завершено",
+ "complete_other": "{{count}} загрузок завершено",
+ "failed_one": "{{count}} загрузка не удалась",
+ "failed_few": "{{count}} загрузки не удались",
+ "failed_many": "{{count}} загрузок не удалось",
+ "failed_other": "{{count}} загрузок не удалось",
+ "clearAll": "Очистить все завершённые загрузки",
+ "done": "Готово",
+ "failedLabel": "Не удалось",
+ "starting": "Запуск..."
+ },
+ "insights": {
+ "suggestedTask": "Предлагаемая задача",
+ "creating": "Создание...",
+ "taskCreated": "Задача создана",
+ "createTask": "Создать задачу",
+ "chatHistory": "История чата",
+ "archive": "Архивировать",
+ "unarchive": "Разархивировать",
+ "archiveSelected": "Архивировать выбранные",
+ "showArchived": "Показать архивные",
+ "hideArchived": "Скрыть архивные",
+ "bulkDeleteTitle": "Удалить разговоры",
+ "bulkDeleteDescription": "Вы уверены, что хотите удалить {{count}} разговор(а/ов)? Это действие нельзя отменить.",
+ "bulkDeleteConfirm": "Удалить {{count}} разговор(а/ов)",
+ "noConversations": "Нет разговоров",
+ "archived": "Архивировано",
+ "conversationsToDelete": "Разговоры для удаления",
+ "archiveConfirmDescription": "Вы уверены, что хотите архивировать выбранные разговоры?",
+ "archiveConfirmTitle": "Архивировать разговоры",
+ "archiveConfirmButton": "Архивировать {{count}} разговор(а/ов)",
+ "deleteTitle": "Удалить разговор",
+ "deleteDescription": "Вы уверены, что хотите удалить этот разговор? Это действие нельзя отменить.",
+ "selectMode": "Выбрать",
+ "exitSelectMode": "Готово",
+ "today": "Сегодня",
+ "yesterday": "Вчера",
+ "daysAgo": "{{count}} дней назад",
+ "messageCount_one": "{{count}} сообщение",
+ "messageCount_few": "{{count}} сообщения",
+ "messageCount_many": "{{count}} сообщений",
+ "messageCount_other": "{{count}} сообщений",
+ "images": {
+ "pasteHint": "Вставьте изображение или снимок экрана",
+ "dropHint": "Перетащите изображение сюда",
+ "screenshotButton": "Прикрепить снимок экрана",
+ "removeImage": "Удалить изображение",
+ "imageCount_one": "Прикреплено {{count}} изображение",
+ "imageCount_few": "Прикреплено {{count}} изображения",
+ "imageCount_many": "Прикреплено {{count}} изображений",
+ "imageCount_other": "Прикреплено {{count}} изображений",
+ "maxImagesReached": "Достигнуто максимальное количество изображений",
+ "invalidType": "Недопустимый тип файла. Используйте PNG, JPEG, GIF или WebP.",
+ "processFailed": "Не удалось обработать изображение",
+ "dragOver": "Перетащите изображение для прикрепления",
+ "analysisUnsupported": "Примечание: анализ изображений пока не поддерживается. Изображения сохранены для справки, но не могут быть проанализированы моделью.",
+ "screenshotTooLarge": "Снимок экрана слишком большой ({{size}}МБ). Максимальный размер — {{max}}МБ. Попробуйте захватить меньшую область.",
+ "notAnalyzed": "Изображения сохранены для справки, но не были проанализированы моделью."
+ }
+ },
+ "ideation": {
+ "converting": "Преобразование...",
+ "convertToTask": "Преобразовать в задачу Auto-Build",
+ "dismissIdea": "Отклонить идею",
+ "description": "Описание",
+ "rationale": "Обоснование",
+ "goToTask": "Перейти к задаче",
+ "conversionFailed": "Преобразование не удалось",
+ "conversionFailedDescription": "Не удалось преобразовать идею в задачу",
+ "conversionError": "Ошибка преобразования",
+ "conversionErrorDescription": "При преобразовании идеи произошла ошибка"
+ },
+ "issues": {
+ "loadingMore": "Загрузка ещё...",
+ "scrollForMore": "Прокрутите для загрузки",
+ "allLoaded": "Все задачи загружены"
+ },
+ "usage": {
+ "dataUnavailable": "Данные об использовании недоступны",
+ "dataUnavailableDescription": "Эндпоинт мониторинга использования для этого провайдера недоступен или не поддерживается.",
+ "activeAccount": "Активный аккаунт",
+ "usageAlert": "Предупреждение об использовании",
+ "accountExceedsThreshold": "Использование аккаунта превышает порог 90%",
+ "authentication": "Аутентификация",
+ "authenticationAriaLabel": "Аутентификация: {{provider}}",
+ "authenticationDetails": "Детали аутентификации",
+ "apiProfile": "API-профиль",
+ "apiKey": "API-ключ",
+ "oauth": "OAuth",
+ "codex": "Codex",
+ "codexSubscription": "Подписка Codex",
+ "claudeCode": "Claude Code",
+ "claudeCodeSubscription": "Подписка Claude Code",
+ "subscription": "Подписка",
+ "provider": "Провайдер",
+ "providerAnthropic": "Anthropic",
+ "providerZai": "Z.AI",
+ "providerZhipu": "ZHIPU AI",
+ "crossProvider": "Кросс-провайдер",
+ "crossProviderConfig": "Кросс-провайдер",
+ "crossProviderUsage": "Использование кросс-провайдера",
+ "crossProviderActive": "Кросс-провайдер активен",
+ "providerOpenRouter": "OpenRouter",
+ "providerUnknown": "Неизвестно",
+ "providerOpenAI": "OpenAI",
+ "providerGoogle": "Google AI",
+ "providerMistral": "Mistral",
+ "providerGroq": "Groq",
+ "providerXai": "xAI",
+ "providerBedrock": "AWS Bedrock",
+ "providerAzure": "Azure OpenAI",
+ "providerOllama": "Ollama",
+ "providerCustomEndpoint": "Пользовательский эндпоинт",
+ "billingSubscription": "Подписка",
+ "billingPayPerUse": "Оплата по использованию",
+ "unlimited": "Безлимитно",
+ "unlimitedApiKey": "Безлимитно (API-ключ)",
+ "noUsageMonitoring": "Мониторинг использования недоступен для этого провайдера",
+ "subscriptionBadge": "Подписка",
+ "subscriptionLimitsApply": "Действуют лимиты скорости",
+ "subscriptionMonitoringComingSoon": "У этого аккаунта с подпиской есть лимиты скорости, но мониторинг использования пока недоступен для этого провайдера.",
+ "queuePosition": "Позиция в очереди",
+ "inUse": "Используется",
+ "noAccount": "Нет аккаунта",
+ "noAccountDescription": "Добавьте аккаунт в настройках для начала работы",
+ "accountName": "Аккаунт",
+ "profile": "Профиль",
+ "id": "ID",
+ "created": "Создан",
+ "apiEndpoint": "API-эндпоинт",
+ "sessionQuota": "Квота сессии",
+ "notAvailable": "Н/Д",
+ "usageStatusAriaLabel": "Статус использования",
+ "usageBreakdown": "Разбивка использования",
+ "used": "использовано",
+ "loading": "Загрузка...",
+ "sessionDefault": "Сессия",
+ "weeklyDefault": "Неделя",
+ "resetsInHours": "Сброс через {{hours}}ч {{minutes}}м",
+ "resetsInDays": "Сброс через {{days}}д {{hours}}ч",
+ "window5Hour": "5-часовое окно",
+ "window7Day": "7-дневное окно",
+ "window5HoursQuota": "Квота на 5 часов",
+ "windowMonthlyToolsQuota": "Месячная квота инструментов",
+ "otherAccounts": "Другие аккаунты",
+ "next": "Далее",
+ "weeklyLimitReached": "Достигнут недельный лимит",
+ "sessionLimitReached": "Достигнут лимит сессии",
+ "notAuthenticated": "Не аутентифицирован",
+ "needsReauth": "Требует повторной авторизации",
+ "reauthRequired": "Требуется повторная аутентификация",
+ "reauthRequiredDescription": "Ваша сессия истекла. Пройдите повторную аутентификацию для просмотра использования и продолжения работы с этим аккаунтом.",
+ "reauthButton": "Повторная аутентификация",
+ "clickToOpenSettings": "Нажмите для открытия настроек →",
+ "sessionShort": "Использование за 5-часовую сессию",
+ "weeklyShort": "Использование за 7-дневную неделю",
+ "swap": "Переключить"
+ },
+ "oauth": {
+ "enterCode": "Ввод кода вручную (резервный вариант)",
+ "enterCodeDescription": "Этот диалог нужен только если браузер не выполнил автоматическое перенаправление. Если аутентификация уже завершена в вашем браузере, вы можете закрыть этот диалог.",
+ "fallbackNote": "Используйте это только если вы видите страницу «Вставьте в Claude Code» в вашем браузере.",
+ "step1": "Завершите авторизацию в вашем браузере",
+ "step2": "Если вы видите страницу с кодом, скопируйте показанный код",
+ "step3": "Вставьте код ниже и нажмите «Отправить»",
+ "codeLabel": "Код авторизации",
+ "codePlaceholder": "Вставьте ваш код здесь (только при необходимости)...",
+ "codeHint": "Код — это длинная строка, отображаемая только при неудаче автоматического перенаправления",
+ "submit": "Отправить",
+ "submitting": "Отправка...",
+ "codeSubmitted": "Код отправлен",
+ "codeSubmittedDescription": "Аутентификация должна завершиться в ближайшее время. Проверьте терминал для подтверждения.",
+ "codeSubmitFailed": "Не удалось отправить код",
+ "codeSubmitFailedDescription": "Пожалуйста, попробуйте снова или скопируйте код вручную в терминал.",
+ "authenticateTitle": "Аутентификация в Claude",
+ "authenticateDescription": "Aperant требует аутентификации Claude AI для AI-функций, таких как генерация дорожной карты, автоматизация задач и идеация.",
+ "authenticateTerminalInfo": "Откроется терминал с Claude CLI для аутентификации. Ваши учётные данные хранятся надёжно и действительны в течение 1 года.",
+ "completeAuthTitle": "Завершить аутентификацию",
+ "terminalOpened": "Открылось окно терминала с Claude CLI.",
+ "completeStepsTitle": "Выполните следующие шаги в терминале:",
+ "stepTypeLogin": "Введите /login и нажмите Enter",
+ "stepBrowserOpen": "Откроется ваш браузер для аутентификации Claude",
+ "stepCompleteOAuth": "Завершите OAuth-процесс в вашем браузере",
+ "stepReturnAndVerify": "Вернитесь сюда и нажмите Подтвердить аутентификацию",
+ "verifyAuth": "Подтвердить аутентификацию",
+ "verifyingAuth": "Проверка аутентификации...",
+ "checkingCredentials": "Проверка ваших учётных данных Claude.",
+ "successTitle": "Аутентификация успешна!",
+ "connectedAs": "Подключено как {{email}}",
+ "credentialsSaved": "Ваши учётные данные Claude сохранены",
+ "canUseFeatures": "Теперь вы можете использовать все AI-функции Aperant",
+ "authFailed": "Аутентификация не удалась",
+ "skipForNow": "Пропустить",
+ "manualTokenEntry": "Ручной ввод токена",
+ "tokenCommandHint": "Выполните claude setup-token для получения токена",
+ "emailOptionalPlaceholder": "Email (необязательно, для отображения)",
+ "saveToken": "Сохранить токен",
+ "accountNamePlaceholder": "Название аккаунта (например, Работа, Личный)",
+ "hasAuthenticatedAccount": "У вас есть хотя бы один аутентифицированный аккаунт Claude. Вы можете перейти к следующему шагу.",
+ "authNotDetected": "Аутентификация не обнаружена. Сначала выполните /login в терминале.",
+ "noProfileSelected": "Профиль для проверки не выбран",
+ "alerts": {
+ "profileCreatedAuthFailed": "Профиль создан, но не удалось запустить аутентификацию: {{error}}",
+ "authPrepareFailed": "Не удалось подготовить аутентификацию: {{error}}",
+ "authStartFailedMessage": "Не удалось запустить аутентификацию. Пожалуйста, попробуйте снова."
+ },
+ "badges": {
+ "default": "По умолчанию",
+ "active": "Активный",
+ "authenticated": "Аутентифицирован",
+ "needsAuth": "Требует авторизации"
+ },
+ "buttons": {
+ "authenticate": "Аутентифицировать",
+ "setActive": "Сделать активным",
+ "back": "Назад",
+ "skip": "Пропустить",
+ "continue": "Продолжить"
+ },
+ "toast": {
+ "tokenSaved": "Токен сохранён",
+ "tokenSavedDescription": "Ваш токен Claude надёжно сохранён.",
+ "tokenSaveFailed": "Не удалось сохранить токен",
+ "addProfileFailed": "Не удалось добавить профиль",
+ "tryAgain": "Пожалуйста, попробуйте снова."
+ },
+ "configureTitle": "Настройка аккаунтов Claude",
+ "addAccountsDesc": "Добавьте и аутентифицируйте ваши аккаунты Claude для использования AI-функций.",
+ "multiAccountInfo": "Вы можете добавить несколько аккаунтов Claude. Активный аккаунт будет использоваться для AI-функций. Вы можете переключать аккаунты в любое время.",
+ "keychainTitle": "Безопасное хранилище",
+ "keychainDescription": "Ваши токены аутентификации надёжно хранятся в macOS Keychain.",
+ "noAccountsYet": "Аккаунты ещё не добавлены. Добавьте ваш первый аккаунт Claude ниже."
+ },
+ "authTerminal": {
+ "failedToCreate": "Не удалось создать терминал",
+ "unknownError": "Неизвестная ошибка",
+ "instructionTitle": "Аутентификация Claude",
+ "step1": "Нажмите Enter для запуска аутентификации",
+ "step2": "Завершите аутентификацию в вашем браузере",
+ "step3": "Вернитесь сюда — аутентификация будет обнаружена автоматически",
+ "authFailed": "Аутентификация не удалась",
+ "connecting": "Подключение...",
+ "authenticate": "Аутентификация: {{profileName}}",
+ "authenticatedAs": "Аутентифицирован как {{email}}",
+ "authenticated": "Аутентифицирован!",
+ "authError": "Ошибка аутентификации",
+ "successMessage": "Аутентификация успешна! Закрытие..."
+ },
+ "profileCreated": {
+ "title": "Профиль «{{profileName}}» создан.",
+ "instructions": "Для аутентификации этого профиля:",
+ "step1": "Перейдите в Настройки > Интеграции",
+ "step2": "Найдите профиль в разделе «Аккаунты Claude»",
+ "step3": "Нажмите «Аутентифицировать» для завершения входа",
+ "footer": "Аккаунт станет доступен после завершения аутентификации."
+ },
+ "roadmap": {
+ "taskCompleted": "Выполнено",
+ "taskDeleted": "Удалено",
+ "taskArchived": "Архивировано",
+ "showMoreFeatures_one": "Показать ещё {{count}} функцию",
+ "showMoreFeatures_few": "Показать ещё {{count}} функции",
+ "showMoreFeatures_many": "Показать ещё {{count}} функций",
+ "showMoreFeatures_other": "Показать ещё {{count}} функций",
+ "showLessFeatures": "Показать меньше",
+ "archiveFeature": "Архивировать",
+ "archiveFeatureConfirmTitle": "Архивировать функцию?",
+ "archiveFeatureConfirmDescription": "Это удалит «{{title}}» из вашей дорожной карты.",
+ "goToTask": "Перейти к задаче",
+ "convertToTask": "Преобразовать в задачу Auto-Build",
+ "build": "Собрать",
+ "task": "Задача",
+ "viewTask": "Просмотреть задачу"
+ },
+ "roadmapGeneration": {
+ "progress": "Прогресс",
+ "elapsed": "Прошло: {{time}}",
+ "stillWorking": "Всё ещё работаем...",
+ "stopping": "Остановка...",
+ "stop": "Остановить",
+ "stopTooltip": "Остановить генерацию",
+ "phases": {
+ "analyzing": {
+ "label": "Анализ",
+ "description": "Анализ структуры проекта и кодовой базы..."
+ },
+ "discovering": {
+ "label": "Исследование",
+ "description": "Исследование целевой аудитории и потребностей пользователей..."
+ },
+ "generating": {
+ "label": "Генерация",
+ "description": "Генерация дорожной карты функций..."
+ },
+ "complete": {
+ "label": "Завершено",
+ "description": "Генерация дорожной карты завершена!"
+ },
+ "error": {
+ "label": "Ошибка",
+ "description": "Генерация не удалась"
+ }
+ },
+ "steps": {
+ "analyze": "Анализ",
+ "discover": "Исследование",
+ "generate": "Генерация"
+ }
+ },
+ "auth": {
+ "failure": {
+ "title": "Требуется аутентификация",
+ "profileLabel": "Профиль",
+ "unknownProfile": "Неизвестный профиль",
+ "tokenExpired": "Ваш токен аутентификации истёк.",
+ "tokenInvalid": "Ваш токен аутентификации недействителен.",
+ "tokenMissing": "Токен аутентификации не найден.",
+ "authFailed": "Аутентификация не удалась.",
+ "description": "Пожалуйста, повторно аутентифицируйте ваш профиль Claude для продолжения использования Aperant.",
+ "taskAffected": "Затронутая задача",
+ "technicalDetails": "Технические детали",
+ "goToSettings": "Перейти в настройки"
+ }
+ },
+ "git": {
+ "branchGroups": {
+ "local": "Локальные ветки",
+ "remote": "Удалённые ветки"
+ },
+ "branchType": {
+ "local": "Локальная",
+ "remote": "Удалённая"
+ }
+ },
+ "githubErrors": {
+ "rateLimitTitle": "Достигнут лимит GitHub",
+ "authTitle": "Требуется аутентификация GitHub",
+ "permissionTitle": "Отказано в доступе GitHub",
+ "notFoundTitle": "Ресурс GitHub не найден",
+ "networkTitle": "Ошибка подключения к GitHub",
+ "unknownTitle": "Ошибка GitHub",
+ "rateLimitMessage": "Достигнут лимит GitHub API. Подождите немного перед повторной попыткой.",
+ "rateLimitMessageMinutes": "Достигнут лимит GitHub API. Подождите {{minutes}} минут(у) перед повторной попыткой.",
+ "rateLimitMessageHours": "Достигнут лимит GitHub API. Лимит сбросится примерно через {{hours}} час(а).",
+ "authMessage": "Аутентификация GitHub не удалась. Проверьте ваш токен GitHub в настройках и попробуйте снова.",
+ "permissionMessage": "Отказано в доступе GitHub. Возможно, у вашего токена нет необходимых прав. Проверьте права токена в настройках.",
+ "permissionMessageScopes": "Отказано в доступе GitHub. Вашему токену не хватает обязательных областей доступа: {{scopes}}. Обновите токен GitHub в настройках.",
+ "notFoundMessage": "Запрошенный ресурс GitHub не найден. Убедитесь, что репозиторий существует и у вас есть к нему доступ.",
+ "networkMessage": "Не удаётся подключиться к GitHub. Проверьте интернет-соединение и попробуйте снова.",
+ "unknownMessage": "При обращении к GitHub произошла непредвиденная ошибка. Пожалуйста, попробуйте снова.",
+ "resetsIn": "Сбрасывается через {{time}}",
+ "countdownHoursMinutes": "{{hours}}ч {{minutes}}м",
+ "countdownMinutesSeconds": "{{minutes}}м {{seconds}}с",
+ "rateLimitExpired": "Лимит сброшен. Теперь можно повторить попытку.",
+ "requiredScopes": "Обязательные области доступа"
+ },
+ "roadmapProgress": {
+ "elapsedTime": "Прошло",
+ "lastActivity": "Последняя активность",
+ "staleWarning": "Активности нет уже некоторое время",
+ "staleWarningTooltip": "Эта задача не проявляет активности уже {{minutes}} минут",
+ "phases": {
+ "analyzing": {
+ "label": "Анализ",
+ "description": "Анализ структуры проекта и кодовой базы..."
+ },
+ "discovering": {
+ "label": "Исследование",
+ "description": "Исследование целевой аудитории и потребностей пользователей..."
+ },
+ "generating": {
+ "label": "Генерация",
+ "description": "Генерация дорожной карты функций..."
+ },
+ "complete": {
+ "label": "Завершено",
+ "description": "Генерация дорожной карты завершена!"
+ },
+ "error": {
+ "label": "Ошибка",
+ "description": "Генерация не удалась"
+ }
+ },
+ "steps": {
+ "analyze": "Анализ",
+ "discover": "Исследование",
+ "generate": "Генерация"
+ },
+ "processing": "Обработка",
+ "processActiveTooltip": "Процесс активно выполняется",
+ "stopGeneration": "Остановить генерацию",
+ "stopping": "Остановка...",
+ "progress": "Прогресс",
+ "lastActivityPrefix": "последняя активность",
+ "lastProgressUpdateTooltip": "Последнее полученное обновление прогресса"
+ },
+ "memory": {
+ "types": {
+ "gotcha": "Ловушка",
+ "decision": "Решение",
+ "preference": "Предпочтение",
+ "pattern": "Паттерн",
+ "requirement": "Требование",
+ "error_pattern": "Паттерн ошибки",
+ "module_insight": "Инсайт модуля",
+ "prefetch_pattern": "Паттерн предзагрузки",
+ "work_state": "Рабочее состояние",
+ "causal_dependency": "Причинная зависимость",
+ "task_calibration": "Калибровка задачи",
+ "e2e_observation": "E2E-наблюдение",
+ "dead_end": "Тупик",
+ "work_unit_outcome": "Результат рабочей единицы",
+ "workflow_recipe": "Рецепт воркфлоу",
+ "context_cost": "Стоимость контекста"
+ },
+ "filters": {
+ "all": "Все",
+ "patterns": "Паттерны",
+ "errors": "Ошибки и ловушки",
+ "decisions": "Решения",
+ "insights": "Инсайты кода",
+ "calibration": "Калибровка"
+ },
+ "badges": {
+ "needsReview": "Требует проверки",
+ "verified": "Проверено",
+ "pinned": "Закреплено",
+ "confidence": "Уверенность"
+ },
+ "sources": {
+ "agent_explicit": "Агент",
+ "observer_inferred": "Наблюдатель",
+ "qa_auto": "QA",
+ "mcp_auto": "MCP",
+ "commit_auto": "Коммит",
+ "user_taught": "Пользователь"
+ },
+ "health": {
+ "totalMemories": "Всего воспоминаний",
+ "avgConfidence": "Средняя уверенность",
+ "verified": "Проверено"
+ },
+ "info": {
+ "database": "База данных",
+ "path": "Путь",
+ "embedding": "Эмбеддинг",
+ "memories": "Воспоминания"
+ },
+ "status": {
+ "title": "Статус памяти",
+ "connected": "Подключено",
+ "notAvailable": "Недоступно",
+ "notConfigured": "Система памяти не настроена",
+ "enableInSettings": "Для включения памяти настройте её в параметрах проекта."
+ },
+ "search": {
+ "title": "Поиск по памяти",
+ "placeholder": "Поиск воспоминаний...",
+ "resultsCount_one": "Найден {{count}} результат",
+ "resultsCount_few": "Найдено {{count}} результата",
+ "resultsCount_many": "Найдено {{count}} результатов",
+ "resultsCount_other": "Найдено {{count}} результатов"
+ },
+ "browser": {
+ "title": "Браузер памяти",
+ "countOf": "{{filtered}} из {{total}} воспоминаний"
+ },
+ "empty": "Воспоминаний пока нет. Они создаются автоматически по мере работы агентов над задачами.",
+ "emptyFilter": "Нет воспоминаний, соответствующих выбранному фильтру.",
+ "showAll": "Показать все воспоминания",
+ "expand": "Развернуть",
+ "collapse": "Свернуть",
+ "sections": {
+ "whatWorked": "Что сработало",
+ "whatFailed": "Что не сработало",
+ "approach": "Подход",
+ "recommendations": "Рекомендации",
+ "patterns": "Паттерны",
+ "gotchas": "Ловушки",
+ "changedFiles": "Изменённые файлы",
+ "fileInsights": "Инсайты файлов",
+ "subtasksCompleted": "Выполненные подзадачи",
+ "relatedFiles": "Связанные файлы",
+ "tags": "Теги",
+ "approachTried": "Испробованный подход",
+ "whyItFailed": "Почему не сработало",
+ "alternativeUsed": "Использованная альтернатива",
+ "steps": "Шаги"
+ },
+ "actions": {
+ "verify": "Подтвердить",
+ "pin": "Закрепить",
+ "unpin": "Открепить",
+ "deprecate": "Удалить"
+ }
+ },
+ "context": {
+ "tabs": {
+ "projectIndex": "Индекс проекта",
+ "memories": "Воспоминания"
+ }
+ },
+ "prStatus": {
+ "ci": {
+ "success": "CI пройден",
+ "pending": "CI ожидает",
+ "failure": "CI не пройден",
+ "successTooltip": "Все проверки CI пройдены",
+ "pendingTooltip": "Проверки CI ещё выполняются",
+ "failureTooltip": "Одна или несколько проверок CI не пройдены"
+ },
+ "review": {
+ "approved": "Одобрено",
+ "changesRequested": "Запрошены изменения",
+ "pending": "Ожидание проверки",
+ "approvedTooltip": "Этот PR одобрен",
+ "changesRequestedTooltip": "По этому PR запрошены изменения",
+ "pendingTooltip": "Ожидание проверки"
+ },
+ "merge": {
+ "ready": "Готово к слиянию",
+ "blocked": "Слияние заблокировано",
+ "conflict": "Есть конфликты",
+ "readyTooltip": "Этот PR готов к слиянию",
+ "blockedTooltip": "Этот PR не может быть смержен из-за блокирующих условий",
+ "conflictTooltip": "В этом PR есть конфликты слияния, которые нужно разрешить"
+ }
+ }
+}
diff --git a/apps/desktop/src/shared/i18n/locales/ru/dialogs.json b/apps/desktop/src/shared/i18n/locales/ru/dialogs.json
new file mode 100644
index 0000000000..aba652fe56
--- /dev/null
+++ b/apps/desktop/src/shared/i18n/locales/ru/dialogs.json
@@ -0,0 +1,239 @@
+{
+ "initialize": {
+ "title": "Инициализация Aperant",
+ "description": "В этом проекте не инициализирован Aperant. Хотите настроить его сейчас?",
+ "willDo": "Будет выполнено:",
+ "createFolder": "Создание папки .auto-claude в вашем проекте",
+ "copyFramework": "Копирование файлов фреймворка Aperant",
+ "setupSpecs": "Настройка директории спецификаций для ваших задач",
+ "sourcePathNotConfigured": "Исходный путь не настроен",
+ "sourcePathNotConfiguredDescription": "Пожалуйста, укажите исходный путь Aperant в настройках приложения перед инициализацией.",
+ "initFailed": "Ошибка инициализации",
+ "initFailedDescription": "Не удалось инициализировать Aperant. Пожалуйста, попробуйте снова."
+ },
+ "gitSetup": {
+ "title": "Требуется Git-репозиторий",
+ "description": "Aperant использует git для безопасной разработки функций в изолированных рабочих пространствах",
+ "notGitRepo": "Эта папка не является git-репозиторием",
+ "noCommits": "Git-репозиторий не содержит коммитов",
+ "needsInit": "Необходимо инициализировать Git, прежде чем Aperant сможет управлять вашим кодом.",
+ "needsCommit": "Для создания воркдеревьев Aperant требуется хотя бы один коммит.",
+ "willSetup": "Мы настроим git за вас:",
+ "initRepo": "Инициализация нового git-репозитория",
+ "createCommit": "Создание начального коммита с вашими текущими файлами",
+ "manual": "Предпочитаете сделать это вручную?",
+ "settingUp": "Настройка Git",
+ "initializingRepo": "Инициализация git-репозитория и создание начального коммита...",
+ "success": "Git инициализирован",
+ "readyToUse": "Ваш проект готов к использованию с Aperant!"
+ },
+ "githubSetup": {
+ "connectTitle": "Подключение к GitHub",
+ "connectDescription": "Aperant требует GitHub для управления ветками кода и актуализации задач.",
+ "claudeTitle": "Подключение к Claude AI",
+ "claudeDescription": "Aperant использует Claude AI для интеллектуальных функций, таких как генерация дорожной карты, автоматизация задач и генерация идей.",
+ "aiProviderTitle": "Подключение к AI",
+ "aiProviderDescription": "Добавьте учётную запись AI-провайдера для работы функций генерации дорожной карты, автоматизации задач и генерации идей.",
+ "aiProviderReady": "У вас настроен хотя бы один AI-провайдер. Можете перейти к следующему шагу.",
+ "skipForNow": "Пропустить пока",
+ "continue": "Продолжить",
+ "selectRepo": "Выбор репозитория",
+ "repoDescription": "Aperant будет использовать этот репозиторий для управления ветками задач и поддержания актуальности кода.",
+ "selectBranch": "Выбор базовой ветки",
+ "branchDescription": "Выберите ветку, которую Aperant будет использовать как базовую для создания веток задач.",
+ "whyBranch": "Зачем выбирать ветку?",
+ "branchExplanation": "Aperant создаёт изолированные рабочие пространства для каждой задачи. Правильный выбор базовой ветки гарантирует, что ваши задачи начнутся с последней версией кода из основной ветки разработки.",
+ "ready": "Aperant готов к использованию! Теперь вы можете создавать задачи, которые автоматически будут основаны на ветке {{branchName}}.",
+ "createRepoAriaLabel": "Создать новый репозиторий на GitHub",
+ "linkRepoAriaLabel": "Привязать существующий репозиторий",
+ "goBackAriaLabel": "Вернуться к выбору репозитория",
+ "selectOwnerAriaLabel": "Выбрать {{owner}} владельцем репозитория",
+ "selectOrgAriaLabel": "Выбрать {{org}} владельцем репозитория",
+ "selectVisibilityAriaLabel": "Установить видимость репозитория: {{visibility}}"
+ },
+ "worktrees": {
+ "title": "Воркдеревья",
+ "description": "Управление изолированными рабочими пространствами для задач Aperant",
+ "empty": "Нет воркдеревьев",
+ "emptyDescription": "Воркдеревья создаются автоматически, когда Aperant разрабатывает функции. Они обеспечивают изолированные рабочие пространства для каждой задачи.",
+ "merge": "Слить воркдерево",
+ "mergeDescription": "Слить изменения из этого воркдерева в базовую ветку.",
+ "delete": "Удалить воркдерево?",
+ "deleteDescription": "Это навсегда удалит воркдерево и все незафиксированные изменения. Действие необратимо.",
+ "bulkDeleteTitle": "Удалить {{count}} воркдеревьев?",
+ "bulkDeleteDescription": "Это навсегда удалит выбранные воркдеревья и все их незафиксированные изменения. Действие необратимо.",
+ "deleting": "Удаление...",
+ "deleteSelected": "Удалить выбранные"
+ },
+ "worktreeCleanup": {
+ "title": "Завершить задачу",
+ "hasWorktree": "У задачи «{{taskTitle}}» всё ещё есть изолированное рабочее пространство (воркдерево).",
+ "willDelete": "Для отметки задачи как завершённой воркдерево и связанная ветка будут удалены.",
+ "warning": "Убедитесь, что вы слили или сохранили все нужные изменения перед продолжением.",
+ "confirm": "Удалить воркдерево и завершить",
+ "completing": "Завершение...",
+ "retry": "Попробовать снова",
+ "errorTitle": "Ошибка очистки",
+ "errorDescription": "Не удалось очистить воркдерево. Пожалуйста, попробуйте снова."
+ },
+ "update": {
+ "title": "Aperant",
+ "projectInitialized": "Проект инициализирован."
+ },
+ "addFeature": {
+ "title": "Добавить функцию",
+ "description": "Добавьте новую функцию в вашу дорожную карту. Опишите, что вы хотите создать и как это вписывается в вашу продуктовую стратегию.",
+ "featureTitle": "Название функции",
+ "featureTitlePlaceholder": "например, Аутентификация пользователей, Поддержка тёмного режима",
+ "featureDescription": "Описание",
+ "featureDescriptionPlaceholder": "Опишите, что делает эта функция и почему она ценна для пользователей.",
+ "rationale": "Обоснование",
+ "optional": "необязательно",
+ "rationalePlaceholder": "Объясните, почему эта функция должна быть реализована и как она вписывается в продуктовое видение.",
+ "phase": "Фаза",
+ "selectPhase": "Выберите фазу",
+ "priority": "Приоритет",
+ "selectPriority": "Выберите приоритет",
+ "complexity": "Сложность",
+ "selectComplexity": "Выберите сложность",
+ "impact": "Влияние",
+ "selectImpact": "Выберите влияние",
+ "lowComplexity": "Низкая",
+ "mediumComplexity": "Средняя",
+ "highComplexity": "Высокая",
+ "lowImpact": "Низкое влияние",
+ "mediumImpact": "Среднее влияние",
+ "highImpact": "Высокое влияние",
+ "titleRequired": "Название обязательно",
+ "descriptionRequired": "Описание обязательно",
+ "phaseRequired": "Пожалуйста, выберите фазу",
+ "cancel": "Отмена",
+ "adding": "Добавление...",
+ "addFeature": "Добавить функцию",
+ "failedToAdd": "Не удалось добавить функцию. Пожалуйста, попробуйте снова."
+ },
+ "addProject": {
+ "title": "Добавить проект",
+ "description": "Выберите способ добавления проекта",
+ "openExisting": "Открыть существующую папку",
+ "openExistingDescription": "Найдите существующий проект на вашем компьютере",
+ "createNew": "Создать новый проект",
+ "createNewDescription": "Начните с нуля с новой папкой проекта",
+ "createNewTitle": "Создать новый проект",
+ "createNewSubtitle": "Настройка новой папки проекта",
+ "projectName": "Название проекта",
+ "projectNamePlaceholder": "my-awesome-project",
+ "projectNameHelp": "Это будет имя папки. Используйте строчные буквы и дефисы.",
+ "location": "Расположение",
+ "locationPlaceholder": "Выберите папку...",
+ "willCreate": "Будет создано:",
+ "browse": "Обзор",
+ "initGit": "Инициализировать git-репозиторий",
+ "back": "Назад",
+ "creating": "Создание...",
+ "createProject": "Создать проект",
+ "nameRequired": "Пожалуйста, введите название проекта",
+ "locationRequired": "Пожалуйста, выберите расположение",
+ "failedToOpen": "Не удалось открыть проект",
+ "failedToCreate": "Не удалось создать проект",
+ "openExistingAriaLabel": "Открыть существующую папку проекта",
+ "createNewAriaLabel": "Создать новый проект"
+ },
+ "customModel": {
+ "title": "Настройка пользовательской модели",
+ "description": "Настройте модель и уровень обдумывания для этого сеанса чата.",
+ "model": "Модель",
+ "thinkingLevel": "Уровень обдумывания",
+ "cancel": "Отмена",
+ "apply": "Применить"
+ },
+ "removeProject": {
+ "title": "Удалить проект?",
+ "description": "Это удалит «{{projectName}}» из приложения. Ваши файлы останутся на диске, и вы сможете повторно добавить проект позже.",
+ "cancel": "Отмена",
+ "remove": "Удалить",
+ "error": "Не удалось удалить проект"
+ },
+ "appUpdate": {
+ "title": "Доступно обновление приложения",
+ "description": "Новая версия Aperant готова к загрузке",
+ "newVersion": "Новая версия",
+ "released": "Выпущено",
+ "downloading": "Загрузка...",
+ "downloadUpdate": "Загрузить обновление",
+ "installAndRestart": "Установить и перезапустить",
+ "installLater": "Установить позже",
+ "remindMeLater": "Напомнить позже",
+ "updateDownloaded": "Обновление успешно загружено! Нажмите «Установить», чтобы перезапустить и применить обновление.",
+ "downloadError": "Не удалось загрузить обновление",
+ "claudeCodeChangelog": "Просмотреть список изменений Claude Code",
+ "claudeCodeChangelogAriaLabel": "Просмотреть список изменений Claude Code (открывается в новом окне)",
+ "readOnlyVolumeTitle": "Невозможно установить из образа диска",
+ "readOnlyVolumeDescription": "Пожалуйста, переместите Aperant в папку Applications перед обновлением."
+ },
+ "addCompetitor": {
+ "title": "Добавить конкурента",
+ "description": "Добавьте известного конкурента в ваш анализ...",
+ "competitorName": "Название конкурента",
+ "competitorNamePlaceholder": "например, Slack, Notion, Figma",
+ "competitorUrl": "URL сайта",
+ "competitorUrlPlaceholder": "например, https://example.com",
+ "competitorDescription": "Описание",
+ "competitorDescriptionPlaceholder": "Краткое описание того, чем занимается этот конкурент...",
+ "relevance": "Релевантность",
+ "selectRelevance": "Выберите релевантность",
+ "highRelevance": "Высокая — прямой конкурент",
+ "mediumRelevance": "Средняя — частичное пересечение",
+ "lowRelevance": "Низкая — косвенная",
+ "nameRequired": "Название конкурента обязательно",
+ "urlRequired": "URL сайта обязателен",
+ "invalidUrl": "Пожалуйста, введите корректный URL",
+ "optional": "необязательно",
+ "cancel": "Отмена",
+ "adding": "Добавление...",
+ "addCompetitor": "Добавить конкурента",
+ "failedToAdd": "Не удалось добавить конкурента"
+ },
+ "competitorAnalysis": {
+ "title": "Включить анализ конкурентов?",
+ "description": "Улучшите вашу дорожную карту с помощью анализа продуктов конкурентов",
+ "whatItDoes": "Что делает анализ конкурентов:",
+ "identifiesCompetitors": "Выявляет 3–5 основных конкурентов на основе типа вашего проекта",
+ "searchesAppStores": "Ищет в магазинах приложений, форумах и социальных сетях отзывы пользователей и болевые точки",
+ "suggestsFeatures": "Предлагает функции, которые закрывают пробелы в продуктах конкурентов",
+ "webSearchesTitle": "Будут выполнены веб-поиски",
+ "webSearchesDescription": "Эта функция выполнит веб-поиски для сбора информации о конкурентах. В поисковых запросах будут использованы название и тип вашего проекта. Код и конфиденциальные данные не передаются.",
+ "optionalInfo": "Вы можете создать дорожную карту без анализа конкурентов. Она всё равно будет основана на структуре вашего проекта и лучших практиках.",
+ "skipAnalysis": "Нет, пропустить анализ",
+ "enableAnalysis": "Да, включить анализ",
+ "knowYourCompetitors": "Уже знаете своих конкурентов?",
+ "addThemDirectly": "Добавьте их напрямую для повышения точности анализа",
+ "addKnownCompetitors": "Добавить известных конкурентов",
+ "addKnownCompetitorsDescription": "Вручную добавьте конкурентов, которых вы уже знаете, в существующий анализ.",
+ "competitorsAdded": "{{count}} добавлено"
+ },
+ "existingCompetitorAnalysis": {
+ "title": "Параметры анализа конкурентов",
+ "description": "Для этого проекта уже есть анализ конкурентов от {{date}}",
+ "recently": "недавно",
+ "useExistingTitle": "Использовать существующий анализ",
+ "recommended": "(Рекомендуется)",
+ "useExistingDescription": "Использовать уже имеющиеся данные о конкурентах. Быстрее и без дополнительных веб-поисков.",
+ "runNewTitle": "Запустить новый анализ",
+ "runNewDescription": "Выполнить новые веб-поиски для получения актуальной информации о конкурентах. Занимает больше времени.",
+ "skipTitle": "Пропустить анализ конкурентов",
+ "skipDescription": "Создать дорожную карту без анализа конкурентов.",
+ "cancel": "Отмена"
+ },
+ "versionWarning": {
+ "title": "Требуется действие",
+ "subtitle": "Обновление версии 2.7.5",
+ "description": "В связи с изменениями аутентификации в этой версии вам необходимо повторно аутентифицировать ваш профиль Claude.",
+ "instructions": "Для повторной аутентификации:",
+ "step1": "Перейдите в Настройки",
+ "step2": "Откройте Настройки приложения > Интеграции",
+ "step3": "Нажмите «Повторная аутентификация» на вашем профиле",
+ "gotIt": "Понятно",
+ "goToSettings": "Перейти в настройки"
+ }
+}
diff --git a/apps/desktop/src/shared/i18n/locales/ru/errors.json b/apps/desktop/src/shared/i18n/locales/ru/errors.json
new file mode 100644
index 0000000000..70f48dfa66
--- /dev/null
+++ b/apps/desktop/src/shared/i18n/locales/ru/errors.json
@@ -0,0 +1,9 @@
+{
+ "task": {
+ "parseImplementationPlan": "Не удалось разобрать implementation_plan.json для {{specId}}: {{error}}",
+ "jsonError": {
+ "titleSuffix": "(Ошибка JSON)",
+ "description": "⚠️ Ошибка разбора JSON: {{error}}\n\nФайл implementation_plan.json повреждён. Запустите автоисправление в бэкенде или исправьте файл вручную."
+ }
+ }
+}
diff --git a/apps/desktop/src/shared/i18n/locales/ru/gitlab.json b/apps/desktop/src/shared/i18n/locales/ru/gitlab.json
new file mode 100644
index 0000000000..49462d1a49
--- /dev/null
+++ b/apps/desktop/src/shared/i18n/locales/ru/gitlab.json
@@ -0,0 +1,208 @@
+{
+ "title": "Задачи GitLab",
+ "states": {
+ "opened": "Открытые",
+ "closed": "Закрытые"
+ },
+ "complexity": {
+ "simple": "Простая",
+ "standard": "Стандартная",
+ "complex": "Сложная"
+ },
+ "header": {
+ "open": "открыто",
+ "searchPlaceholder": "Поиск задач..."
+ },
+ "filters": {
+ "opened": "Открытые",
+ "closed": "Закрытые",
+ "all": "Все"
+ },
+ "empty": {
+ "noMatch": "Нет задач, соответствующих вашему поиску",
+ "selectIssue": "Выберите задачу для просмотра деталей"
+ },
+ "notConnected": {
+ "title": "GitLab не подключён",
+ "description": "Настройте ваш токен GitLab и проект в настройках проекта для синхронизации задач.",
+ "openSettings": "Открыть настройки"
+ },
+ "detail": {
+ "notes": "заметки",
+ "viewTask": "Просмотреть задачу",
+ "createTask": "Создать задачу",
+ "taskLinked": "Задача привязана",
+ "taskId": "ID задачи",
+ "description": "Описание",
+ "noDescription": "Описание не предоставлено.",
+ "assignees": "Исполнители",
+ "milestone": "Веха"
+ },
+ "investigation": {
+ "title": "Создать задачу из тикета",
+ "issuePrefix": "Тикет",
+ "description": "Создайте задачу из этого тикета GitLab. Задача будет добавлена на вашу канбан-доску в колонку «Бэклог».",
+ "selectNotes": "Выбрать заметки для включения",
+ "deselectAll": "Снять выделение со всех",
+ "selectAll": "Выбрать все",
+ "willInclude": "Задача будет включать:",
+ "includeTitle": "Заголовок и описание тикета",
+ "includeLink": "Ссылку обратно на тикет GitLab",
+ "includeLabels": "Метки и метаданные тикета",
+ "noNotes": "Нет заметок (у этого тикета нет заметок)",
+ "failedToLoadNotes": "Не удалось загрузить заметки",
+ "taskCreated": "Задача создана! Просмотрите её на канбан-доске.",
+ "creating": "Создание...",
+ "cancel": "Отмена",
+ "done": "Готово",
+ "close": "Закрыть"
+ },
+ "settings": {
+ "enableIssues": "Включить тикеты GitLab",
+ "enableIssuesDescription": "Синхронизировать тикеты из GitLab и автоматически создавать задачи",
+ "instance": "Экземпляр GitLab",
+ "instanceDescription": "Используйте https://gitlab.com или URL вашего собственного экземпляра",
+ "connectedVia": "Подключено через GitLab CLI",
+ "authenticatedAs": "Аутентифицированы как",
+ "useDifferentToken": "Использовать другой токен",
+ "authentication": "Аутентификация GitLab",
+ "useManualToken": "Использовать ручной токен",
+ "authenticating": "Аутентификация через glab CLI...",
+ "browserWindow": "Должно открыться окно браузера для входа в систему.",
+ "personalAccessToken": "Персональный токен доступа",
+ "useOAuth": "Использовать OAuth вместо этого",
+ "tokenScope": "Создайте токен с разрешением",
+ "scopeApi": "api",
+ "scopeFrom": "из",
+ "gitlabSettings": "Настройки GitLab",
+ "project": "Проект",
+ "enterManually": "Ввести вручную",
+ "loadingProjects": "Загрузка проектов...",
+ "selectProject": "Выберите проект...",
+ "searchProjects": "Поиск проектов...",
+ "noMatchingProjects": "Нет подходящих проектов",
+ "noProjectsFound": "Проекты не найдены",
+ "selected": "Выбрано",
+ "projectFormat": "Формат:",
+ "projectFormatExample": "(например, gitlab-org/gitlab)",
+ "connectionStatus": "Статус подключения",
+ "checking": "Проверка...",
+ "connectedTo": "Подключено к",
+ "notConnected": "Не подключено",
+ "issuesAvailable": "Тикеты доступны",
+ "issuesAvailableDescription": "Откройте тикеты GitLab из боковой панели для просмотра, анализа и создания задач из тикетов.",
+ "defaultBranch": "Ветка по умолчанию",
+ "defaultBranchDescription": "Базовая ветка для создания воркдеревьев задач",
+ "loadingBranches": "Загрузка веток...",
+ "autoDetect": "Автоопределение (main/master)",
+ "searchBranches": "Поиск веток...",
+ "noMatchingBranches": "Нет подходящих веток",
+ "noBranchesFound": "Ветки не найдены",
+ "branchFromNote": "Все новые задачи будут ответвляться от",
+ "autoSyncOnLoad": "Автосинхронизация при загрузке",
+ "autoSyncDescription": "Автоматически загружать тикеты при открытии проекта",
+ "cli": {
+ "required": "Требуется GitLab CLI",
+ "notInstalled": "GitLab CLI (glab) необходим для аутентификации через OAuth. Установите его, чтобы использовать опцию «Использовать OAuth».",
+ "installButton": "Установить glab",
+ "installing": "Установка...",
+ "installSuccess": "Установка запущена в вашем терминале. Завершите её и нажмите «Обновить».",
+ "refresh": "Обновить",
+ "learnMore": "Подробнее",
+ "installed": "GitLab CLI установлен:"
+ }
+ },
+ "mergeRequests": {
+ "title": "Merge Request-ы GitLab",
+ "newMR": "Новый Merge Request",
+ "selectMR": "Выберите merge request для просмотра деталей",
+ "states": {
+ "opened": "Открытые",
+ "closed": "Закрытые",
+ "merged": "Слитые",
+ "locked": "Заблокированные"
+ },
+ "filters": {
+ "opened": "Открытые",
+ "closed": "Закрытые",
+ "merged": "Слитые",
+ "all": "Все"
+ }
+ },
+ "mrReview": {
+ "runReview": "Запустить AI-ревью",
+ "reviewing": "Ревью...",
+ "followupReview": "Повторное ревью",
+ "newCommits": "новый коммит",
+ "newCommitsPlural": "новых коммита",
+ "cancel": "Отмена",
+ "postFindings": "Опубликовать результаты",
+ "posting": "Публикация...",
+ "postedTo": "Опубликовано в GitLab",
+ "approve": "Одобрить",
+ "approving": "Одобрение...",
+ "merge": "Слить MR",
+ "merging": "Слияние...",
+ "aiReviewResult": "Результат AI-ревью",
+ "followupReviewResult": "Повторное ревью",
+ "description": "Описание",
+ "noDescription": "Описание не предоставлено.",
+ "labels": "Метки",
+ "status": {
+ "notReviewed": "Не проверено",
+ "notReviewedDesc": "Запустите AI-ревью для анализа этого MR",
+ "reviewComplete": "Ревью завершено",
+ "reviewCompleteDesc": "замечание(я) найдено. Выберите и опубликуйте в GitLab.",
+ "waitingForChanges": "Ожидание изменений",
+ "waitingForChangesDesc": "замечание(я) опубликовано. Ожидание ответа разработчика.",
+ "readyToMerge": "Готово к слиянию",
+ "readyToMergeDesc": "Блокирующих проблем не найдено. Этот MR можно слить.",
+ "needsAttention": "Требует внимания",
+ "needsAttentionDesc": "замечание(я) необходимо опубликовать в GitLab.",
+ "readyForFollowup": "Готово к повторному ревью",
+ "readyForFollowupDesc": "с момента ревью. Запустите повторное ревью, чтобы проверить устранение проблем.",
+ "blockingIssues": "Блокирующие проблемы",
+ "blockingIssuesDesc": "блокирующая(их) проблема(ы) остаётся открытой."
+ },
+ "overallStatus": {
+ "approve": "Одобрить",
+ "requestChanges": "Запрошены изменения",
+ "comment": "Комментарий"
+ },
+ "resolution": {
+ "resolved": "устранено",
+ "stillOpen": "всё ещё открыто",
+ "newIssue": "новая проблема",
+ "newIssues": "новые проблемы"
+ }
+ },
+ "findings": {
+ "summary": "выбрано",
+ "selectCriticalHigh": "Выбрать блокирующие/обязательные",
+ "selectAll": "Выбрать все",
+ "clear": "Очистить",
+ "noIssues": "Проблем не найдено! Код выглядит хорошо.",
+ "suggestedFix": "Предложенное исправление:",
+ "posted": "Опубликовано",
+ "severity": {
+ "critical": "Блокирующее",
+ "criticalDesc": "Необходимо исправить",
+ "high": "Обязательное",
+ "highDesc": "Следует исправить",
+ "medium": "Рекомендуемое",
+ "mediumDesc": "Улучшить качество",
+ "low": "Предложение",
+ "lowDesc": "К рассмотрению"
+ },
+ "category": {
+ "security": "Безопасность",
+ "quality": "Качество",
+ "style": "Стиль",
+ "test": "Тест",
+ "docs": "Документация",
+ "pattern": "Паттерн",
+ "performance": "Производительность",
+ "logic": "Логика"
+ }
+ }
+}
diff --git a/apps/desktop/src/shared/i18n/locales/ru/navigation.json b/apps/desktop/src/shared/i18n/locales/ru/navigation.json
new file mode 100644
index 0000000000..9e328f791b
--- /dev/null
+++ b/apps/desktop/src/shared/i18n/locales/ru/navigation.json
@@ -0,0 +1,87 @@
+{
+ "sections": {
+ "project": "Проект",
+ "tools": "Инструменты"
+ },
+ "items": {
+ "kanban": "Kanban-доска",
+ "terminals": "Терминалы агентов",
+ "insights": "Аналитика",
+ "roadmap": "Дорожная карта",
+ "ideation": "Генерация идей",
+ "changelog": "История изменений",
+ "context": "Контекст",
+ "githubIssues": "GitHub Issues",
+ "githubPRs": "GitHub PRs",
+ "gitlabIssues": "GitLab Issues",
+ "gitlabMRs": "GitLab MRs",
+ "worktrees": "Воркtree-ветки",
+ "agentTools": "Обзор MCP"
+ },
+ "actions": {
+ "settings": "Настройки",
+ "help": "Помощь и обратная связь",
+ "newTask": "Новая задача",
+ "collapseSidebar": "Свернуть боковую панель",
+ "expandSidebar": "Развернуть боковую панель",
+ "sponsor": "Поддержать нас"
+ },
+ "tooltips": {
+ "settings": "Настройки приложения",
+ "help": "Помощь и обратная связь"
+ },
+ "messages": {
+ "initializeToCreateTasks": "Инициализируйте Aperant для создания задач"
+ },
+ "updateBanner": {
+ "title": "Доступно обновление",
+ "version": "Версия {{version}} готова к установке",
+ "updateAndRestart": "Обновить и перезапустить",
+ "installAndRestart": "Установить и перезапустить",
+ "downloading": "Загрузка...",
+ "dismiss": "Закрыть",
+ "downloadError": "Не удалось загрузить обновление",
+ "readOnlyVolumeWarning": "Перенесите приложение в папку «Программы» для обновления"
+ },
+ "claudeCode": {
+ "checking": "Проверка Claude Code...",
+ "upToDate": "Claude Code актуален",
+ "updateAvailable": "Доступно обновление Claude Code",
+ "notInstalled": "Claude Code не установлен",
+ "error": "Ошибка при проверке Claude Code",
+ "installed": "Установлен",
+ "outdated": "Доступно обновление",
+ "missing": "Не установлен",
+ "current": "Текущая",
+ "latest": "Последняя",
+ "path": "Путь",
+ "lastChecked": "Последняя проверка",
+ "learnMore": "Узнать больше о Claude Code",
+ "learnMoreAriaLabel": "Узнать больше о Claude Code (откроется в новом окне)",
+ "viewChangelog": "Просмотреть историю изменений Claude Code",
+ "viewChangelogAriaLabel": "Просмотреть историю изменений Claude Code (откроется в новом окне)",
+ "updateWarningTitle": "Обновить Claude Code?",
+ "updateWarningDescription": "При обновлении все активные сессии Claude Code будут закрыты. Несохранённые данные в этих сессиях могут быть утеряны. Сохраните работу перед продолжением.",
+ "updateWarningTerminalNote": "Откроется окно терминала для выполнения команды установки. Дождитесь завершения установки перед продолжением.",
+ "updateAnyway": "Открыть терминал и обновить",
+ "switchVersion": "Сменить версию",
+ "selectVersion": "Выбрать версию",
+ "loadingVersions": "Загрузка версий...",
+ "failedToLoadVersions": "Не удалось загрузить версии",
+ "installingVersion": "Установка версии {{version}}...",
+ "rollbackWarningTitle": "Переключиться на версию {{version}}?",
+ "rollbackWarningDescription": "При смене версии все активные сессии Claude Code будут закрыты. Несохранённые данные в этих сессиях могут быть утеряны. Сохраните работу перед продолжением.",
+ "rollbackWarningTerminalNote": "Откроется окно терминала для выполнения команды установки. Дождитесь завершения установки перед продолжением.",
+ "switchAnyway": "Открыть терминал и переключить",
+ "currentVersion": "Текущая",
+ "switchInstallation": "Сменить установку",
+ "selectInstallation": "Выбрать установку",
+ "loadingInstallations": "Загрузка установок...",
+ "failedToLoadInstallations": "Не удалось загрузить установки",
+ "activeInstallation": "Активная",
+ "pathChangeWarningTitle": "Сменить установку CLI?",
+ "pathChangeWarningDescription": "При смене установки CLI будет использоваться другой бинарный файл Claude Code. Текущие сессии продолжат использовать предыдущую установку до перезапуска.",
+ "switchInstallationConfirm": "Переключить",
+ "versionUnknown": "версия неизвестна"
+ }
+}
diff --git a/apps/desktop/src/shared/i18n/locales/ru/onboarding.json b/apps/desktop/src/shared/i18n/locales/ru/onboarding.json
new file mode 100644
index 0000000000..edad27cadb
--- /dev/null
+++ b/apps/desktop/src/shared/i18n/locales/ru/onboarding.json
@@ -0,0 +1,261 @@
+{
+ "wizard": {
+ "title": "Мастер настройки",
+ "description": "Настройте ваше окружение Aperant за несколько простых шагов",
+ "helpText": "Этот мастер поможет вам настроить окружение всего за несколько шагов. Вы можете настроить OAuth-токен Claude, включить функции памяти и создать первую задачу."
+ },
+ "welcome": {
+ "title": "Добро пожаловать в Aperant",
+ "subtitle": "Создавайте программное обеспечение автономно с помощью AI-агентов",
+ "getStarted": "Начать",
+ "skip": "Пропустить настройку",
+ "features": {
+ "aiPowered": {
+ "title": "Разработка на базе AI",
+ "description": "Генерируйте код и создавайте функции с помощью агентов Claude Code"
+ },
+ "specDriven": {
+ "title": "Процесс на основе спецификаций",
+ "description": "Определяйте задачи с чёткими спецификациями и позвольте Aperant взять реализацию на себя"
+ },
+ "memory": {
+ "title": "Память и контекст",
+ "description": "Постоянная память между сессиями с помощью Graphiti"
+ },
+ "parallel": {
+ "title": "Параллельное выполнение",
+ "description": "Запускайте несколько агентов параллельно для ускорения циклов разработки"
+ }
+ }
+ },
+ "oauth": {
+ "title": "Аутентификация Claude",
+ "description": "Подключите ваш аккаунт Claude для включения AI-функций",
+ "configureTitle": "Настройка аутентификации Claude",
+ "addAccountsDesc": "Добавьте ваши аккаунты Claude для включения AI-функций",
+ "multiAccountInfo": "Добавьте несколько подписок Claude, чтобы автоматически переключаться между ними при достижении лимита запросов.",
+ "noAccountsYet": "Аккаунты ещё не настроены",
+ "badges": {
+ "default": "По умолчанию",
+ "active": "Активный",
+ "authenticated": "Аутентифицирован",
+ "needsAuth": "Требует аутентификации"
+ },
+ "buttons": {
+ "authenticate": "Аутентифицироваться",
+ "setActive": "Сделать активным",
+ "rename": "Переименовать",
+ "delete": "Удалить",
+ "add": "Добавить",
+ "adding": "Добавление...",
+ "showToken": "Показать токен",
+ "hideToken": "Скрыть токен",
+ "copyToken": "Скопировать токен",
+ "back": "Назад",
+ "continue": "Продолжить",
+ "skip": "Пропустить"
+ },
+ "labels": {
+ "accountName": "Название аккаунта",
+ "namePlaceholder": "Название профиля (например, Работа, Личный)",
+ "tokenLabel": "OAuth-токен",
+ "tokenPlaceholder": "Введите токен здесь",
+ "tokenHint": "Вставьте токен, отображённый в вашем терминале после завершения OAuth-входа."
+ },
+ "keychainTitle": "Безопасное хранилище",
+ "keychainDescription": "Ваши токены зашифрованы с помощью системного хранилища ключей. Возможно, вы увидите запрос пароля от macOS — нажмите «Всегда разрешать», чтобы больше не видеть его.",
+ "toast": {
+ "authSuccess": "Профиль успешно аутентифицирован",
+ "authSuccessWithEmail": "Аккаунт: {{email}}",
+ "authSuccessGeneric": "Аутентификация завершена. Теперь вы можете использовать этот профиль.",
+ "authStartFailed": "Не удалось запустить аутентификацию",
+ "addProfileFailed": "Не удалось добавить профиль",
+ "tokenSaved": "Токен сохранён",
+ "tokenSavedDescription": "Ваш токен был успешно сохранён.",
+ "tokenSaveFailed": "Не удалось сохранить токен",
+ "tryAgain": "Пожалуйста, попробуйте снова."
+ },
+ "alerts": {
+ "profileCreatedAuthFailed": "Профиль создан, но не удалось подготовить аутентификацию: {{error}}",
+ "authPrepareFailed": "Не удалось подготовить аутентификацию: {{error}}",
+ "authStartFailedMessage": "Не удалось запустить аутентификацию. Пожалуйста, попробуйте снова."
+ }
+ },
+ "memory": {
+ "title": "Память",
+ "description": "Настройка постоянной памяти между сессиями для агентов",
+ "contextDescription": "Память Aperant помогает запоминать контекст между сессиями разработки",
+ "enableMemory": "Включить память",
+ "enableMemoryDescription": "Постоянная память между сессиями с использованием встроенной базы данных",
+ "memoryDisabledInfo": "Память отключена. Результаты сессий будут сохраняться только в локальных файлах. Включите память для постоянного контекста между сессиями с семантическим поиском.",
+ "embeddingProvider": "Провайдер эмбеддингов",
+ "embeddingProviderDescription": "Провайдер для семантического поиска (необязательно — ключевой поиск работает без него)",
+ "selectEmbeddingModel": "Выберите модель эмбеддингов",
+ "openaiApiKey": "API-ключ OpenAI",
+ "openaiApiKeyDescription": "Требуется для эмбеддингов OpenAI",
+ "openaiGetKey": "Получите ваш ключ на",
+ "voyageApiKey": "API-ключ Voyage AI",
+ "voyageApiKeyDescription": "Требуется для эмбеддингов Voyage AI",
+ "voyageEmbeddingModel": "Модель эмбеддингов",
+ "googleApiKey": "API-ключ Google AI",
+ "googleApiKeyDescription": "Требуется для эмбеддингов Google AI",
+ "azureConfig": "Конфигурация Azure OpenAI",
+ "azureApiKey": "API-ключ",
+ "azureBaseUrl": "Базовый URL",
+ "azureEmbeddingDeployment": "Название развёртывания эмбеддингов",
+ "memoryInfo": "Память хранит открытия, паттерны и выводы о вашей кодовой базе, чтобы будущие сессии начинались с уже загруженным контекстом.",
+ "learnMore": "Подробнее о памяти",
+ "back": "Назад",
+ "skip": "Пропустить",
+ "saving": "Сохранение...",
+ "saveAndContinue": "Сохранить и продолжить",
+ "providers": {
+ "ollama": "Ollama (Локально — бесплатно)",
+ "openai": "OpenAI",
+ "voyage": "Voyage AI",
+ "google": "Google AI",
+ "azure": "Azure OpenAI"
+ },
+ "ollamaConfig": "Конфигурация Ollama",
+ "checking": "Проверка...",
+ "connected": "Подключено",
+ "notRunning": "Не запущено",
+ "baseUrl": "Базовый URL",
+ "embeddingModel": "Модель эмбеддингов",
+ "embeddingDim": "Размерность эмбеддингов",
+ "embeddingDimDescription": "Требуется для эмбеддингов Ollama (например, 768 для nomic-embed-text)",
+ "modelRecommendation": "Рекомендуется: qwen3-embedding:4b (баланс), :8b (качество), :0.6b (скорость)"
+ },
+ "completion": {
+ "title": "Всё готово!",
+ "subtitle": "Aperant готов помочь вам создавать отличное программное обеспечение",
+ "setupComplete": "Настройка завершена",
+ "setupCompleteDescription": "Ваше окружение настроено и готово к работе. Вы можете немедленно начать создавать задачи или изучить приложение в своём темпе.",
+ "whatsNext": "Что дальше?",
+ "createTask": {
+ "title": "Создать задачу",
+ "description": "Начните с создания первой задачи, чтобы увидеть Aperant в действии.",
+ "action": "Открыть создание задачи"
+ },
+ "customizeSettings": {
+ "title": "Настроить параметры",
+ "description": "Настройте предпочтения, настройте интеграции или повторно запустите этот мастер.",
+ "action": "Открыть настройки"
+ },
+ "exploreDocs": {
+ "title": "Изучить документацию",
+ "description": "Узнайте больше о расширенных функциях, лучших практиках и устранении неполадок."
+ },
+ "finish": "Завершить и начать разработку",
+ "rerunHint": "Вы всегда можете повторно запустить этот мастер из Настройки → Приложение"
+ },
+ "steps": {
+ "welcome": "Добро пожаловать",
+ "accounts": "Аккаунты",
+ "devtools": "Инструменты",
+ "privacy": "Конфиденциальность",
+ "memory": "Память",
+ "done": "Готово"
+ },
+ "privacy": {
+ "title": "Помогите улучшить Aperant",
+ "subtitle": "Анонимные отчёты об ошибках помогают нам быстрее исправлять баги",
+ "whatWeCollect": {
+ "title": "Что мы собираем",
+ "crashReports": "Отчёты о сбоях и трассировки стека ошибок",
+ "errorMessages": "Сообщения об ошибках (с анонимизированными путями к файлам)",
+ "appVersion": "Версию приложения и информацию о платформе"
+ },
+ "whatWeNeverCollect": {
+ "title": "Что мы никогда не собираем",
+ "code": "Ваш код или файлы проекта",
+ "filenames": "Полные пути к файлам (имена пользователей скрыты)",
+ "apiKeys": "API-ключи или токены",
+ "personalData": "Личную информацию или данные об использовании"
+ },
+ "toggle": {
+ "label": "Отправлять анонимные отчёты об ошибках",
+ "description": "Помогите нам выявлять и устранять проблемы"
+ }
+ },
+ "claudeCode": {
+ "title": "Claude Code CLI",
+ "description": "Установите или обновите Claude Code CLI для включения AI-функций",
+ "detecting": "Проверка установки Claude Code...",
+ "info": {
+ "title": "Что такое Claude Code?",
+ "description": "Claude Code — официальный CLI от Anthropic, обеспечивающий AI-функции Aperant. Он предоставляет безопасную аутентификацию и прямой доступ к моделям Claude."
+ },
+ "status": {
+ "installed": "Установлено",
+ "outdated": "Доступно обновление",
+ "notFound": "Не установлено"
+ },
+ "version": {
+ "current": "Текущая версия",
+ "latest": "Последняя версия"
+ },
+ "install": {
+ "button": "Установить Claude Code",
+ "updating": "Обновить Claude Code",
+ "inProgress": "Установка...",
+ "success": "Команда установки отправлена в терминал. Пожалуйста, завершите установку там.",
+ "instructions": "Установщик откроется в вашем терминале. Следуйте инструкциям для завершения установки."
+ },
+ "learnMore": "Подробнее о Claude Code"
+ },
+ "devtools": {
+ "title": "Инструменты разработчика",
+ "description": "Выберите предпочитаемые IDE, терминал и CLI для работы с воркдеревьями Aperant",
+ "detecting": "Определение установленных инструментов...",
+ "detectAgain": "Определить снова",
+ "whyConfigure": "Зачем это настраивать?",
+ "whyConfigureDescription": "Когда Aperant разрабатывает функции в изолированных воркдеревьях, вы можете открывать их напрямую в предпочитаемой IDE или терминале для тестирования и проверки изменений.",
+ "ide": {
+ "label": "Предпочитаемая IDE",
+ "description": "Aperant будет открывать воркдеревья в этом редакторе",
+ "customPath": "Пользовательский путь к IDE"
+ },
+ "terminal": {
+ "label": "Предпочитаемый терминал",
+ "description": "Aperant будет открывать сессии терминала здесь",
+ "customPath": "Пользовательский путь к терминалу"
+ },
+ "cli": {
+ "label": "Предпочитаемый CLI",
+ "description": "CLI-инструмент для AI-сессий терминала",
+ "customPath": "Пользовательский путь к CLI"
+ },
+ "detectedSummary": "Обнаружено в вашей системе:",
+ "noToolsDetected": "Дополнительные инструменты не обнаружены (будут использованы VS Code и системный терминал)",
+ "custom": "Пользовательский...",
+ "saveAndContinue": "Сохранить и продолжить"
+ },
+ "accounts": {
+ "title": "Добавьте ваши AI-аккаунты",
+ "description": "Подключите аккаунты ваших AI-провайдеров. Вы можете добавить ещё позже в настройках.",
+ "buttons": {
+ "back": "Назад",
+ "continue": "Продолжить",
+ "skip": "Пропустить пока"
+ }
+ },
+ "ollama": {
+ "notInstalled": {
+ "title": "Ollama не установлена",
+ "description": "Ollama предоставляет бесплатные локальные модели эмбеддингов для семантического поиска. Установите одним кликом, чтобы включить эту функцию.",
+ "installSuccess": "Установка запущена в вашем терминале. Завершите установку там, затем нажмите «Повторить».",
+ "installButton": "Установить Ollama",
+ "installing": "Установка...",
+ "retry": "Повторить",
+ "learnMore": "Подробнее",
+ "fallbackNote": "Память будет работать с ключевым поиском даже без Ollama."
+ },
+ "notRunning": {
+ "title": "Ollama не запущена",
+ "description": "Ollama установлена, но не запущена. Запустите Ollama для использования локальных моделей эмбеддингов.",
+ "retry": "Повторить",
+ "fallbackNote": "Память будет работать с ключевым поиском даже без эмбеддингов."
+ }
+ }
+}
diff --git a/apps/desktop/src/shared/i18n/locales/ru/settings.json b/apps/desktop/src/shared/i18n/locales/ru/settings.json
new file mode 100644
index 0000000000..f4a3f9781f
--- /dev/null
+++ b/apps/desktop/src/shared/i18n/locales/ru/settings.json
@@ -0,0 +1,1188 @@
+{
+ "title": "Настройки",
+ "tabs": {
+ "app": "Настройки приложения",
+ "project": "Настройки проекта"
+ },
+ "sections": {
+ "appearance": {
+ "title": "Внешний вид",
+ "description": "Настройте отображение Aperant"
+ },
+ "display": {
+ "title": "Отображение",
+ "description": "Настройте размер элементов интерфейса"
+ },
+ "language": {
+ "title": "Язык",
+ "description": "Выберите предпочитаемый язык"
+ },
+ "devtools": {
+ "title": "Инструменты разработчика",
+ "description": "Настройки IDE и терминала"
+ },
+ "agent": {
+ "title": "Настройки агента",
+ "description": "Модель и фреймворк по умолчанию"
+ },
+ "paths": {
+ "title": "Пути",
+ "description": "Пути к CLI-инструментам и фреймворкам"
+ },
+ "accounts": {
+ "title": "Аккаунты",
+ "description": "Аккаунты Claude и API-эндпоинты"
+ },
+ "updates": {
+ "title": "Обновления",
+ "description": "Обновления Aperant"
+ },
+ "notifications": {
+ "title": "Уведомления",
+ "description": "Настройки оповещений"
+ },
+ "debug": {
+ "title": "Отладка и логи",
+ "description": "Инструменты диагностики"
+ },
+ "terminal-fonts": {
+ "title": "Шрифты терминала",
+ "description": "Настройте внешний вид шрифтов терминала"
+ }
+ },
+ "apiProfiles": {
+ "title": "API-профили",
+ "description": "Настройте пользовательские Anthropic-совместимые API-эндпоинты",
+ "addButton": "Добавить профиль",
+ "presets": {
+ "anthropic": "Anthropic",
+ "openrouter": "OpenRouter",
+ "groq": "Groq",
+ "zaiGlobal": "z.AI (Глобальный)",
+ "zaiChina": "z.AI (Китай)"
+ },
+ "fields": {
+ "name": "Название",
+ "preset": "Шаблон",
+ "baseUrl": "Базовый URL",
+ "apiKey": "API-ключ"
+ },
+ "placeholders": {
+ "name": "Мой пользовательский API",
+ "preset": "Выберите шаблон провайдера",
+ "baseUrl": "https://api.anthropic.com",
+ "apiKey": "sk-ant-..."
+ },
+ "hints": {
+ "preset": "Шаблоны заполняют базовый URL; API-ключ нужно вставить самостоятельно.",
+ "baseUrl": "Пример: https://api.anthropic.com или http://localhost:8080"
+ },
+ "validation": {
+ "nameRequired": "Название обязательно",
+ "baseUrlRequired": "Базовый URL обязателен",
+ "baseUrlInvalid": "Неверный формат URL (должен начинаться с http:// или https://)",
+ "apiKeyRequired": "API-ключ обязателен",
+ "apiKeyInvalid": "Неверный формат API-ключа"
+ },
+ "actions": {
+ "save": "Сохранить профиль",
+ "saving": "Сохранение...",
+ "cancel": "Отмена",
+ "changeKey": "Изменить",
+ "cancelKeyChange": "Отмена"
+ },
+ "testConnection": {
+ "label": "Проверить подключение",
+ "testing": "Проверка...",
+ "success": "Подключение успешно",
+ "failure": "Подключение не удалось"
+ },
+ "models": {
+ "title": "Необязательно: маппинг названий моделей",
+ "description": "Выберите модели вашего API-провайдера. Оставьте пустым для использования значений по умолчанию.",
+ "defaultLabel": "Модель по умолчанию (необязательно)",
+ "haikuLabel": "Модель Haiku (необязательно)",
+ "sonnetLabel": "Модель Sonnet (необязательно)",
+ "opusLabel": "Модель Opus (необязательно)",
+ "defaultPlaceholder": "напр., claude-sonnet-4-6",
+ "haikuPlaceholder": "напр., claude-haiku-4-5-20251001",
+ "sonnetPlaceholder": "напр., claude-sonnet-4-6",
+ "opusPlaceholder": "напр., claude-opus-4-6",
+ "opus1mPlaceholder": "напр., claude-opus-4-6 (контекст 1M)"
+ },
+ "empty": {
+ "title": "API-профили не настроены",
+ "description": "Создайте профиль для настройки пользовательских API-эндпоинтов для сборок.",
+ "action": "Создать первый профиль"
+ },
+ "switchToOauth": {
+ "label": "Переключиться на OAuth",
+ "loading": "Переключение..."
+ },
+ "activeBadge": "Активен",
+ "customModels": "Пользовательские модели: {{models}}",
+ "setActive": {
+ "label": "Сделать активным",
+ "loading": "Применение..."
+ },
+ "tooltips": {
+ "edit": "Редактировать профиль",
+ "deleteActive": "Переключитесь на OAuth перед удалением",
+ "deleteInactive": "Удалить профиль"
+ },
+ "deleteAriaLabel": "Удалить профиль {{name}}",
+ "toast": {
+ "create": {
+ "title": "Профиль создан",
+ "description": "«{{name}}» успешно добавлен."
+ },
+ "update": {
+ "title": "Профиль обновлён",
+ "description": "«{{name}}» успешно обновлён."
+ },
+ "delete": {
+ "title": "Профиль удалён",
+ "description": "«{{name}}» удалён.",
+ "errorTitle": "Не удалось удалить профиль",
+ "errorFallback": "При удалении профиля произошла ошибка."
+ },
+ "switch": {
+ "oauthTitle": "Переключено на OAuth",
+ "oauthDescription": "Используется OAuth-аутентификация",
+ "profileTitle": "Профиль активирован",
+ "profileDescription": "Используется {{name}}",
+ "errorTitle": "Не удалось сменить аутентификацию",
+ "errorFallback": "При смене метода аутентификации произошла ошибка."
+ }
+ },
+ "dialog": {
+ "createTitle": "Добавить API-профиль",
+ "editTitle": "Редактировать профиль",
+ "description": "Настройте пользовательский Anthropic-совместимый API-эндпоинт для сборок.",
+ "deleteTitle": "Удалить профиль?",
+ "deleteDescription": "Вы уверены, что хотите удалить «{{name}}»? Это действие нельзя отменить.",
+ "cancel": "Отмена",
+ "delete": "Удалить",
+ "deleting": "Удаление..."
+ }
+ },
+ "modelSelect": {
+ "placeholder": "Выберите модель или введите вручную",
+ "placeholderManual": "Введите название модели (напр., claude-sonnet-4-6)",
+ "searchPlaceholder": "Поиск моделей...",
+ "noResults": "Модели не найдены",
+ "discoveryNotAvailable": "Обнаружение моделей недоступно. Введите название модели вручную.",
+ "ollamaLoading": "Загрузка моделей Ollama...",
+ "ollamaNoModels": "Модели Ollama не установлены",
+ "ollamaNoModelsHint": "Установите модели в Настройках агента → вкладка Ollama",
+ "apiKeyOnly": "Только API-ключ"
+ },
+ "language": {
+ "label": "Язык интерфейса",
+ "description": "Выберите язык для интерфейса приложения"
+ },
+ "scale": {
+ "presets": "Предустановки масштаба",
+ "presetsDescription": "Быстрые варианты масштаба для распространённых предпочтений",
+ "fineTune": "Точная настройка масштаба",
+ "fineTuneDescription": "Настройка от 75% до 200% с шагом 5%",
+ "default": "По умолчанию",
+ "comfortable": "Комфортный",
+ "large": "Крупный"
+ },
+ "logOrder": {
+ "label": "Порядок логов",
+ "description": "Выберите отображение логов в детальном виде задачи",
+ "chronological": "Хронологический (сначала старые)",
+ "reverseChronological": "Обратный хронологический (сначала новые)"
+ },
+ "gpuAcceleration": {
+ "label": "Аппаратное ускорение GPU",
+ "description": "Использовать WebGL для рендеринга терминала (экспериментально, быстрее при большом количестве терминалов)",
+ "auto": "Авто (использовать WebGL при поддержке)",
+ "on": "Всегда включено",
+ "off": "Выключено (по умолчанию)",
+ "helperText": "Изменения применяются только к новым терминалам"
+ },
+ "general": {
+ "otherAgentSettings": "Другие настройки агента",
+ "otherAgentSettingsDescription": "Дополнительные параметры настройки агента",
+ "agentFramework": "Фреймворк агента",
+ "agentFrameworkDescription": "Фреймворк разработки для автономных задач",
+ "agentFrameworkAutoClaude": "Aperant",
+ "aiTerminalNaming": "AI-именование терминалов",
+ "aiTerminalNamingDescription": "Автоматически называть терминалы на основе команд (использует модель AI Naming)",
+ "featureModelSettings": "Настройки модели функций",
+ "featureModelSettingsDescription": "Модель и уровень мышления для Аналитики, Генерации идей и Дорожной карты",
+ "model": "Модель",
+ "thinkingLevel": "Уровень мышления",
+ "paths": "Пути",
+ "pathsDescription": "Настройте пути к исполняемым файлам и фреймворкам",
+ "pythonPath": "Путь к Python",
+ "pythonPathDescription": "Путь к исполняемому файлу Python (оставьте пустым для автоопределения)",
+ "pythonPathPlaceholder": "python3 (по умолчанию)",
+ "gitPath": "Путь к Git",
+ "gitPathDescription": "Путь к исполняемому файлу Git (оставьте пустым для автоопределения)",
+ "gitPathPlaceholder": "git (по умолчанию)",
+ "githubCLIPath": "Путь к GitHub CLI",
+ "githubCLIPathDescription": "Путь к исполняемому файлу GitHub CLI (gh) (оставьте пустым для автоопределения)",
+ "githubCLIPathPlaceholder": "gh (по умолчанию)",
+ "gitlabCLIPath": "Путь к GitLab CLI",
+ "gitlabCLIPathDescription": "Путь к исполняемому файлу GitLab CLI (glab) (оставьте пустым для автоопределения)",
+ "gitlabCLIPathPlaceholder": "glab (по умолчанию)",
+ "claudePath": "Путь к Claude CLI",
+ "claudePathDescription": "Путь к исполняемому файлу Claude CLI (оставьте пустым для автоопределения)",
+ "claudePathPlaceholder": "claude (по умолчанию)",
+ "detectedPath": "Обнаружен автоматически",
+ "detectedVersion": "Версия",
+ "detectedSource": "Источник",
+ "sourceUserConfig": "Конфигурация пользователя",
+ "sourceVenv": "Виртуальное окружение",
+ "sourceHomebrew": "Homebrew",
+ "sourceNvm": "NVM",
+ "sourceSystemPath": "Системный PATH",
+ "sourceBundled": "Встроенный",
+ "sourceFallback": "Запасной вариант",
+ "notDetected": "Не обнаружен",
+ "autoClaudePath": "Путь Aperant",
+ "autoClaudePathDescription": "Относительный путь к директории auto-claude в проектах",
+ "autoClaudePathPlaceholder": "auto-claude (по умолчанию)",
+ "autoNameTerminals": "Автоматически именовать терминалы",
+ "autoNameTerminalsDescription": "Использовать AI для генерации описательных имён вкладок терминала на основе активности"
+ },
+ "theme": {
+ "title": "Внешний вид",
+ "description": "Настройте отображение Aperant",
+ "mode": "Режим",
+ "modeDescription": "Выберите светлую или тёмную тему",
+ "light": "Светлая",
+ "dark": "Тёмная",
+ "system": "Системная",
+ "colorTheme": "Цветовая тема",
+ "colorThemeDescription": "Выберите предпочитаемую цветовую палитру"
+ },
+ "devtools": {
+ "title": "Инструменты разработчика",
+ "description": "Настройте предпочитаемые IDE, терминал и шрифты терминала",
+ "detecting": "Обнаружение установленных инструментов...",
+ "detectAgain": "Обнаружить снова",
+ "tabTools": "Инструменты",
+ "tabTerminalFonts": "Шрифты терминала",
+ "ide": {
+ "label": "Предпочитаемая IDE",
+ "description": "Aperant будет открывать воркtree в этом редакторе",
+ "placeholder": "Выберите IDE...",
+ "customPath": "Пользовательский путь к IDE",
+ "customPathPlaceholder": "/путь/к/вашей/ide"
+ },
+ "terminal": {
+ "label": "Предпочитаемый терминал",
+ "description": "Aperant будет открывать терминальные сессии здесь",
+ "placeholder": "Выберите терминал...",
+ "customPath": "Пользовательский путь к терминалу",
+ "customPathPlaceholder": "/путь/к/вашему/терминалу"
+ },
+ "cli": {
+ "label": "Предпочитаемый CLI",
+ "description": "CLI-инструмент для терминальных сессий с AI",
+ "placeholder": "Выберите CLI...",
+ "customPath": "Пользовательский путь к CLI",
+ "customPathPlaceholder": "/путь/к/вашему/cli"
+ },
+ "detected": "Обнаружен",
+ "notInstalled": "Не установлен",
+ "detectedSummary": "Обнаружено в системе:",
+ "noToolsDetected": "Дополнительные инструменты не обнаружены (будут использоваться VS Code и системный терминал)",
+ "autoNameClaude": {
+ "label": "Автоименование Claude-терминалов",
+ "description": "Использовать AI для генерации описательного имени Claude-терминалов на основе первого сообщения"
+ },
+ "yoloMode": {
+ "label": "Режим YOLO",
+ "description": "Запустить Claude с флагом --dangerously-skip-permissions, обходя все запросы безопасности. Используйте с крайней осторожностью.",
+ "warning": "Этот режим обходит систему разрешений Claude. Включайте только если полностью доверяете выполняемому коду."
+ }
+ },
+ "updates": {
+ "title": "Обновления",
+ "description": "Управление обновлениями Aperant",
+ "appUpdateReady": "Обновление приложения готово",
+ "newVersion": "Новая версия",
+ "released": "Выпущено",
+ "downloading": "Загрузка...",
+ "updateDownloaded": "Обновление загружено! Нажмите «Установить» для перезапуска и применения обновления.",
+ "installAndRestart": "Установить и перезапустить",
+ "downloadUpdate": "Загрузить обновление",
+ "version": "Версия",
+ "loading": "Загрузка...",
+ "checkingForUpdates": "Проверка обновлений...",
+ "newVersionAvailable": "Доступна новая версия:",
+ "latestVersion": "У вас установлена последняя версия.",
+ "viewRelease": "Посмотреть полный релиз на GitHub",
+ "unableToCheck": "Не удалось проверить обновления",
+ "checkForUpdates": "Проверить обновления",
+ "autoUpdateProjects": "Автообновление проектов",
+ "autoUpdateProjectsDescription": "Автоматически обновлять Aperant в проектах при выходе новой версии",
+ "betaUpdates": "Бета-обновления",
+ "betaUpdatesDescription": "Получать предрелизные бета-версии с новыми функциями (может быть менее стабильным)",
+ "stableDowngradeAvailable": "Доступна стабильная версия",
+ "stableDowngradeDescription": "Вы используете бета-версию. Поскольку бета-обновления отключены, можно переключиться на последний стабильный релиз.",
+ "stableVersion": "Стабильная версия",
+ "downloadStableVersion": "Загрузить стабильную версию",
+ "readOnlyVolumeTitle": "Невозможно установить с образа диска",
+ "readOnlyVolumeDescription": "Aperant запущен с образа диска только для чтения (DMG). Перетащите приложение в папку «Программы» и перезапустите его оттуда для установки обновлений.",
+ "downloadError": "Не удалось загрузить обновление"
+ },
+ "notifications": {
+ "title": "Уведомления",
+ "description": "Настройте параметры уведомлений по умолчанию",
+ "onTaskComplete": "При завершении задачи",
+ "onTaskCompleteDescription": "Уведомлять при успешном завершении задачи",
+ "onTaskFailed": "При ошибке задачи",
+ "onTaskFailedDescription": "Уведомлять при возникновении ошибки в задаче",
+ "onReviewNeeded": "При необходимости проверки",
+ "onReviewNeededDescription": "Уведомлять когда QA требует вашей проверки",
+ "sound": "Звук",
+ "soundDescription": "Воспроизводить звук с уведомлениями"
+ },
+ "actions": {
+ "save": "Сохранить настройки",
+ "rerunWizard": "Перезапустить мастер настройки",
+ "rerunWizardDescription": "Запустить мастер настройки снова"
+ },
+ "projectSections": {
+ "general": {
+ "title": "Основные",
+ "description": "Конфигурация Auto-Build и агента",
+ "useClaudeMd": "Использовать CLAUDE.md",
+ "useClaudeMdDescription": "Включить инструкции CLAUDE.md в контекст агента"
+ },
+ "claude": {
+ "title": "Авторизация Claude",
+ "description": "Аутентификация Claude"
+ },
+ "linear": {
+ "title": "Linear",
+ "description": "Интеграция с Linear",
+ "integrationTitle": "Интеграция с Linear",
+ "integrationDescription": "Подключитесь к Linear для отслеживания задач и импорта",
+ "syncDescription": "Синхронизация с Linear для отслеживания задач"
+ },
+ "github": {
+ "title": "GitHub",
+ "description": "Синхронизация GitHub Issues",
+ "integrationTitle": "Интеграция с GitHub",
+ "integrationDescription": "Подключитесь к GitHub для отслеживания задач",
+ "syncDescription": "Синхронизация с GitHub Issues",
+ "defaultBranch": {
+ "label": "Ветка по умолчанию",
+ "description": "Базовая ветка для создания воркtree задач",
+ "autoDetect": "Автоопределение (main/master)",
+ "searchPlaceholder": "Поиск веток...",
+ "noBranchesFound": "Ветки не найдены",
+ "selectedBranchHelp": "Все новые задачи будут ветвиться от {{branch}}"
+ },
+ "pushNewBranches": {
+ "label": "Автоматически отправлять новые ветки",
+ "description": "Отправлять новые ветки задач и воркtree на GitHub и автоматически настраивать отслеживание"
+ }
+ },
+ "gitlab": {
+ "title": "GitLab",
+ "description": "Синхронизация GitLab Issues",
+ "integrationTitle": "Интеграция с GitLab",
+ "integrationDescription": "Подключитесь к GitLab для отслеживания задач",
+ "syncDescription": "Синхронизация с GitLab Issues"
+ },
+ "memory": {
+ "title": "Память",
+ "description": "Бэкенд памяти Graphiti",
+ "integrationTitle": "Память",
+ "integrationDescription": "Настройте постоянную межсессионную память для агентов",
+ "syncDescription": "Настройте постоянную память"
+ }
+ },
+ "agentProfile": {
+ "label": "Профиль агента",
+ "title": "Профиль агента по умолчанию",
+ "sectionDescription": "Выберите предустановленную конфигурацию модели и уровня мышления",
+ "profilesInfo": "Профили агентов предоставляют предустановленные конфигурации модели и уровня мышления Claude. При создании новой задачи эти настройки используются по умолчанию. Их всегда можно переопределить в мастере создания задачи.",
+ "custom": "Пользовательский",
+ "customConfiguration": "Пользовательская конфигурация",
+ "customDescription": "Выберите модель и уровень мышления",
+ "phaseConfiguration": "Конфигурация фаз",
+ "phaseConfigurationDescription": "Настройте модель и уровень мышления для каждой фазы",
+ "clickToCustomize": "Нажмите для настройки",
+ "model": "Модель",
+ "thinking": "Мышление",
+ "thinkingLevel": "Уровень мышления",
+ "selectModel": "Выберите модель",
+ "selectThinkingLevel": "Выберите уровень мышления",
+ "perPhaseOptimization": "(оптимизация по фазам)",
+ "resetToDefaults": "Сбросить к значениям по умолчанию",
+ "resetToProfileDefaults": "Сбросить к настройкам {{profile}} по умолчанию",
+ "customized": "Настроен",
+ "ollamaNotConfigured": "Выберите модели ниже",
+ "phaseConfigNote": "Эти настройки будут использоваться по умолчанию при создании новых задач с данным профилем. Их можно переопределить для каждой задачи в мастере создания задачи.",
+ "adaptiveThinking": {
+ "badge": "Адаптивное",
+ "tooltip": "Opus использует адаптивное мышление — он динамически решает, сколько думать в рамках установленного бюджетного лимита уровня мышления."
+ },
+ "reasoning": {
+ "adaptive": "Адаптивное",
+ "budget": "Бюджет",
+ "reasoning": "Рассуждение",
+ "thinking": "Мышление",
+ "noThinking": "(Без мышления)",
+ "toggle": {
+ "off": "Выкл",
+ "on": "Вкл"
+ },
+ "badgeTooltip": {
+ "adaptive_effort": "Динамически решает, сколько думать в рамках бюджетного лимита",
+ "thinking_tokens": "Мышление на основе бюджета с настраиваемым распределением токенов",
+ "reasoning_effort": "Уровни усилий рассуждения (низкий/средний/высокий)",
+ "thinking_toggle": "Включение/выключение мышления",
+ "none": "Расширенное мышление не поддерживается"
+ }
+ },
+ "phases": {
+ "spec": {
+ "label": "Создание спецификации",
+ "description": "Исследование, требования, сбор контекста"
+ },
+ "planning": {
+ "label": "Планирование",
+ "description": "Планирование реализации и архитектура"
+ },
+ "coding": {
+ "label": "Разработка",
+ "description": "Непосредственная реализация кода"
+ },
+ "qa": {
+ "label": "QA-проверка",
+ "description": "Обеспечение качества и валидация"
+ }
+ },
+ "providerOverrides": {
+ "title": "Маппинг моделей провайдера",
+ "description": "Настройте, какую модель использует каждый провайдер для каждого сокращённого имени",
+ "defaultMapping": "По умолчанию",
+ "yourOverride": "Ваш вариант",
+ "shorthand": "Сокращённое имя",
+ "useDefault": "Использовать по умолчанию",
+ "resetAll": "Сбросить всё",
+ "noConnectedProviders": "Нет подключённых провайдеров. Добавьте аккаунты в настройках Аккаунтов для настройки маппинга моделей.",
+ "equivalentNote": "Когда активен не-Anthropic провайдер, эти маппинги определяют, какая модель используется для каждой фазы."
+ },
+ "providerTabs": {
+ "moreProviders": "Ещё",
+ "noProviders": "Нет подключённых провайдеров. Добавьте аккаунты в настройках Аккаунтов для настройки специфических параметров агента провайдера.",
+ "configureFor": "Настроить параметры агента для {{provider}}",
+ "crossProvider": "Кросс-провайдерный",
+ "crossProviderDisabledTooltip": "Подключите два или более аккаунта провайдеров для включения кросс-провайдерных возможностей",
+ "needsSetup": "Требуется настройка"
+ },
+ "crossProviderTab": {
+ "title": "Кросс-провайдерная конфигурация",
+ "description": "Назначьте разный провайдер и модель для каждой фазы конвейера для максимальной гибкости.",
+ "activateInfo": "Задачи, созданные при активной данной конфигурации, будут использовать кросс-провайдерную настройку.",
+ "featureModelsTitle": "Модели функций",
+ "featureModelsDescription": "Настройте модели для функций вне конвейера (Аналитика, Генерация идей и др.)"
+ },
+ "customProfile": {
+ "name": "Пользовательский (кросс-провайдерный)",
+ "description": "Смешивайте разных провайдеров и модели для каждой фазы",
+ "phaseAssignment": "Назначьте провайдера и модель для каждой фазы"
+ },
+ "ollamaModels": {
+ "title": "Модели Ollama",
+ "description": "Управляйте локально установленными моделями для задач AI-агента",
+ "installed": "Установленные модели",
+ "installedCount": "{{count}} модел(и)",
+ "noModels": "Модели LLM не установлены",
+ "recommended": "Рекомендуется для разработки",
+ "recommendedDescription": "Популярные модели, оптимизированные для генерации кода и рассуждений",
+ "download": "Загрузить",
+ "downloading": "Загрузка...",
+ "refresh": "Обновить",
+ "loading": "Загрузка моделей...",
+ "ollamaNotAvailable": "Подключите Ollama в настройках Аккаунтов для управления моделями"
+ }
+ },
+ "workspace": {
+ "roles": {
+ "backend": "Бэкенд",
+ "frontend": "Фронтенд",
+ "mobile": "Мобильный",
+ "shared": "Общий",
+ "apiGateway": "API-шлюз",
+ "worker": "Воркер",
+ "other": "Другое"
+ }
+ },
+ "integrations": {
+ "title": "Интеграции",
+ "description": "Управление аккаунтами Claude и API-ключами",
+ "claudeAccounts": "Аккаунты Claude",
+ "claudeAccountsDescription": "Добавьте несколько подписок Claude для автоматического переключения при достижении лимитов запросов.",
+ "claudeAccountsWarning": "При аутентификации убедитесь, что вошли в правильный аккаунт Claude в браузере. Каждый профиль должен использовать отдельную подписку.",
+ "noAccountsYet": "Аккаунты пока не настроены",
+ "default": "По умолчанию",
+ "active": "Активен",
+ "authenticated": "Аутентифицирован",
+ "needsAuth": "Требуется авторизация",
+ "authenticate": "Аутентифицировать",
+ "authenticating": "Аутентификация...",
+ "setActive": "Сделать активным",
+ "manualTokenEntry": "Ввод токена вручную",
+ "runSetupToken": "Запустите claude и введите /login для аутентификации",
+ "tokenPlaceholder": "sk-ant-oat01-...",
+ "emailPlaceholder": "Email (необязательно, для отображения)",
+ "saveToken": "Сохранить токен",
+ "accountNamePlaceholder": "Название аккаунта (напр., Работа, Личный)",
+ "autoSwitching": "Автоматическое переключение аккаунтов",
+ "autoSwitchingDescription": "Автоматически переключаться между аккаунтами Claude во избежание прерываний. Настройте проактивный мониторинг для переключения до достижения лимитов.",
+ "enableAutoSwitching": "Включить автоматическое переключение",
+ "masterSwitch": "Главный переключатель для всех функций автосмены",
+ "proactiveMonitoring": "Проактивный мониторинг",
+ "proactiveDescription": "Регулярно проверять использование и переключаться до достижения лимитов",
+ "checkUsageEvery": "Проверять использование каждые",
+ "seconds15": "15 секунд",
+ "seconds30": "30 секунд (рекомендуется)",
+ "minute1": "1 минуту",
+ "disabled": "Отключено",
+ "sessionThreshold": "Порог использования сессии",
+ "sessionThresholdDescription": "Переключаться при достижении данного уровня использования сессии (рекомендуется: 95%)",
+ "weeklyThreshold": "Недельный порог использования",
+ "weeklyThresholdDescription": "Переключаться при достижении данного уровня недельного использования (рекомендуется: 99%)",
+ "reactiveRecovery": "Реактивное восстановление",
+ "reactiveDescription": "Автосмена при неожиданном достижении лимита запросов",
+ "autoSwitchOnAuthFailure": "Автосмена при сбое авторизации",
+ "autoSwitchOnAuthFailureDescription": "Автоматически переключаться на другой аутентифицированный аккаунт при сбое аутентификации",
+ "apiKeys": "API-ключи",
+ "apiKeysInfo": "Ключи, установленные здесь, используются по умолчанию. Отдельные проекты могут переопределить их в своих настройках.",
+ "openaiKey": "API-ключ OpenAI",
+ "openaiKeyDescription": "Необходим для бэкенда памяти Graphiti (эмбеддинги)",
+ "toast": {
+ "authSuccess": "Профиль аутентифицирован",
+ "authSuccessWithEmail": "Подключено как {{email}}",
+ "authSuccessGeneric": "Аутентификация выполнена. Теперь можно использовать этот профиль.",
+ "authStartFailed": "Ошибка аутентификации",
+ "addProfileFailed": "Не удалось добавить профиль",
+ "loadProfilesFailed": "Не удалось загрузить профили",
+ "deleteProfileFailed": "Не удалось удалить профиль",
+ "renameProfileFailed": "Не удалось переименовать профиль",
+ "setActiveProfileFailed": "Не удалось установить активный профиль",
+ "profileCreatedAuthFailed": "Профиль создан — требуется аутентификация",
+ "profileCreatedAuthFailedDescription": "Профиль добавлен, но аутентификация не удалась. Нажмите кнопку входа для аутентификации.",
+ "tokenSaved": "Токен сохранён",
+ "tokenSavedDescription": "Ваш токен успешно сохранён.",
+ "tokenSaveFailed": "Не удалось сохранить токен",
+ "settingsUpdateFailed": "Не удалось обновить настройки",
+ "tryAgain": "Попробуйте ещё раз.",
+ "terminalCreationFailed": "Не удалось создать терминал авторизации",
+ "terminalCreationFailedDescription": "Не удалось запустить процесс аутентификации. {{error}}",
+ "maxTerminalsReached": "Достигнуто максимальное количество терминалов",
+ "maxTerminalsReachedDescription": "Закройте часть терминалов и попробуйте снова. Одновременно можно открыть не более 12 терминалов.",
+ "terminalError": "Ошибка терминала",
+ "terminalErrorDescription": "Не удалось создать терминал: {{error}}",
+ "authProcessFailed": "Процесс аутентификации не удалось запустить",
+ "authProcessFailedDescription": "Не удалось создать терминал аутентификации. Попробуйте снова или проверьте логи для получения подробностей."
+ },
+ "alerts": {
+ "profileCreatedAuthFailed": "Профиль создан, но не удалось подготовить аутентификацию: {{error}}",
+ "authPrepareFailed": "Не удалось подготовить аутентификацию: {{error}}",
+ "authStartFailedMessage": "Не удалось запустить аутентификацию. Попробуйте ещё раз."
+ }
+ },
+ "accounts": {
+ "title": "Аккаунты",
+ "description": "Управление аккаунтами Claude и API-эндпоинтами",
+ "tabs": {
+ "claudeCode": "Claude Code",
+ "customEndpoints": "Пользовательские эндпоинты"
+ },
+ "claudeCode": {
+ "description": "Добавьте несколько подписок Claude для автоматического переключения при достижении лимитов запросов.",
+ "noAccountsYet": "Аккаунты пока не настроены",
+ "default": "По умолчанию",
+ "active": "Активен",
+ "authenticated": "Аутентифицирован",
+ "needsAuth": "Требуется авторизация",
+ "authenticate": "Аутентифицировать",
+ "authenticating": "Аутентификация...",
+ "setActive": "Сделать активным",
+ "manualTokenEntry": "Ввод токена вручную",
+ "runSetupToken": "Запустите claude и введите /login для аутентификации",
+ "tokenPlaceholder": "sk-ant-oat01-...",
+ "emailPlaceholder": "Email (необязательно, для отображения)",
+ "saveToken": "Сохранить токен",
+ "accountNamePlaceholder": "Название аккаунта (напр., Работа, Личный)"
+ },
+ "customEndpoints": {
+ "description": "Настройте пользовательские Anthropic-совместимые API-эндпоинты",
+ "addButton": "Добавить профиль",
+ "activeBadge": "Активен",
+ "customModels": "Пользовательские модели: {{models}}",
+ "setActive": {
+ "label": "Сделать активным",
+ "loading": "Применение..."
+ },
+ "switchToOauth": {
+ "label": "Использовать Claude Code",
+ "loading": "Переключение..."
+ },
+ "tooltips": {
+ "edit": "Редактировать профиль",
+ "deleteActive": "Нельзя удалить активный профиль",
+ "deleteInactive": "Удалить профиль"
+ },
+ "empty": {
+ "title": "Нет пользовательских эндпоинтов",
+ "description": "Настройте пользовательские Anthropic-совместимые API-эндпоинты для использования альтернативных провайдеров.",
+ "action": "Добавить профиль"
+ },
+ "dialog": {
+ "deleteTitle": "Удалить профиль",
+ "deleteDescription": "Вы уверены, что хотите удалить «{{name}}»? Это действие нельзя отменить.",
+ "cancel": "Отмена",
+ "delete": "Удалить",
+ "deleting": "Удаление..."
+ }
+ },
+ "autoSwitching": {
+ "title": "Автоматическое переключение аккаунтов",
+ "description": "Автоматически переключаться между аккаунтами во избежание прерываний. Настройте проактивный мониторинг для переключения до достижения лимитов.",
+ "enableAutoSwitching": "Включить автоматическое переключение",
+ "masterSwitch": "Главный переключатель для всех функций автосмены",
+ "proactiveMonitoring": "Проактивный мониторинг",
+ "proactiveDescription": "Регулярно проверять использование и переключаться до достижения лимитов",
+ "sessionThreshold": "Порог использования сессии",
+ "sessionThresholdDescription": "Переключаться при достижении данного уровня использования сессии (рекомендуется: 95%)",
+ "weeklyThreshold": "Недельный порог использования",
+ "weeklyThresholdDescription": "Переключаться при достижении данного уровня недельного использования (рекомендуется: 99%)",
+ "reactiveRecovery": "Реактивное восстановление",
+ "reactiveDescription": "Автосмена при неожиданном достижении лимита запросов",
+ "autoSwitchOnAuthFailure": "Автосмена при сбое авторизации",
+ "autoSwitchOnAuthFailureDescription": "Автоматически переключаться на другой аутентифицированный аккаунт при сбое аутентификации"
+ },
+ "priority": {
+ "title": "Приоритет аккаунтов",
+ "description": "Перетащите для изменения порядка. Система будет переключаться на следующий доступный аккаунт по порядку.",
+ "tabs": {
+ "default": "По умолчанию",
+ "crossProvider": "Кросс-провайдерный"
+ },
+ "crossProviderDescription": "Этот приоритет используется при активном кросс-провайдерном режиме. Когда несколько аккаунтов используют одного провайдера, система выбирает лучший доступный на основе этого порядка.",
+ "setActive": "Сделать активным",
+ "setActiveTooltip": "Сделать основным аккаунтом",
+ "noAccounts": "Аккаунты не настроены. Добавьте аккаунты выше для установки приоритета.",
+ "noEmail": "Нет email",
+ "active": "Активен",
+ "inUse": "Используется",
+ "next": "Следующий",
+ "unlimited": "Без ограничений",
+ "unavailable": "Недоступен",
+ "typeOAuth": "OAuth",
+ "typeAPI": "API",
+ "payPerUse": "Оплата за использование",
+ "needsAuth": "Не аутентифицирован",
+ "duplicateUsage": "Дублирующийся шаблон использования",
+ "duplicateUsageHint": "Эти OAuth-профили имеют совпадающие значения использования. Убедитесь, что каждый профиль привязан к разному аккаунту, если это неожиданно.",
+ "needsReauth": "Требуется повторная авторизация",
+ "needsReauthHint": "Токен обновления этого профиля недействителен. Нажмите для повторной аутентификации.",
+ "sessionUsage": "Использование сессии (5-часовое окно)",
+ "weeklyUsage": "Недельное использование (7-дневное окно)",
+ "oauthSection": "Аккаунты Claude (сначала циклически перебираются)",
+ "apiSection": "Запасные эндпоинты (когда все аккаунты исчерпаны)",
+ "tipTitle": "Как работает приоритет",
+ "tipDescription": "Аккаунты Claude входят в вашу подписку и будут перебираться первыми. API-эндпоинты оплачиваются за запрос и используются как запасные, когда все аккаунты Claude достигли своих лимитов.",
+ "status": {
+ "healthy": "В норме",
+ "moderate": "Умеренно",
+ "highUsage": "Высокое использование",
+ "nearLimit": "Близко к лимиту",
+ "rateLimited": "Лимит запросов"
+ }
+ },
+ "toast": {
+ "loadProfilesFailed": "Не удалось загрузить профили",
+ "addProfileFailed": "Не удалось добавить профиль",
+ "deleteProfileFailed": "Не удалось удалить профиль",
+ "renameProfileFailed": "Не удалось переименовать профиль",
+ "setActiveProfileFailed": "Не удалось установить активный профиль",
+ "tokenSaved": "Токен сохранён",
+ "tokenSavedDescription": "Ваш токен успешно сохранён.",
+ "tokenSaveFailed": "Не удалось сохранить токен",
+ "settingsUpdateFailed": "Не удалось обновить настройки",
+ "tryAgain": "Попробуйте ещё раз."
+ },
+ "alerts": {
+ "profileCreatedAuthFailed": "Профиль создан, но не удалось подготовить аутентификацию: {{error}}",
+ "authPrepareFailed": "Не удалось подготовить аутентификацию: {{error}}",
+ "authStartFailedMessage": "Не удалось запустить аутентификацию. Попробуйте ещё раз."
+ }
+ },
+ "providers": {
+ "card": {
+ "oauth": "OAuth",
+ "codex": "Codex",
+ "codexSubscription": "Подписка Codex",
+ "claudeCode": "Claude Code",
+ "claudeCodeSubscription": "Подписка Claude Code",
+ "zaiCodingPlan": "Тарифный план для разработки",
+ "zaiUsageBased": "Оплата за использование",
+ "zaiCodingPlanSubscription": "Z.AI Тарифный план для разработки",
+ "apiKey": "API-ключ",
+ "active": "Активен",
+ "setDefault": "Сделать активным",
+ "edit": "Редактировать аккаунт",
+ "reauth": "Повторно аутентифицироваться",
+ "delete": "Удалить аккаунт",
+ "showKey": "Показать API-ключ",
+ "hideKey": "Скрыть API-ключ",
+ "oauthAccount": "OAuth-аккаунт",
+ "oauthLinked": "Связанный аккаунт",
+ "noEndpoint": "Нет эндпоинта",
+ "customModels": "{{count}} модел(и) настроено"
+ },
+ "section": {
+ "envDetected": "Из окружения",
+ "envCredentialDetected": "Учётные данные обнаружены из переменной окружения {{envVar}}",
+ "noAccounts": "Аккаунты не настроены",
+ "addOAuth": "Добавить OAuth-аккаунт",
+ "addClaudeCode": "Добавить аккаунт Claude Code",
+ "addCodexSubscription": "Добавить подписку Codex",
+ "addCodingPlan": "Добавить тарифный план для разработки",
+ "addUsageBased": "Добавить API-ключ с оплатой за использование",
+ "addApiKey": "Добавить API-ключ",
+ "addEndpoint": "Добавить эндпоинт"
+ },
+ "dialog": {
+ "addTitle": "Добавить аккаунт",
+ "editTitle": "Редактировать аккаунт",
+ "deleteTitle": "Удалить аккаунт?",
+ "deleteDescription": "Вы уверены, что хотите удалить этот аккаунт? Это действие нельзя отменить.",
+ "cancel": "Отмена",
+ "close": "Закрыть",
+ "delete": "Удалить",
+ "deleting": "Удаление...",
+ "save": "Сохранить изменения",
+ "add": "Добавить аккаунт",
+ "optional": "(необязательно)",
+ "oauthDescription": "Подключиться с помощью OAuth-аутентификации",
+ "apiKeyDescription": "Добавьте ваш API-ключ и конфигурацию",
+ "zaiCodingPlanDescription": "Добавьте ваш API-ключ Z.AI Coding Plan для использования моделей GLM по подписке",
+ "zaiUsageBasedDescription": "Добавьте ваш API-ключ Z.AI с оплатой за использование для доступа к моделям GLM",
+ "codexOAuthDescription": "Войдите с подпиской ChatGPT Plus или Pro для использования моделей Codex",
+ "codexAuthenticating": "Открывается вход в OpenAI в браузере...",
+ "codexWaiting": "Ожидание аутентификации в браузере...",
+ "codexSuccess": "Аутентификация через OpenAI Codex выполнена",
+ "codexError": "Ошибка аутентификации OpenAI: {{error}}",
+ "codexAuthenticate": "Аутентифицироваться через OpenAI",
+ "codexReauthenticate": "Повторно аутентифицироваться через OpenAI",
+ "oauthInstructions": "Для добавления OAuth-аккаунта используйте процесс аутентификации Claude Code на вкладке Claude Code выше. OAuth-аккаунты привязаны к вашей подписке Claude.ai.",
+ "oauthAuthenticate": "Аутентифицироваться через Anthropic",
+ "oauthReauthenticate": "Повторно аутентифицироваться через Anthropic",
+ "oauthAuthenticating": "Открывается браузер...",
+ "oauthWaiting": "Ожидание авторизации...",
+ "oauthSuccess": "Аутентифицировано как {{email}}",
+ "oauthError": "Ошибка аутентификации: {{error}}",
+ "oauthFallback": "Использовать терминал (запасной вариант)",
+ "oauthFallbackDescription": "Если вход через браузер не работает, используйте встроенный терминал",
+ "oauthNameRequired": "Введите название аккаунта перед аутентификацией",
+ "modelsDescription": "Добавьте ID моделей, доступных на этом эндпоинте. Они появятся в выборщике моделей.",
+ "fields": {
+ "name": "Название аккаунта",
+ "apiKey": "API-ключ",
+ "baseUrl": "Базовый URL",
+ "region": "Регион AWS",
+ "models": "Модели"
+ },
+ "placeholders": {
+ "name": "Мой аккаунт",
+ "apiKey": "sk-...",
+ "baseUrl": "https://...",
+ "modelId": "ID модели (напр. llama-3.1-70b)",
+ "modelLabel": "Отображаемое имя"
+ },
+ "toast": {
+ "added": "Аккаунт добавлен",
+ "updated": "Аккаунт обновлён",
+ "error": "Не удалось сохранить аккаунт",
+ "duplicateEmail": "Этот email уже зарегистрирован как «{{existingName}}»",
+ "createProfileFailed": "Не удалось создать профиль",
+ "authPrepareFailed": "Не удалось подготовить терминал",
+ "unexpectedError": "Неожиданная ошибка"
+ }
+ },
+ "toast": {
+ "deleted": "Аккаунт удалён",
+ "deleteFailed": "Не удалось удалить аккаунт",
+ "reauthStarted": "Открывается аутентификация...",
+ "reauthSuccess": "Повторная аутентификация выполнена успешно",
+ "reauthFailed": "Повторная аутентификация не удалась"
+ },
+ "categories": {
+ "popular": "Популярные",
+ "infrastructure": "Инфраструктура",
+ "local": "Локальные и пользовательские"
+ },
+ "ollama": {
+ "connection": {
+ "checking": "Проверка подключения к Ollama...",
+ "connected": "Подключено",
+ "connectedDescription": "Ollama запущен и готов к работе",
+ "modelsAvailable": "Установлено {{count}} модел(и) LLM",
+ "noModels": "Модели LLM пока не установлены",
+ "customUrl": "Пользовательский URL",
+ "customUrlPlaceholder": "http://localhost:11434",
+ "notInstalled": "Ollama не установлен",
+ "notInstalledDescription": "Установите Ollama для запуска открытых AI-моделей локально",
+ "notRunning": "Ollama не запущен",
+ "notRunningDescription": "Запустите сервис Ollama для подключения",
+ "install": "Установить Ollama",
+ "retry": "Повторить",
+ "learnMore": "Узнать больше",
+ "autoConnected": "Автоматически подключено как локальный провайдер",
+ "startCommand": "Выполните 'ollama serve' в терминале"
+ }
+ }
+ },
+ "debug": {
+ "title": "Отладка и логи",
+ "description": "Доступ к логам и отладочной информации для диагностики",
+ "errorReporting": {
+ "label": "Анонимные отчёты об ошибках",
+ "description": "Отправлять отчёты о сбоях для улучшения Aperant. Персональные данные и код не собираются."
+ },
+ "openLogsFolder": "Открыть папку логов",
+ "copyDebugInfo": "Скопировать отладочную информацию",
+ "copied": "Скопировано!",
+ "loadInfo": "Загрузить отладочную информацию",
+ "systemInfo": "Информация о системе",
+ "logsLocation": "Расположение логов",
+ "recentErrors": "Последние ошибки",
+ "noRecentErrors": "Последних ошибок нет",
+ "helpTitle": "Сообщение о проблемах",
+ "helpText": "При сообщении об ошибках нажмите «Скопировать отладочную информацию» для получения сведений о системе и последних ошибках, которые помогут нам диагностировать проблему."
+ },
+ "projectSettings": {
+ "noProjectSelected": {
+ "title": "Проект не выбран",
+ "description": "Выберите проект в боковой панели для настройки его параметров."
+ }
+ },
+ "mcp": {
+ "title": "Обзор MCP-серверов",
+ "titleWithProject": "Обзор MCP-серверов для {{projectName}}",
+ "description": "Настройте, какие MCP-серверы доступны агентам в этом проекте",
+ "descriptionNoProject": "Выберите проект для настройки MCP-серверов",
+ "serversEnabled": "Включено серверов: {{count}}",
+ "configuration": "Конфигурация MCP-серверов",
+ "configurationHint": "Отключённые серверы снижают использование контекста и время запуска",
+ "noProjectSelected": "Проект не выбран",
+ "noProjectSelectedDescription": "Выберите проект из выпадающего списка для просмотра и настройки MCP-серверов.",
+ "projectNotInitialized": "Проект не инициализирован",
+ "projectNotInitializedDescription": "Инициализируйте Aperant для этого проекта, чтобы настроить MCP-серверы.",
+ "browserAutomation": "Автоматизация браузера (только для QA-агентов)",
+ "alwaysEnabled": "всегда включено",
+ "addServer": "Добавить сервер",
+ "addMcpTo": "Добавить MCP-сервер к {{agent}}",
+ "addMcpDescription": "Выберите MCP-сервер для добавления к этому агенту",
+ "allMcpsAdded": "Все доступные MCP-серверы уже добавлены",
+ "added": "добавлен",
+ "removed": "удалён",
+ "remove": "Удалить",
+ "restore": "Восстановить",
+ "noMcpServers": "Нет MCP-серверов",
+ "cannotRemove": "Нельзя удалить (обязательный)",
+ "servers": {
+ "context7": {
+ "name": "Context7",
+ "description": "Поиск документации для библиотек"
+ },
+ "graphiti": {
+ "name": "Graphiti Memory",
+ "description": "Граф знаний для межсессионного контекста",
+ "notConfigured": "Требуется настройка памяти (см. настройки Памяти)"
+ },
+ "linear": {
+ "name": "Linear",
+ "description": "Интеграция с системой управления проектами",
+ "notConfigured": "Требуется интеграция с Linear (см. настройки Linear)"
+ },
+ "electron": {
+ "name": "Electron",
+ "description": "Автоматизация десктопного приложения через Chrome DevTools"
+ },
+ "puppeteer": {
+ "name": "Puppeteer",
+ "description": "Автоматизация веб-браузера для тестирования"
+ },
+ "autoClaude": {
+ "name": "Инструменты Aperant",
+ "description": "Отслеживание прогресса сборки"
+ }
+ },
+ "customServers": "Пользовательские серверы",
+ "addCustomServer": "Добавить пользовательский сервер",
+ "editCustomServer": "Редактировать пользовательский сервер",
+ "customServerDescription": "Добавьте MCP-сервер на основе команды или HTTP",
+ "serverType": "Тип сервера",
+ "typeCommand": "Команда (npx/npm)",
+ "typeHttp": "HTTP",
+ "serverName": "Название",
+ "serverNamePlaceholder": "Мой MCP-сервер",
+ "serverDescription": "Описание",
+ "serverDescriptionPlaceholder": "Что делает этот сервер",
+ "command": "Команда",
+ "args": "Аргументы",
+ "argsHint": "Аргументы, разделённые пробелами",
+ "url": "URL",
+ "headers": "Заголовки",
+ "headerName": "Название заголовка",
+ "headerValue": "Значение заголовка",
+ "noCustomServers": "Пользовательские серверы не настроены. Добавьте один для использования с агентами.",
+ "errorNameRequired": "Название сервера обязательно",
+ "errorIdExists": "Сервер с таким ID уже существует",
+ "errorCommandRequired": "Команда обязательна для серверов на основе команды",
+ "errorUrlRequired": "URL обязателен для HTTP-серверов",
+ "testConnection": "Проверить",
+ "testing": "Проверка...",
+ "authToken": "Токен аутентификации",
+ "authTokenPlaceholder": "Вставьте ваш API-токен или PAT сюда",
+ "authTokenHint": "Используется как Bearer-токен в заголовке Authorization",
+ "advancedHeaders": "Дополнительные заголовки",
+ "status": {
+ "healthy": "Сервер отвечает",
+ "unhealthy": "Сервер не отвечает",
+ "needsAuth": "Требуется аутентификация",
+ "checking": "Проверка...",
+ "unknown": "Статус неизвестен"
+ },
+ "hints": {
+ "github": "Похоже на GitHub MCP-сервер. Вам потребуется Personal Access Token с соответствующими правами.",
+ "createGithubPat": "Создать GitHub PAT",
+ "google": "Похоже на Google API. Вам потребуется OAuth-токен или API-ключ.",
+ "createGoogleToken": "Создать учётные данные Google",
+ "anthropic": "Похоже на Anthropic API. Вам потребуется API-ключ.",
+ "createAnthropicKey": "Создать Anthropic API-ключ",
+ "openai": "Похоже на OpenAI API. Вам потребуется API-ключ.",
+ "createOpenaiKey": "Создать OpenAI API-ключ"
+ }
+ },
+ "terminalFonts": {
+ "title": "Шрифты терминала",
+ "description": "Настройте внешний вид и поведение шрифтов терминала",
+ "configActions": "Конфигурация:",
+ "export": "Экспорт JSON",
+ "import": "Импорт JSON",
+ "copy": "Копировать в буфер обмена",
+ "fontConfig": {
+ "title": "Конфигурация шрифта",
+ "description": "Настройте семейство, размер, насыщенность, межстрочный интервал и трекинг",
+ "fontFamily": "Семейство шрифтов",
+ "fontFamilyDescription": "Основной моноширинный шрифт для текста терминала",
+ "selectFont": "Выберите шрифт...",
+ "searchFont": "Поиск шрифтов...",
+ "noFonts": "Шрифты не найдены",
+ "fontChain": "Цепочка шрифтов:",
+ "fontSize": "Размер шрифта",
+ "fontSizeDescription": "Базовый размер шрифта в пикселях (10–24px)",
+ "decreaseFontSize": "Уменьшить размер шрифта на {{step}}px",
+ "increaseFontSize": "Увеличить размер шрифта на {{step}}px",
+ "pixels": "пикселей",
+ "fontWeight": "Насыщенность шрифта",
+ "fontWeightDescription": "Насыщенность шрифта от 100 (тонкий) до 900 (чёрный) с шагом 100",
+ "commonWeights": "Часто используемые: 400 (обычный), 600 (полужирный), 700 (жирный)",
+ "decreaseFontWeight": "Уменьшить насыщенность шрифта на {{step}}",
+ "increaseFontWeight": "Увеличить насыщенность шрифта на {{step}}",
+ "lineHeight": "Межстрочный интервал",
+ "lineHeightDescription": "Межстрочный интервал как множитель от размера шрифта (1.0–2.0)",
+ "letterSpacing": "Трекинг",
+ "letterSpacingDescription": "Горизонтальное расстояние между символами (от -2 до 5px)"
+ },
+ "cursorConfig": {
+ "title": "Конфигурация курсора",
+ "description": "Настройте стиль, мигание и акцентный цвет курсора",
+ "cursorStyle": "Стиль курсора",
+ "cursorStyleDescription": "Выберите внешний вид курсора терминала",
+ "selectStyle": "Выберите стиль курсора...",
+ "currentStyle": "Текущий:",
+ "styleBlock": "Блок",
+ "styleBlockDescription": "Полный блочный курсор",
+ "styleUnderline": "Подчёркивание",
+ "styleUnderlineDescription": "Курсор в виде подчёркивания",
+ "styleBar": "Полоса",
+ "styleBarDescription": "Курсор в виде вертикальной полосы",
+ "cursorBlink": "Мигание курсора",
+ "cursorBlinkDescription": "Включить или отключить анимацию мигания курсора",
+ "blinkStatus": "Статус:",
+ "enabled": "Включено",
+ "disabled": "Отключено",
+ "cursorAccentColor": "Акцентный цвет курсора",
+ "cursorAccentColorDescription": "Выберите цвет курсора терминала",
+ "cursorColorLabel": "Акцентный цвет курсора",
+ "cursorColorDescription": "Текущий цвет: {{color}}",
+ "pickColor": "Нажмите для выбора цвета",
+ "resetColor": "Сбросить к чёрному",
+ "reset": "Сброс",
+ "preview": "Предпросмотр:"
+ },
+ "performanceConfig": {
+ "title": "Настройки производительности",
+ "description": "Настройте лимит прокрутки и другие параметры производительности",
+ "presets": "Быстрые шаблоны",
+ "presetsDescription": "Общие лимиты прокрутки для различных сценариев использования",
+ "scrollback": "Лимит прокрутки",
+ "scrollbackDescription": "Максимальное количество строк в истории терминала",
+ "scrollbackPresets": "Быстрые шаблоны",
+ "presetMinimal": "Минимальный",
+ "presetMinimalDescription": "Минимальная история (1K строк)",
+ "presetStandard": "Стандартный",
+ "presetStandardDescription": "Стандартная история (10K строк)",
+ "presetExtended": "Расширенный",
+ "presetExtendedDescription": "Расширенная история (50K строк)",
+ "presetMaximum": "Максимальный",
+ "presetMaximumDescription": "Максимальная история (100K строк)",
+ "decreaseScrollback": "Уменьшить лимит прокрутки на {{step}}",
+ "increaseScrollback": "Увеличить лимит прокрутки на {{step}}",
+ "lines": "строк",
+ "kValue": "{{value}}K",
+ "scrollbackValue": "{{value}} строк"
+ },
+ "presets": {
+ "title": "Быстрые шаблоны",
+ "description": "Применяйте предустановленные настройки шрифтов терминала или сохраняйте свои",
+ "builtin": "Встроенные шаблоны",
+ "builtinDescription": "Нажмите для применения предустановленного шаблона",
+ "vscode": "Consolas 14px, блочный курсор",
+ "vscodeName": "VS Code",
+ "intellij": "JetBrains Mono 13px, блочный курсор",
+ "intellijName": "IntelliJ IDEA",
+ "macos": "SF Mono 13px, блочный курсор",
+ "macosName": "macOS Terminal",
+ "ubuntu": "Ubuntu Mono 13px, блочный курсор",
+ "ubuntuName": "Ubuntu Terminal",
+ "reset": "Сбросить к значениям по умолчанию",
+ "resetDescription": "Восстановить настройки по умолчанию для вашей операционной системы",
+ "resetToOS": "Сбросить к значениям по умолчанию {{os}}",
+ "resetButton": "Сбросить к настройкам ОС",
+ "custom": "Пользовательские шаблоны",
+ "customDescription": "Сохраните текущую конфигурацию как пользовательский шаблон",
+ "presetNamePlaceholder": "Название шаблона...",
+ "savePreset": "Сохранить текущую конфигурацию как шаблон",
+ "applyPreset": "Применить этот шаблон",
+ "deletePreset": "Удалить этот шаблон",
+ "noCustomPresets": "Пользовательских шаблонов пока нет. Сохраните текущую конфигурацию для начала.",
+ "duplicateName": "Шаблон с таким именем уже существует",
+ "saved": "Шаблон «{{name}}» сохранён",
+ "deleted": "Шаблон «{{name}}» удалён",
+ "unknownFont": "Неизвестный",
+ "applyFailed": "Не удалось применить шаблон «{{name}}»",
+ "presetNameLabel": "Название шаблона",
+ "summary": "{{font}}, {{size}}px, курсор {{cursor}}"
+ },
+ "preview": {
+ "title": "Предпросмотр в реальном времени",
+ "description": "Предпросмотр настроек терминала в реальном времени (обновление в течение 300 мс)",
+ "ariaLabel": "Предпросмотр шрифтов терминала",
+ "infoText": "Этот предпросмотр обновляется в течение 300 мс после любого изменения, показывая, как настройки будут выглядеть в реальных терминалах."
+ },
+ "importExport": {
+ "exportSuccess": "Настройки успешно экспортированы",
+ "exportFailed": "Не удалось экспортировать настройки",
+ "importSuccess": "Настройки успешно импортированы",
+ "importFailed": "Не удалось импортировать настройки: неверный формат JSON",
+ "importFailedRange": "Не удалось импортировать настройки: значения вне допустимого диапазона",
+ "copySuccess": "Настройки скопированы в буфер обмена",
+ "copyFailed": "Не удалось скопировать в буфер обмена",
+ "fileTooLarge": "Файл импорта слишком большой (макс. 10KB)",
+ "readError": "Не удалось прочитать файл"
+ },
+ "slider": {
+ "decrease": "Уменьшить {{label}} на {{step}}",
+ "increase": "Увеличить {{label}} на {{step}}",
+ "currentValue": "Текущее значение: {{value}}"
+ }
+ },
+ "agents": {
+ "pr_template_filler": {
+ "label": "Заполнитель шаблонов PR",
+ "description": "AI заполняет шаблоны GitHub PR на основе изменений кода"
+ }
+ },
+ "provider": {
+ "title": "AI-провайдер",
+ "description": "Настройте предпочтения AI-провайдера и модели",
+ "selection": {
+ "label": "Провайдер",
+ "description": "Выберите AI-провайдера для задач агента",
+ "anthropic": "Anthropic",
+ "openai": "OpenAI",
+ "ollama": "Ollama (локальный)",
+ "openrouter": "OpenRouter"
+ },
+ "apiKey": {
+ "label": "API-ключ",
+ "description": "Ваш API-ключ для выбранного провайдера",
+ "placeholder": "Введите ваш API-ключ",
+ "anthropicPlaceholder": "sk-ant-...",
+ "openaiPlaceholder": "sk-...",
+ "openrouterPlaceholder": "sk-or-...",
+ "validation": {
+ "required": "API-ключ обязателен для этого провайдера",
+ "invalid": "Неверный формат API-ключа"
+ }
+ },
+ "ollama": {
+ "endpointUrl": "URL эндпоинта Ollama",
+ "endpointDescription": "URL, по которому запущен ваш экземпляр Ollama",
+ "endpointPlaceholder": "http://localhost:11434",
+ "validation": {
+ "urlRequired": "URL эндпоинта обязателен для Ollama",
+ "urlInvalid": "Неверный формат URL (должен начинаться с http:// или https://)"
+ }
+ },
+ "phaseModels": {
+ "title": "Настройки модели для каждой фазы",
+ "description": "Настройте, какую модель использовать для каждой фазы конвейера",
+ "spec": {
+ "label": "Модель создания спецификации",
+ "description": "Модель для исследования, требований и сбора контекста"
+ },
+ "planning": {
+ "label": "Модель планирования",
+ "description": "Модель для планирования реализации и архитектуры"
+ },
+ "coding": {
+ "label": "Модель разработки",
+ "description": "Модель для реализации кода"
+ },
+ "qa": {
+ "label": "Модель QA-проверки",
+ "description": "Модель для обеспечения качества и валидации"
+ },
+ "placeholder": "Выберите модель",
+ "useDefault": "Использовать модель по умолчанию"
+ },
+ "testConnection": {
+ "label": "Проверить подключение",
+ "testing": "Проверка...",
+ "success": "Подключение успешно",
+ "failure": "Подключение не удалось"
+ },
+ "toast": {
+ "saved": {
+ "title": "Настройки провайдера сохранены",
+ "description": "Конфигурация вашего AI-провайдера обновлена."
+ },
+ "error": {
+ "title": "Не удалось сохранить настройки провайдера",
+ "description": "При сохранении конфигурации провайдера произошла ошибка."
+ }
+ }
+ }
+}
diff --git a/apps/desktop/src/shared/i18n/locales/ru/taskReview.json b/apps/desktop/src/shared/i18n/locales/ru/taskReview.json
new file mode 100644
index 0000000000..a0741e9ff4
--- /dev/null
+++ b/apps/desktop/src/shared/i18n/locales/ru/taskReview.json
@@ -0,0 +1,162 @@
+{
+ "terminal": {
+ "openTerminal": "Открыть терминал",
+ "openInbuilt": "Открыть во встроенном терминале",
+ "openExternal": "Открыть во внешнем терминале"
+ },
+ "merge": {
+ "branchHasNewCommits": "Ветка {{branch}} содержит {{count}} новый коммит.",
+ "branchHasNewCommits_other": "Ветка {{branch}} содержит {{count}} новых коммита.",
+ "branchHasNewCommitsSinceWorktree": "Ветка {{branch}} содержит {{count}} новый коммит с момента создания этого воркдерева.",
+ "branchHasNewCommitsSinceWorktree_other": "Ветка {{branch}} содержит {{count}} новых коммита с момента создания этого воркдерева.",
+ "filesNeedMerging": "{{count}} файл требует слияния.",
+ "filesNeedMerging_other": "{{count}} файла требуют слияния.",
+ "filesNeedIntelligentMerging": "{{count}} файл потребует интеллектуального слияния:",
+ "filesNeedIntelligentMerging_other": "{{count}} файла потребуют интеллектуального слияния:",
+ "branchHasNewCommitsSinceBuild": "Ветка {{branch}} содержит {{count}} новый коммит с начала этой сборки.",
+ "branchHasNewCommitsSinceBuild_other": "Ветка {{branch}} содержит {{count}} новых коммита с начала этой сборки.",
+ "filesNeedAIMergeDueToRenames": "{{count}} файл требует AI-слияния из-за {{renameCount}} переименования файла.",
+ "filesNeedAIMergeDueToRenames_other": "{{count}} файла требуют AI-слияния из-за {{renameCount}} переименований файлов.",
+ "filesNeedAIMergeDueToRenamesPlural": "{{count}} файл требует AI-слияния из-за {{renameCount}} переименований файлов.",
+ "filesNeedAIMergeDueToRenamesPlural_other": "{{count}} файла требуют AI-слияния из-за {{renameCount}} переименований файлов.",
+ "fileRenamesDetected": "{{count}} переименование файла обнаружено — AI выполнит слияние.",
+ "fileRenamesDetected_other": "{{count}} переименования файлов обнаружено — AI выполнит слияние.",
+ "filesRenamedOrMoved": "Файлы могли быть переименованы или перемещены — AI выполнит слияние.",
+ "alreadyMergedTitle": "Изменения уже в вашей ветке",
+ "alreadyMergedDescription": "Похоже, эти изменения уже существуют в вашей текущей ветке. Вы можете безопасно отметить эту задачу как выполненную.",
+ "alreadyMergedTooltip": "Изменения задачи уже присутствуют в вашей ветке. Пометка как выполнено очистит воркдерево без слияния.",
+ "matchingFiles": "Совпадающие файлы",
+ "supersededTitle": "Изменения устарели",
+ "supersededDescription": "Ваша текущая ветка содержит более новую версию этих изменений. Рассмотрите возможность отклонения этой задачи или просмотра сравнения.",
+ "supersededCompareTooltip": "Просмотрите подробное сравнение, чтобы увидеть, чем текущая ветка отличается от изменений этой задачи.",
+ "supersededDiscardTooltip": "Удалите воркдерево этой задачи, поскольку изменения больше не нужны.",
+ "status": {
+ "branchDiverged": "Ветки разошлись",
+ "aiWillResolve": "AI разрешит конфликт",
+ "filesRenamed": "Файлы переименованы",
+ "branchBehind": "Ветка отстаёт",
+ "readyToMerge": "Готово к слиянию",
+ "files": "файлы",
+ "file": "файл",
+ "conflict": "конфликт",
+ "conflicts": "конфликты",
+ "details": "Детали",
+ "refresh": "Обновить",
+ "stageOnly": "Только подготовить (проверить в IDE перед коммитом)",
+ "discardBuild": "Отклонить сборку"
+ },
+ "buttons": {
+ "stageWithAIMerge": "Подготовить с AI-слиянием",
+ "mergeWithAI": "Слить с AI",
+ "stageTo": "Подготовить в {{branch}}",
+ "mergeTo": "Слить в {{branch}}",
+ "resolving": "Разрешение...",
+ "staging": "Подготовка...",
+ "merging": "Слияние...",
+ "completing": "Завершение..."
+ },
+ "actions": {
+ "markAsDone": "Отметить как выполнено",
+ "discardTask": "Отклонить задачу",
+ "viewComparison": "Просмотреть сравнение"
+ }
+ },
+ "pr": {
+ "title": "Создать Pull Request",
+ "description": "Отправить ветку и создать pull request для «{{taskTitle}}»",
+ "errors": {
+ "unknown": "Произошла неизвестная ошибка при создании pull request",
+ "invalidBranchName": "Имя ветки содержит недопустимые символы. Используйте только буквы, цифры, дефисы (-), подчёркивания (_) и косую черту (/).",
+ "emptyTitle": "Заголовок pull request не может быть пустым."
+ },
+ "success": {
+ "created": "Pull request успешно создан!",
+ "alreadyExists": "Pull request для этой ветки уже существует"
+ },
+ "actions": {
+ "retry": "Повторить",
+ "creating": "Создание PR...",
+ "create": "Создать Pull Request"
+ },
+ "labels": {
+ "sourceBranch": "Исходная ветка",
+ "targetBranch": "Целевая ветка",
+ "commits": "Коммиты",
+ "changes": "Изменения",
+ "prTitle": "Заголовок PR (необязательно)",
+ "draftPR": "Создать как черновой PR",
+ "unknown": "Неизвестно"
+ },
+ "hints": {
+ "targetBranch": "Оставьте пустым для использования ветки по умолчанию",
+ "prTitle": "Оставьте пустым для использования заголовка задачи"
+ }
+ },
+ "mergeProgress": {
+ "stages": {
+ "analyzing": "Анализ изменений",
+ "detectingConflicts": "Обнаружение конфликтов",
+ "resolving": "Разрешение конфликтов",
+ "validating": "Проверка слияния",
+ "complete": "Слияние завершено",
+ "error": "Ошибка слияния",
+ "stalled": "Слияние зависло"
+ },
+ "conflictCounter": "{{found}} обнаружено, {{resolved}} разрешено",
+ "currentFile": "Текущий файл",
+ "viewLogs": "Просмотреть логи",
+ "hideLogs": "Скрыть логи",
+ "logTypes": {
+ "info": "Информация",
+ "warning": "Предупреждение",
+ "error": "Ошибка",
+ "conflict": "Конфликт",
+ "resolution": "Разрешение"
+ },
+ "completionMessage": "Все изменения успешно слиты.",
+ "errorMessage": "Во время процесса слияния произошла ошибка."
+ },
+ "stagedSuccess": {
+ "title": "Изменения успешно подготовлены",
+ "aiCommitMessage": "Сообщение коммита, сгенерированное AI",
+ "copied": "Скопировано!",
+ "copy": "Скопировать",
+ "editHint": "Отредактируйте по необходимости, затем скопируйте и используйте с",
+ "nextSteps": "Следующие шаги:",
+ "reviewChanges": "Проверьте подготовленные изменения с помощью",
+ "commitWhenReady": "Зафиксируйте, когда будете готовы:",
+ "pushToRemote": "Отправьте на удалённый сервер, когда удовлетворены результатом",
+ "cleaningUp": "Очистка...",
+ "markingDone": "Отметка как выполнено...",
+ "resetting": "Сброс...",
+ "deleteWorktreeAndMarkDone": "Удалить воркдерево и отметить как выполнено",
+ "markDoneOnly": "Только отметить как выполнено",
+ "markAsDone": "Отметить как выполнено",
+ "reviewAgain": "Проверить снова",
+ "commitMessagePlaceholder": "Сообщение коммита...",
+ "worktreeExplanation": "«Удалить воркдерево и отметить как выполнено» очищает изолированное рабочее пространство. «Только отметить как выполнено» оставляет его для справки.",
+ "errors": {
+ "failedToDeleteWorktree": "Не удалось удалить воркдерево",
+ "worktreeDeletedButStatusFailed": "Воркдерево удалено, но не удалось обновить статус задачи: {{error}}",
+ "failedToMarkAsDone": "Не удалось отметить как выполнено",
+ "failedToResetStagedState": "Не удалось сбросить состояние подготовки"
+ }
+ },
+ "bulkPR": {
+ "title": "Создать Pull Request-ы",
+ "description": "Создать pull request-ы для {{count}} выбранных задач",
+ "creating": "Создание PR {{current}} из {{total}}...",
+ "creatingPR": "Создание PR {{current}} из {{total}}",
+ "resultsDescription": "{{success}} успешно, {{failed}} с ошибками",
+ "tasksToProcess": "Задачи для обработки",
+ "targetBranchHint": "Оставьте пустым для использования ветки по умолчанию каждой задачи. Будет применено ко всем PR.",
+ "createAll": "Создать {{count}} PR",
+ "completed": "завершено",
+ "succeeded": "успешно",
+ "failed": "с ошибкой",
+ "skipped": "пропущено",
+ "alreadyExisted": "уже существовало",
+ "noWorktree": "Воркдерево для этой задачи не найдено",
+ "resultsDescriptionWithSkipped": "{{success}} успешно, {{skipped}} пропущено, {{failed}} с ошибками"
+ }
+}
diff --git a/apps/desktop/src/shared/i18n/locales/ru/tasks.json b/apps/desktop/src/shared/i18n/locales/ru/tasks.json
new file mode 100644
index 0000000000..9ffab06b77
--- /dev/null
+++ b/apps/desktop/src/shared/i18n/locales/ru/tasks.json
@@ -0,0 +1,357 @@
+{
+ "refreshTasks": "Обновить задачи",
+ "status": {
+ "backlog": "Бэклог",
+ "queue": "Очередь",
+ "todo": "К выполнению",
+ "in_progress": "В работе",
+ "review": "На проверке",
+ "prCreated": "PR создан",
+ "complete": "Завершено",
+ "archived": "В архиве"
+ },
+ "actions": {
+ "start": "Запустить",
+ "stop": "Остановить",
+ "recover": "Восстановить",
+ "resume": "Возобновить",
+ "archive": "Архивировать",
+ "delete": "Удалить",
+ "view": "Просмотреть детали",
+ "viewPR": "Просмотреть PR",
+ "moveTo": "Переместить в",
+ "taskActions": "Действия с задачей",
+ "selectTask": "Выбрать задачу: {{title}}"
+ },
+ "labels": {
+ "running": "Выполняется",
+ "aiReview": "AI-ревью",
+ "needsReview": "Требует проверки",
+ "pending": "Ожидает",
+ "stuck": "Застряло",
+ "incomplete": "Не завершено",
+ "recovering": "Восстановление...",
+ "needsRecovery": "Требует восстановления",
+ "needsResume": "Требует возобновления"
+ },
+ "reviewReason": {
+ "completed": "Завершено",
+ "hasErrors": "Есть ошибки",
+ "qaIssues": "Проблемы QA",
+ "approvePlan": "Одобрить план",
+ "stopped": "Остановлено"
+ },
+ "tooltips": {
+ "archiveTask": "Архивировать задачу",
+ "archiveAllDone": "Архивировать все выполненные задачи",
+ "viewPR": "Открыть pull request в браузере"
+ },
+ "creation": {
+ "title": "Создать новую задачу",
+ "description": "Опишите, что вы хотите создать",
+ "placeholder": "Опишите вашу задачу..."
+ },
+ "empty": {
+ "title": "Задач пока нет",
+ "description": "Создайте первую задачу, чтобы начать"
+ },
+ "columns": {
+ "backlog": "Планирование",
+ "queue": "Очередь",
+ "in_progress": "В работе",
+ "ai_review": "AI-ревью",
+ "human_review": "Проверка человеком",
+ "done": "Готово",
+ "pr_created": "PR создан",
+ "error": "Ошибка"
+ },
+ "kanban": {
+ "emptyBacklog": "Нет запланированных задач",
+ "emptyBacklogHint": "Добавьте задачу для начала работы",
+ "emptyQueue": "Очередь пуста",
+ "emptyQueueHint": "Задачи будут ждать здесь при достижении лимита параллельных задач",
+ "emptyInProgress": "Ничего не выполняется",
+ "emptyInProgressHint": "Запустите задачу из планирования",
+ "emptyAiReview": "Нет задач на ревью",
+ "emptyAiReviewHint": "AI проверит завершённые задачи",
+ "emptyHumanReview": "Нечего проверять",
+ "emptyHumanReviewHint": "Задачи ожидают вашего одобрения здесь",
+ "emptyDone": "Нет выполненных задач",
+ "emptyDoneHint": "Одобренные задачи появятся здесь",
+ "emptyDefault": "Нет задач",
+ "dropHere": "Перетащите сюда",
+ "showArchived": "Показать архивные",
+ "addTaskAriaLabel": "Добавить новую задачу в бэклог",
+ "queueAllAriaLabel": "Переместить все задачи в очередь",
+ "closeTaskDetailsAriaLabel": "Закрыть детали задачи",
+ "editTask": "Редактировать задачу",
+ "cannotEditWhileRunning": "Нельзя редактировать во время выполнения задачи",
+ "worktreeCleanupTitle": "Очистка воркдерева",
+ "worktreeCleanupStaged": "Эта задача была подготовлена и имеет воркдерево. Хотите очистить воркдерево?",
+ "worktreeCleanupNotStaged": "У этой задачи есть воркдерево с незлитыми изменениями. Удалите воркдерево для отметки как выполнено или отмените для проверки изменений.",
+ "keepWorktree": "Сохранить воркдерево",
+ "deleteWorktree": "Удалить воркдерево и отметить как выполнено",
+ "refreshTasks": "Обновить задачи",
+ "queueSettings": "Настройки очереди",
+ "orderSaveFailedTitle": "Порядок не сохранён",
+ "orderSaveFailedDescription": "Изменение порядка задач применено, но не удалось сохранить в хранилище. После обновления страницы изменения будут утеряны.",
+ "selectAll": "Выбрать все",
+ "deselectAll": "Снять выделение со всех",
+ "selectedCount": "{{count}} выбрано",
+ "selectedCountOne": "{{count}} задача выбрана",
+ "selectedCountOther": "{{count}} задачи выбрано",
+ "createPRs": "Создать PR-ы",
+ "deleteSelected": "Удалить",
+ "deleteConfirmTitle": "Удалить выбранные задачи",
+ "deleteConfirmDescription": "Вы уверены, что хотите навсегда удалить эти задачи?",
+ "deleteWarning": "Это действие необратимо. Все файлы задач, включая спецификацию, план реализации и любой сгенерированный код, будут навсегда удалены из проекта.",
+ "tasksToDelete": "Задачи для удаления",
+ "deleteConfirmButton": "Удалить {{count}} задачи",
+ "deleteSuccess": "Успешно удалено задач: {{count}}",
+ "deleteError": "Не удалось удалить некоторые задачи",
+ "clearSelection": "Снять выделение",
+ "collapseColumn": "Свернуть колонку",
+ "expandColumn": "Развернуть колонку",
+ "resizeColumn": "Изменить размер колонки",
+ "lockColumn": "Зафиксировать ширину колонки",
+ "unlockColumn": "Разблокировать ширину колонки",
+ "columnLocked": "Ширина колонки зафиксирована",
+ "expandAll": "Развернуть все колонки"
+ },
+ "queue": {
+ "limitReached": "Достигнут лимит параллельных задач ({{current}}/{{max}}). Задача перемещена в очередь.",
+ "movedToQueue": "Задача перемещена в очередь.",
+ "autoPromoted": "Задача автоматически перемещена из очереди в «В работе».",
+ "capacityAvailable": "Доступно {{count}} место(а) в «В работе».",
+ "queueAll": "Добавить все в очередь",
+ "queueAllSuccess": "Перемещено задач в очередь: {{count}}.",
+ "settings": {
+ "title": "Настройки очереди",
+ "description": "Настройте максимальное количество задач, которые могут выполняться параллельно на доске «В работе»",
+ "maxParallelLabel": "Макс. параллельных задач",
+ "minValueError": "Должно быть не менее 1",
+ "maxValueError": "Не может превышать 10",
+ "hint": "При достижении этого лимита новые задачи будут ожидать в очереди перед переходом в «В работе»",
+ "saved": "Настройки очереди сохранены",
+ "saveFailed": "Не удалось сохранить настройки очереди",
+ "retry": "Пожалуйста, попробуйте снова"
+ }
+ },
+ "execution": {
+ "phases": {
+ "idle": "Простой",
+ "planning": "Планирование",
+ "coding": "Разработка",
+ "rate_limit_paused": "Ограничение запросов",
+ "auth_failure_paused": "Требуется авторизация",
+ "reviewing": "Ревью",
+ "fixing": "Исправление",
+ "complete": "Завершено",
+ "failed": "Ошибка"
+ },
+ "labels": {
+ "interrupted": "Прервано",
+ "progress": "Прогресс",
+ "entry": "запись",
+ "entries": "записей"
+ },
+ "shortPhases": {
+ "plan": "План",
+ "code": "Код",
+ "qa": "QA"
+ }
+ },
+ "files": {
+ "title": "Файлы",
+ "tab": "Файлы",
+ "noSpecPath": "Файлы спецификации недоступны",
+ "noFiles": "Файлы не найдены",
+ "loading": "Загрузка файлов...",
+ "loadingContent": "Загрузка содержимого...",
+ "errorLoading": "Не удалось загрузить файлы",
+ "errorLoadingContent": "Не удалось загрузить содержимое файла",
+ "retry": "Повторить",
+ "selectFile": "Выберите файл для просмотра его содержимого",
+ "openInIDE": "Открыть в IDE"
+ },
+ "metadata": {
+ "fastMode": "Быстрый",
+ "severity": "серьёзность",
+ "pullRequest": "Pull Request",
+ "showMore": "Показать больше",
+ "showLess": "Показать меньше"
+ },
+ "images": {
+ "removeImageAriaLabel": "Удалить изображение {{filename}}",
+ "pasteHint": "Совет: вставляйте скриншоты напрямую с помощью {{shortcut}} для добавления референсных изображений."
+ },
+ "imagePreview": {
+ "close": "Закрыть предпросмотр",
+ "unavailable": "Изображение недоступно",
+ "description": "Предпросмотр {{filename}}",
+ "doubleClickHint": "Двойной клик для увеличения",
+ "lowResolution": "Предпросмотр низкого разрешения"
+ },
+ "notifications": {
+ "backgroundTaskTitle": "Задача продолжается в фоне",
+ "backgroundTaskDescription": "Задача всё ещё выполняется. Вы можете повторно открыть этот диалог для отслеживания прогресса."
+ },
+ "wizard": {
+ "createTitle": "Создать новую задачу",
+ "createDescription": "Опишите, что вы хотите создать. AI проанализирует ваш запрос и создаст подробную спецификацию.",
+ "descriptionPlaceholder": "Опишите функцию, исправление бага или улучшение, которое вы хотите реализовать. Будьте максимально конкретны относительно требований, ограничений и ожидаемого поведения. Введите @ для ссылки на файлы.",
+ "draftRestored": "Черновик восстановлен",
+ "startFresh": "Начать заново",
+ "hideFiles": "Скрыть файлы",
+ "browseFiles": "Обзор файлов",
+ "creating": "Создание...",
+ "createTask": "Создать задачу",
+ "worktreeNotice": {
+ "title": "Изолированное рабочее пространство",
+ "description": "Эта задача выполняется в изолированном git-воркдереве. Ваша основная ветка остаётся в безопасности до тех пор, пока вы не решите выполнить слияние."
+ },
+ "gitOptions": {
+ "title": "Git-опции (необязательно)",
+ "baseBranchLabel": "Базовая ветка (необязательно)",
+ "useProjectDefault": "Использовать проектную по умолчанию",
+ "useProjectDefaultWithBranch": "Использовать проектную по умолчанию ({{branch}})",
+ "searchBranches": "Поиск веток...",
+ "noBranchesFound": "Ветки не найдены",
+ "helpText": "Переопределите ветку, из которой будет создано воркдерево этой задачи. Оставьте пустым для использования настроенной ветки по умолчанию проекта.",
+ "pushNewBranchesLabel": "Автоматически отправлять новую ветку",
+ "pushNewBranchesDescription": "Опубликовать ветку этой задачи на GitHub и автоматически настроить отслеживание. Отключите, чтобы оставить только локально.",
+ "useWorktreeLabel": "Использовать изолированное рабочее пространство (рекомендуется)",
+ "useWorktreeDescription": "Создаёт изменения в отдельном git-воркдереве для безопасной проверки перед слиянием. Отключите для разработки напрямую в вашем проекте (быстрее, но рискованнее)."
+ },
+ "errors": {
+ "createFailed": "Не удалось создать задачу. Пожалуйста, попробуйте снова.",
+ "startFailed": "Не удалось запустить задачу"
+ }
+ },
+ "feedback": {
+ "dragDropHint": "Перетащите изображения или вставьте скриншоты",
+ "imageAdded": "Изображение успешно добавлено",
+ "maxImagesError": "Максимально допустимо {{count}} изображений",
+ "invalidTypeError": "Недопустимый тип изображения. Допустимые: {{types}}",
+ "removeImage": "Удалить изображение",
+ "processingError": "Не удалось обработать изображение"
+ },
+ "review": {
+ "mergeTooltip": "Сливает изменения из ветки воркдерева задачи обратно в базовую ветку. AI разрешит возможные конфликты. Затем вы можете выбрать, сохранить или удалить воркдерево."
+ },
+ "edit": {
+ "title": "Редактировать задачу",
+ "description": "Обновите детали задачи, включая заголовок, описание, классификацию, изображения и настройки. Изменения будут сохранены в файлах спецификации.",
+ "saveChanges": "Сохранить изменения",
+ "errors": {
+ "updateFailed": "Не удалось обновить задачу. Пожалуйста, попробуйте снова."
+ }
+ },
+ "form": {
+ "description": "Описание",
+ "descriptionPlaceholder": "Опишите функцию, исправление бага или улучшение, которое вы хотите реализовать. Будьте максимально конкретны относительно требований, ограничений и ожидаемого поведения.",
+ "imageAddedSuccess": "Изображение успешно добавлено!",
+ "taskTitle": "Заголовок задачи",
+ "titlePlaceholder": "Оставьте пустым для автогенерации из описания",
+ "titleHelpText": "Краткий описательный заголовок будет сгенерирован автоматически, если поле оставлено пустым.",
+ "classificationOptional": "Классификация (необязательно)",
+ "requireReviewLabel": "Требовать проверки человеком перед разработкой",
+ "requireReviewDescription": "При включении вам будет предложено проверить спецификацию и план реализации перед началом фазы разработки. Это позволяет одобрить, запросить изменения или оставить отзыв.",
+ "fastModeLabel": "Быстрый режим",
+ "fastModeDescription": "Та же модель Opus 4.6 с более быстрым выводом. Более высокая стоимость токена.",
+ "fastModeNotice": "Требует включения «дополнительного использования» в вашей подписке Claude.",
+ "errors": {
+ "descriptionRequired": "Пожалуйста, предоставьте описание",
+ "maxImagesReached": "Максимально допустимо 5 изображений",
+ "invalidImageType": "Недопустимый тип изображения. Допустимые: PNG, JPEG, GIF, WebP",
+ "processPasteFailed": "Не удалось обработать вставленное изображение",
+ "processDropFailed": "Не удалось обработать перетащенное изображение"
+ },
+ "classification": {
+ "category": "Категория",
+ "selectCategory": "Выберите категорию",
+ "priority": "Приоритет",
+ "selectPriority": "Выберите приоритет",
+ "complexity": "Сложность",
+ "selectComplexity": "Выберите сложность",
+ "impact": "Влияние",
+ "selectImpact": "Выберите влияние",
+ "helpText": "Эти метки помогают организовывать и приоритизировать задачи. Они необязательны, но полезны для фильтрации.",
+ "values": {
+ "category": {
+ "feature": "Функция",
+ "bug_fix": "Исправление бага",
+ "refactoring": "Рефакторинг",
+ "documentation": "Документация",
+ "security": "Безопасность"
+ },
+ "priority": {
+ "low": "Низкий",
+ "medium": "Средний",
+ "high": "Высокий",
+ "urgent": "Срочный"
+ },
+ "complexity": {
+ "trivial": "Тривиальная",
+ "small": "Маленькая",
+ "medium": "Средняя",
+ "large": "Большая",
+ "complex": "Сложная"
+ },
+ "impact": {
+ "low": "Низкое влияние",
+ "medium": "Среднее влияние",
+ "high": "Высокое влияние",
+ "critical": "Критическое влияние"
+ }
+ }
+ }
+ },
+ "subtasks": {
+ "untitled": "Безымянная подзадача",
+ "expandAll": "Развернуть все",
+ "collapseAll": "Свернуть все"
+ },
+ "bulkPR": {
+ "selectAllInColumn": "Выбрать все задачи в колонке",
+ "deselectAllInColumn": "Снять выделение со всех задач",
+ "selectionMode": "Режим выбора активен",
+ "exitSelectionMode": "Выйти из режима выбора",
+ "noTasksToSelect": "Нет доступных задач для выбора",
+ "confirmBulkAction": "Подтвердить массовое действие для {{count}} задач",
+ "processingTasks": "Обработка выбранных задач..."
+ },
+ "screenshot": {
+ "title": "Сделать скриншот",
+ "description": "Выберите экран или окно для захвата в качестве референсного изображения",
+ "capture": "Захватить",
+ "capturing": "Захват...",
+ "noSources": "Экраны или окна не найдены",
+ "errors": {
+ "getSources": "Не удалось получить источники скриншотов",
+ "fetchSources": "Не удалось загрузить источники скриншотов",
+ "capture": "Не удалось сделать скриншот",
+ "captureFailed": "Не удалось сделать скриншот"
+ },
+ "devMode": {
+ "title": "Захват скриншота недоступен",
+ "description": "Захват экрана недоступен в режиме разработки из-за ограничений системных разрешений.",
+ "hint": "Используйте внешний инструмент для скриншотов и вставьте напрямую в описание задачи с помощью {{shortcut}}."
+ }
+ },
+ "deleteDialog": {
+ "title": "Удалить задачу",
+ "confirmMessage": "Вы уверены, что хотите удалить",
+ "destructiveWarning": "Это действие необратимо. Все файлы задачи, включая спецификацию, план реализации и любой сгенерированный код, будут навсегда удалены из проекта.",
+ "checkingChanges": "Проверка незафиксированных изменений...",
+ "uncommittedChanges": "Воркдерево этой задачи содержит {{count}} незафиксированный файл(а)",
+ "uncommittedChangesHint": "Эти изменения не были зафиксированы или слиты. Удаление задачи навсегда уничтожит все незафиксированные изменения в воркдереве.",
+ "cancel": "Отмена",
+ "deletePermanently": "Удалить навсегда",
+ "deleting": "Удаление..."
+ },
+ "referenceImages": {
+ "title": "Референсные изображения (необязательно)",
+ "description": "Добавьте визуальные референсы, такие как скриншоты или дизайны, чтобы помочь AI понять ваши требования."
+ }
+}
diff --git a/apps/desktop/src/shared/i18n/locales/ru/terminal.json b/apps/desktop/src/shared/i18n/locales/ru/terminal.json
new file mode 100644
index 0000000000..f2cfa25e2b
--- /dev/null
+++ b/apps/desktop/src/shared/i18n/locales/ru/terminal.json
@@ -0,0 +1,58 @@
+{
+ "expand": {
+ "expand": "Развернуть терминал",
+ "collapse": "Свернуть терминал"
+ },
+ "resume": {
+ "pending": "Доступно возобновление",
+ "pendingTooltip": "Нажмите, чтобы возобновить предыдущую сессию Claude",
+ "resumeAllSessions": "Возобновить все"
+ },
+ "auth": {
+ "terminalTitle": "Авторизация: {{profileName}}",
+ "maxTerminalsReached": "Невозможно открыть терминал авторизации: достигнуто максимальное количество терминалов. Сначала закройте один из них."
+ },
+ "swap": {
+ "inProgress": "Переключение профиля...",
+ "resumingSession": "Возобновление сессии Claude...",
+ "sessionResumed": "Сессия возобновлена с новым профилем",
+ "resumeFailed": "Не удалось возобновить сессию. Вы можете начать новую.",
+ "noSession": "Профиль переключён. Нет активной сессии для возобновления.",
+ "migrationFailed": "Профиль переключён, но миграция сессии не удалась. Запускается новый терминал."
+ },
+ "worktree": {
+ "create": "Воркtree",
+ "createNew": "Новый воркtree",
+ "existing": "Воркtree-ветки терминала",
+ "taskWorktrees": "Воркtree-ветки задач",
+ "otherWorktrees": "Прочие",
+ "createTitle": "Создать воркtree терминала",
+ "createDescription": "Создайте изолированное рабочее пространство для этого терминала. Вся работа будет выполняться в директории воркtree.",
+ "name": "Название воркtree",
+ "namePlaceholder": "my-feature",
+ "nameRequired": "Название воркtree обязательно",
+ "nameInvalid": "Название должно начинаться и заканчиваться буквой или цифрой",
+ "nameHelp": "Строчные буквы, цифры, дефисы и подчёркивания (пробелы заменяются дефисами)",
+ "associateTask": "Привязать к задаче",
+ "selectTask": "Выберите задачу...",
+ "noTask": "Без задачи (отдельный воркtree)",
+ "createBranch": "Создать ветку Git",
+ "branchHelp": "Будет создана ветка: {{branch}}",
+ "baseBranch": "Базовая ветка",
+ "selectBaseBranch": "Выберите базовую ветку...",
+ "searchBranch": "Поиск веток...",
+ "noBranchFound": "Ветки не найдены",
+ "useProjectDefault": "Использовать по умолчанию ({{branch}})",
+ "baseBranchHelp": "Ветка, из которой будет создан воркtree",
+ "openInIDE": "Открыть в IDE",
+ "maxReached": "Достигнут максимум из 12 воркtree-веток терминала",
+ "alreadyExists": "Воркtree с таким именем уже существует",
+ "searchPlaceholder": "Поиск воркtree...",
+ "noResults": "Воркtree не найдены",
+ "deleteTitle": "Удалить воркtree?",
+ "deleteDescription": "Это безвозвратно удалит воркtree и его ветку. Все незафиксированные изменения будут потеряны.",
+ "detached": "(отсоединён)",
+ "remotePushFailed": "Отслеживание удалённой ветки не настроено",
+ "remotePushFailedDescription": "Воркtree создан, но ветку не удалось отправить на удалённый сервер. Возможно, потребуется вручную выполнить git push -u."
+ }
+}
diff --git a/apps/desktop/src/shared/i18n/locales/ru/welcome.json b/apps/desktop/src/shared/i18n/locales/ru/welcome.json
new file mode 100644
index 0000000000..d5e5008669
--- /dev/null
+++ b/apps/desktop/src/shared/i18n/locales/ru/welcome.json
@@ -0,0 +1,17 @@
+{
+ "hero": {
+ "title": "Добро пожаловать в Aperant",
+ "subtitle": "Создавайте программное обеспечение автономно с помощью AI-агентов"
+ },
+ "actions": {
+ "newProject": "Новый проект",
+ "openProject": "Открыть проект"
+ },
+ "recentProjects": {
+ "title": "Последние проекты",
+ "empty": "Проектов пока нет",
+ "emptyDescription": "Создайте новый проект или откройте существующий, чтобы начать",
+ "openFolder": "Открыть папку",
+ "openProjectAriaLabel": "Открыть проект {{name}}"
+ }
+}