summaryrefslogtreecommitdiffhomepage
path: root/packages/app
diff options
context:
space:
mode:
authorAlex Yaroshuk <[email protected]>2026-01-22 05:30:12 +0800
committerGitHub <[email protected]>2026-01-21 15:30:12 -0600
commit383c2787f95463e74aefb78e526068249bc2db24 (patch)
treeb686aed6eea0e218cdfcdf6196dba9f26bfada66 /packages/app
parentc89f6e7ac61e0dd5404888df87555627efce6087 (diff)
downloadopencode-383c2787f95463e74aefb78e526068249bc2db24.tar.gz
opencode-383c2787f95463e74aefb78e526068249bc2db24.zip
feat(i18n): add Russian language support (#9882)
Diffstat (limited to 'packages/app')
-rw-r--r--packages/app/src/context/language.tsx12
-rw-r--r--packages/app/src/i18n/da.ts1
-rw-r--r--packages/app/src/i18n/de.ts1
-rw-r--r--packages/app/src/i18n/en.ts1
-rw-r--r--packages/app/src/i18n/es.ts1
-rw-r--r--packages/app/src/i18n/fr.ts1
-rw-r--r--packages/app/src/i18n/ja.ts1
-rw-r--r--packages/app/src/i18n/ko.ts1
-rw-r--r--packages/app/src/i18n/ru.ts642
-rw-r--r--packages/app/src/i18n/zh.ts1
10 files changed, 659 insertions, 3 deletions
diff --git a/packages/app/src/context/language.tsx b/packages/app/src/context/language.tsx
index 7275fb36f..5fb03afe2 100644
--- a/packages/app/src/context/language.tsx
+++ b/packages/app/src/context/language.tsx
@@ -11,6 +11,8 @@ import { dict as es } from "@/i18n/es"
import { dict as fr } from "@/i18n/fr"
import { dict as da } from "@/i18n/da"
import { dict as ja } from "@/i18n/ja"
+import { dict as pl } from "@/i18n/pl"
+import { dict as ru } from "@/i18n/ru"
import { dict as uiEn } from "@opencode-ai/ui/i18n/en"
import { dict as uiZh } from "@opencode-ai/ui/i18n/zh"
import { dict as uiKo } from "@opencode-ai/ui/i18n/ko"
@@ -19,15 +21,15 @@ import { dict as uiEs } from "@opencode-ai/ui/i18n/es"
import { dict as uiFr } from "@opencode-ai/ui/i18n/fr"
import { dict as uiDa } from "@opencode-ai/ui/i18n/da"
import { dict as uiJa } from "@opencode-ai/ui/i18n/ja"
-import { dict as pl } from "@/i18n/pl"
import { dict as uiPl } from "@opencode-ai/ui/i18n/pl"
+import { dict as uiRu } from "@opencode-ai/ui/i18n/ru"
-export type Locale = "en" | "zh" | "ko" | "de" | "es" | "fr" | "da" | "ja" | "pl"
+export type Locale = "en" | "zh" | "ko" | "de" | "es" | "fr" | "da" | "ja" | "pl" | "ru"
type RawDictionary = typeof en & typeof uiEn
type Dictionary = i18n.Flatten<RawDictionary>
-const LOCALES: readonly Locale[] = ["en", "zh", "ko", "de", "es", "fr", "da", "ja", "pl"]
+const LOCALES: readonly Locale[] = ["en", "zh", "ko", "de", "es", "fr", "da", "ja", "pl", "ru"]
function detectLocale(): Locale {
if (typeof navigator !== "object") return "en"
@@ -43,6 +45,7 @@ function detectLocale(): Locale {
if (language.toLowerCase().startsWith("da")) return "da"
if (language.toLowerCase().startsWith("ja")) return "ja"
if (language.toLowerCase().startsWith("pl")) return "pl"
+ if (language.toLowerCase().startsWith("ru")) return "ru"
}
return "en"
@@ -67,6 +70,7 @@ export const { use: useLanguage, provider: LanguageProvider } = createSimpleCont
if (store.locale === "da") return "da"
if (store.locale === "ja") return "ja"
if (store.locale === "pl") return "pl"
+ if (store.locale === "ru") return "ru"
return "en"
})
@@ -86,6 +90,7 @@ export const { use: useLanguage, provider: LanguageProvider } = createSimpleCont
if (locale() === "da") return { ...base, ...i18n.flatten({ ...da, ...uiDa }) }
if (locale() === "ja") return { ...base, ...i18n.flatten({ ...ja, ...uiJa }) }
if (locale() === "pl") return { ...base, ...i18n.flatten({ ...pl, ...uiPl }) }
+ if (locale() === "ru") return { ...base, ...i18n.flatten({ ...ru, ...uiRu }) }
return { ...base, ...i18n.flatten({ ...ko, ...uiKo }) }
})
@@ -101,6 +106,7 @@ export const { use: useLanguage, provider: LanguageProvider } = createSimpleCont
da: "language.da",
ja: "language.ja",
pl: "language.pl",
+ ru: "language.ru",
}
const label = (value: Locale) => t(labelKey[value])
diff --git a/packages/app/src/i18n/da.ts b/packages/app/src/i18n/da.ts
index c7149ec75..3ec4a5f6f 100644
--- a/packages/app/src/i18n/da.ts
+++ b/packages/app/src/i18n/da.ts
@@ -276,6 +276,7 @@ export const dict = {
"language.fr": "Fransk",
"language.ja": "Japansk",
"language.da": "Dansk",
+ "language.ru": "Russisk",
"language.pl": "Polsk",
"toast.language.title": "Sprog",
diff --git a/packages/app/src/i18n/de.ts b/packages/app/src/i18n/de.ts
index 941390a04..85bb436e5 100644
--- a/packages/app/src/i18n/de.ts
+++ b/packages/app/src/i18n/de.ts
@@ -281,6 +281,7 @@ export const dict = {
"language.fr": "Französisch",
"language.ja": "Japanisch",
"language.da": "Dänisch",
+ "language.ru": "Russisch",
"language.pl": "Polnisch",
"toast.language.title": "Sprache",
diff --git a/packages/app/src/i18n/en.ts b/packages/app/src/i18n/en.ts
index 2eb69d040..ec7d8da2f 100644
--- a/packages/app/src/i18n/en.ts
+++ b/packages/app/src/i18n/en.ts
@@ -293,6 +293,7 @@ export const dict = {
"language.fr": "French",
"language.ja": "Japanese",
"language.da": "Danish",
+ "language.ru": "Russian",
"language.pl": "Polish",
"toast.language.title": "Language",
diff --git a/packages/app/src/i18n/es.ts b/packages/app/src/i18n/es.ts
index 21bd296eb..d19a22f5c 100644
--- a/packages/app/src/i18n/es.ts
+++ b/packages/app/src/i18n/es.ts
@@ -276,6 +276,7 @@ export const dict = {
"language.fr": "Francés",
"language.ja": "Japonés",
"language.da": "Danés",
+ "language.ru": "Ruso",
"language.pl": "Polaco",
"toast.language.title": "Idioma",
diff --git a/packages/app/src/i18n/fr.ts b/packages/app/src/i18n/fr.ts
index b2f78cd8e..831a23c07 100644
--- a/packages/app/src/i18n/fr.ts
+++ b/packages/app/src/i18n/fr.ts
@@ -276,6 +276,7 @@ export const dict = {
"language.fr": "Français",
"language.ja": "Japonais",
"language.da": "Danois",
+ "language.ru": "Russe",
"language.pl": "Polonais",
"toast.language.title": "Langue",
diff --git a/packages/app/src/i18n/ja.ts b/packages/app/src/i18n/ja.ts
index 1d87037ae..7237659f2 100644
--- a/packages/app/src/i18n/ja.ts
+++ b/packages/app/src/i18n/ja.ts
@@ -274,6 +274,7 @@ export const dict = {
"language.fr": "フランス語",
"language.ja": "日本語",
"language.da": "デンマーク語",
+ "language.ru": "ロシア語",
"language.pl": "ポーランド語",
"toast.language.title": "言語",
diff --git a/packages/app/src/i18n/ko.ts b/packages/app/src/i18n/ko.ts
index 64fa629c9..4ddeb9aea 100644
--- a/packages/app/src/i18n/ko.ts
+++ b/packages/app/src/i18n/ko.ts
@@ -278,6 +278,7 @@ export const dict = {
"language.fr": "프랑스어",
"language.ja": "일본어",
"language.da": "덴마크어",
+ "language.ru": "러시아어",
"language.pl": "폴란드어",
"toast.language.title": "언어",
diff --git a/packages/app/src/i18n/ru.ts b/packages/app/src/i18n/ru.ts
new file mode 100644
index 000000000..f0d014dec
--- /dev/null
+++ b/packages/app/src/i18n/ru.ts
@@ -0,0 +1,642 @@
+export const dict = {
+ "command.category.suggested": "Предложено",
+ "command.category.view": "Просмотр",
+ "command.category.project": "Проект",
+ "command.category.provider": "Провайдер",
+ "command.category.server": "Сервер",
+ "command.category.session": "Сессия",
+ "command.category.theme": "Тема",
+ "command.category.language": "Язык",
+ "command.category.file": "Файл",
+ "command.category.terminal": "Терминал",
+ "command.category.model": "Модель",
+ "command.category.mcp": "MCP",
+ "command.category.agent": "Агент",
+ "command.category.permissions": "Разрешения",
+ "command.category.workspace": "Рабочее пространство",
+ "command.category.settings": "Настройки",
+
+ "theme.scheme.system": "Системная",
+ "theme.scheme.light": "Светлая",
+ "theme.scheme.dark": "Тёмная",
+
+ "command.sidebar.toggle": "Переключить боковую панель",
+ "command.project.open": "Открыть проект",
+ "command.provider.connect": "Подключить провайдера",
+ "command.server.switch": "Переключить сервер",
+ "command.settings.open": "Открыть настройки",
+ "command.session.previous": "Предыдущая сессия",
+ "command.session.next": "Следующая сессия",
+ "command.session.archive": "Архивировать сессию",
+
+ "command.palette": "Палитра команд",
+
+ "command.theme.cycle": "Цикл тем",
+ "command.theme.set": "Использовать тему: {{theme}}",
+ "command.theme.scheme.cycle": "Цикл цветовой схемы",
+ "command.theme.scheme.set": "Использовать цветовую схему: {{scheme}}",
+
+ "command.language.cycle": "Цикл языков",
+ "command.language.set": "Использовать язык: {{language}}",
+
+ "command.session.new": "Новая сессия",
+ "command.file.open": "Открыть файл",
+ "command.file.open.description": "Поиск файлов и команд",
+ "command.terminal.toggle": "Переключить терминал",
+ "command.review.toggle": "Переключить обзор",
+ "command.terminal.new": "Новый терминал",
+ "command.terminal.new.description": "Создать новую вкладку терминала",
+ "command.steps.toggle": "Переключить шаги",
+ "command.steps.toggle.description": "Показать или скрыть шаги для текущего сообщения",
+ "command.message.previous": "Предыдущее сообщение",
+ "command.message.previous.description": "Перейти к предыдущему сообщению пользователя",
+ "command.message.next": "Следующее сообщение",
+ "command.message.next.description": "Перейти к следующему сообщению пользователя",
+ "command.model.choose": "Выбрать модель",
+ "command.model.choose.description": "Выбрать другую модель",
+ "command.mcp.toggle": "Переключить MCP",
+ "command.mcp.toggle.description": "Переключить MCP",
+ "command.agent.cycle": "Цикл агентов",
+ "command.agent.cycle.description": "Переключиться к следующему агенту",
+ "command.agent.cycle.reverse": "Цикл агентов назад",
+ "command.agent.cycle.reverse.description": "Переключиться к предыдущему агенту",
+ "command.model.variant.cycle": "Цикл режимов мышления",
+ "command.model.variant.cycle.description": "Переключиться к следующему уровню усилий",
+ "command.permissions.autoaccept.enable": "Авто-принятие изменений",
+ "command.permissions.autoaccept.disable": "Прекратить авто-принятие изменений",
+ "command.session.undo": "Отменить",
+ "command.session.undo.description": "Отменить последнее сообщение",
+ "command.session.redo": "Повторить",
+ "command.session.redo.description": "Повторить отменённое сообщение",
+ "command.session.compact": "Сжать сессию",
+ "command.session.compact.description": "Сократить сессию для уменьшения размера контекста",
+ "command.session.fork": "Создать ответвление",
+ "command.session.fork.description": "Создать новую сессию из сообщения",
+ "command.session.share": "Поделиться сессией",
+ "command.session.share.description": "Поделиться сессией и скопировать URL в буфер обмена",
+ "command.session.unshare": "Отменить публикацию",
+ "command.session.unshare.description": "Прекратить публикацию сессии",
+
+ "palette.search.placeholder": "Поиск файлов и команд",
+ "palette.empty": "Ничего не найдено",
+ "palette.group.commands": "Команды",
+ "palette.group.files": "Файлы",
+
+ "dialog.provider.search.placeholder": "Поиск провайдеров",
+ "dialog.provider.empty": "Провайдеры не найдены",
+ "dialog.provider.group.popular": "Популярные",
+ "dialog.provider.group.other": "Другие",
+ "dialog.provider.tag.recommended": "Рекомендуемые",
+ "dialog.provider.anthropic.note": "Подключитесь с помощью Claude Pro/Max или API ключа",
+
+ "dialog.model.select.title": "Выбрать модель",
+ "dialog.model.search.placeholder": "Поиск моделей",
+ "dialog.model.empty": "Модели не найдены",
+ "dialog.model.manage": "Управление моделями",
+ "dialog.model.manage.description": "Настройте какие модели появляются в выборе модели",
+
+ "dialog.model.unpaid.freeModels.title": "Бесплатные модели от OpenCode",
+ "dialog.model.unpaid.addMore.title": "Добавьте больше моделей от популярных провайдеров",
+
+ "dialog.provider.viewAll": "Посмотреть всех провайдеров",
+
+ "provider.connect.title": "Подключить {{provider}}",
+ "provider.connect.title.anthropicProMax": "Войти с помощью Claude Pro/Max",
+ "provider.connect.selectMethod": "Выберите способ входа для {{provider}}.",
+ "provider.connect.method.apiKey": "API ключ",
+ "provider.connect.status.inProgress": "Авторизация...",
+ "provider.connect.status.waiting": "Ожидание авторизации...",
+ "provider.connect.status.failed": "Ошибка авторизации: {{error}}",
+ "provider.connect.apiKey.description":
+ "Введите ваш API ключ {{provider}} для подключения аккаунта и использования моделей {{provider}} в OpenCode.",
+ "provider.connect.apiKey.label": "{{provider}} API ключ",
+ "provider.connect.apiKey.placeholder": "API ключ",
+ "provider.connect.apiKey.required": "API ключ обязателен",
+ "provider.connect.opencodeZen.line1":
+ "OpenCode Zen даёт вам доступ к отобранным надёжным оптимизированным моделям для агентов программирования.",
+ "provider.connect.opencodeZen.line2":
+ "С одним API ключом вы получите доступ к таким моделям как Claude, GPT, Gemini, GLM и другим.",
+ "provider.connect.opencodeZen.visit.prefix": "Посетите ",
+ "provider.connect.opencodeZen.visit.link": "opencode.ai/zen",
+ "provider.connect.opencodeZen.visit.suffix": " чтобы получить ваш API ключ.",
+ "provider.connect.oauth.code.visit.prefix": "Посетите ",
+ "provider.connect.oauth.code.visit.link": "эту ссылку",
+ "provider.connect.oauth.code.visit.suffix":
+ " чтобы получить код авторизации для подключения аккаунта и использования моделей {{provider}} в OpenCode.",
+ "provider.connect.oauth.code.label": "{{method}} код авторизации",
+ "provider.connect.oauth.code.placeholder": "Код авторизации",
+ "provider.connect.oauth.code.required": "Код авторизации обязателен",
+ "provider.connect.oauth.code.invalid": "Неверный код авторизации",
+ "provider.connect.oauth.auto.visit.prefix": "Посетите ",
+ "provider.connect.oauth.auto.visit.link": "эту ссылку",
+ "provider.connect.oauth.auto.visit.suffix":
+ " и введите код ниже для подключения аккаунта и использования моделей {{provider}} в OpenCode.",
+ "provider.connect.oauth.auto.confirmationCode": "Код подтверждения",
+ "provider.connect.toast.connected.title": "{{provider}} подключён",
+ "provider.connect.toast.connected.description": "Модели {{provider}} теперь доступны.",
+
+ "model.tag.free": "Бесплатно",
+ "model.tag.latest": "Последняя",
+ "model.provider.anthropic": "Anthropic",
+ "model.provider.openai": "OpenAI",
+ "model.provider.google": "Google",
+ "model.provider.xai": "xAI",
+ "model.provider.meta": "Meta",
+ "model.input.text": "текст",
+ "model.input.image": "изображение",
+ "model.input.audio": "аудио",
+ "model.input.video": "видео",
+ "model.input.pdf": "pdf",
+ "model.tooltip.allows": "Разрешено: {{inputs}}",
+ "model.tooltip.reasoning.allowed": "Разрешает рассуждение",
+ "model.tooltip.reasoning.none": "Без рассуждения",
+ "model.tooltip.context": "Лимит контекста {{limit}}",
+
+ "common.search.placeholder": "Поиск",
+ "common.loading": "Загрузка",
+ "common.loading.ellipsis": "...",
+ "common.cancel": "Отмена",
+ "common.submit": "Отправить",
+ "common.save": "Сохранить",
+ "common.saving": "Сохранение...",
+ "common.default": "По умолчанию",
+ "common.attachment": "вложение",
+
+ "prompt.placeholder.shell": "Введите команду оболочки...",
+ "prompt.placeholder.normal": 'Спросите что угодно... "{{example}}"',
+ "prompt.mode.shell": "Оболочка",
+ "prompt.mode.shell.exit": "esc для выхода",
+
+ "prompt.example.1": "Исправить TODO в коде",
+ "prompt.example.2": "Какой технологический стек этого проекта?",
+ "prompt.example.3": "Исправить сломанные тесты",
+ "prompt.example.4": "Объясни как работает аутентификация",
+ "prompt.example.5": "Найти и исправить уязвимости безопасности",
+ "prompt.example.6": "Добавить юнит-тесты для сервиса пользователя",
+ "prompt.example.7": "Рефакторить эту функцию для лучшей читаемости",
+ "prompt.example.8": "Что означает эта ошибка?",
+ "prompt.example.9": "Помоги мне отладить эту проблему",
+ "prompt.example.10": "Сгенерировать документацию API",
+ "prompt.example.11": "Оптимизировать запросы к базе данных",
+ "prompt.example.12": "Добавить валидацию ввода",
+ "prompt.example.13": "Создать новый компонент для...",
+ "prompt.example.14": "Как развернуть этот проект?",
+ "prompt.example.15": "Проверь мой код на лучшие практики",
+ "prompt.example.16": "Добавить обработку ошибок в эту функцию",
+ "prompt.example.17": "Объясни этот паттерн regex",
+ "prompt.example.18": "Конвертировать это в TypeScript",
+ "prompt.example.19": "Добавить логирование по всему проекту",
+ "prompt.example.20": "Какие зависимости устарели?",
+ "prompt.example.21": "Помоги написать скрипт миграции",
+ "prompt.example.22": "Реализовать кэширование для этой конечной точки",
+ "prompt.example.23": "Добавить пагинацию в этот список",
+ "prompt.example.24": "Создать CLI команду для...",
+ "prompt.example.25": "Как работают переменные окружения здесь?",
+
+ "prompt.popover.emptyResults": "Нет совпадений",
+ "prompt.popover.emptyCommands": "Нет совпадающих команд",
+ "prompt.dropzone.label": "Перетащите изображения или PDF сюда",
+ "prompt.slash.badge.custom": "своё",
+ "prompt.context.active": "активно",
+ "prompt.context.includeActiveFile": "Включить активный файл",
+ "prompt.action.attachFile": "Прикрепить файл",
+ "prompt.action.send": "Отправить",
+ "prompt.action.stop": "Остановить",
+
+ "prompt.toast.pasteUnsupported.title": "Неподдерживаемая вставка",
+ "prompt.toast.pasteUnsupported.description": "Сюда можно вставлять только изображения или PDF.",
+ "prompt.toast.modelAgentRequired.title": "Выберите агента и модель",
+ "prompt.toast.modelAgentRequired.description": "Выберите агента и модель перед отправкой запроса.",
+ "prompt.toast.worktreeCreateFailed.title": "Не удалось создать worktree",
+ "prompt.toast.sessionCreateFailed.title": "Не удалось создать сессию",
+ "prompt.toast.shellSendFailed.title": "Не удалось отправить команду оболочки",
+ "prompt.toast.commandSendFailed.title": "Не удалось отправить команду",
+ "prompt.toast.promptSendFailed.title": "Не удалось отправить запрос",
+
+ "dialog.mcp.title": "MCP",
+ "dialog.mcp.description": "{{enabled}} из {{total}} включено",
+ "dialog.mcp.empty": "MCP не настроены",
+
+ "mcp.status.connected": "подключено",
+ "mcp.status.failed": "ошибка",
+ "mcp.status.needs_auth": "требуется авторизация",
+ "mcp.status.disabled": "отключено",
+
+ "dialog.fork.empty": "Нет сообщений для ответвления",
+
+ "dialog.directory.search.placeholder": "Поиск папок",
+ "dialog.directory.empty": "Папки не найдены",
+
+ "dialog.server.title": "Серверы",
+ "dialog.server.description": "Переключите сервер OpenCode к которому подключается приложение.",
+ "dialog.server.search.placeholder": "Поиск серверов",
+ "dialog.server.empty": "Серверов пока нет",
+ "dialog.server.add.title": "Добавить сервер",
+ "dialog.server.add.url": "URL сервера",
+ "dialog.server.add.placeholder": "http://localhost:4096",
+ "dialog.server.add.error": "Не удалось подключиться к серверу",
+ "dialog.server.add.checking": "Проверка...",
+ "dialog.server.add.button": "Добавить",
+ "dialog.server.default.title": "Сервер по умолчанию",
+ "dialog.server.default.description":
+ "Подключаться к этому серверу при запуске приложения вместо запуска локального сервера. Требуется перезапуск.",
+ "dialog.server.default.none": "Сервер не выбран",
+ "dialog.server.default.set": "Установить текущий сервер по умолчанию",
+ "dialog.server.default.clear": "Очистить",
+
+ "dialog.project.edit.title": "Редактировать проект",
+ "dialog.project.edit.name": "Название",
+ "dialog.project.edit.icon": "Иконка",
+ "dialog.project.edit.icon.alt": "Иконка проекта",
+ "dialog.project.edit.icon.hint": "Нажмите или перетащите изображение",
+ "dialog.project.edit.icon.recommended": "Рекомендуется: 128x128px",
+ "dialog.project.edit.color": "Цвет",
+
+ "context.breakdown.title": "Разбивка контекста",
+ "context.breakdown.note":
+ 'Приблизительная разбивка входных токенов. "Другое" включает определения инструментов и накладные расходы.',
+ "context.breakdown.system": "Система",
+ "context.breakdown.user": "Пользователь",
+ "context.breakdown.assistant": "Ассистент",
+ "context.breakdown.tool": "Вызовы инструментов",
+ "context.breakdown.other": "Другое",
+
+ "context.systemPrompt.title": "Системный промпт",
+ "context.rawMessages.title": "Исходные сообщения",
+
+ "context.stats.session": "Сессия",
+ "context.stats.messages": "Сообщения",
+ "context.stats.provider": "Провайдер",
+ "context.stats.model": "Модель",
+ "context.stats.limit": "Лимит контекста",
+ "context.stats.totalTokens": "Всего токенов",
+ "context.stats.usage": "Использование",
+ "context.stats.inputTokens": "Входные токены",
+ "context.stats.outputTokens": "Выходные токены",
+ "context.stats.reasoningTokens": "Токены рассуждения",
+ "context.stats.cacheTokens": "Токены кэша (чтение/запись)",
+ "context.stats.userMessages": "Сообщения пользователя",
+ "context.stats.assistantMessages": "Сообщения ассистента",
+ "context.stats.totalCost": "Общая стоимость",
+ "context.stats.sessionCreated": "Сессия создана",
+ "context.stats.lastActivity": "Последняя активность",
+
+ "context.usage.tokens": "Токены",
+ "context.usage.usage": "Использование",
+ "context.usage.cost": "Стоимость",
+ "context.usage.clickToView": "Нажмите для просмотра контекста",
+
+ "language.en": "Английский",
+ "language.zh": "Китайский",
+ "language.ko": "Корейский",
+ "language.de": "Немецкий",
+ "language.es": "Испанский",
+ "language.fr": "Французский",
+ "language.ja": "Японский",
+ "language.da": "Датский",
+ "language.ru": "Русский",
+
+ "toast.language.title": "Язык",
+ "toast.language.description": "Переключено на {{language}}",
+
+ "toast.theme.title": "Тема переключена",
+ "toast.scheme.title": "Цветовая схема",
+
+ "toast.permissions.autoaccept.on.title": "Авто-принятие изменений",
+ "toast.permissions.autoaccept.on.description": "Разрешения на редактирование и запись будут автоматически одобрены",
+ "toast.permissions.autoaccept.off.title": "Авто-принятие остановлено",
+ "toast.permissions.autoaccept.off.description": "Редактирование и запись потребуют подтверждения",
+
+ "toast.model.none.title": "Модель не выбрана",
+ "toast.model.none.description": "Подключите провайдера для суммаризации сессии",
+
+ "toast.file.loadFailed.title": "Не удалось загрузить файл",
+
+ "toast.session.share.copyFailed.title": "Не удалось скопировать URL в буфер обмена",
+ "toast.session.share.success.title": "Сессия опубликована",
+ "toast.session.share.success.description": "URL скопирован в буфер обмена!",
+ "toast.session.share.failed.title": "Не удалось опубликовать сессию",
+ "toast.session.share.failed.description": "Произошла ошибка при публикации сессии",
+
+ "toast.session.unshare.success.title": "Публикация отменена",
+ "toast.session.unshare.success.description": "Публикация успешно отменена!",
+ "toast.session.unshare.failed.title": "Не удалось отменить публикацию",
+ "toast.session.unshare.failed.description": "Произошла ошибка при отмене публикации",
+
+ "toast.session.listFailed.title": "Не удалось загрузить сессии для {{project}}",
+
+ "toast.update.title": "Доступно обновление",
+ "toast.update.description": "Новая версия OpenCode ({{version}}) доступна для установки.",
+ "toast.update.action.installRestart": "Установить и перезапустить",
+ "toast.update.action.notYet": "Пока нет",
+
+ "error.page.title": "Что-то пошло не так",
+ "error.page.description": "Произошла ошибка при загрузке приложения.",
+ "error.page.details.label": "Детали ошибки",
+ "error.page.action.restart": "Перезапустить",
+ "error.page.action.checking": "Проверка...",
+ "error.page.action.checkUpdates": "Проверить обновления",
+ "error.page.action.updateTo": "Обновить до {{version}}",
+ "error.page.report.prefix": "Пожалуйста, сообщите об этой ошибке команде OpenCode",
+ "error.page.report.discord": "в Discord",
+ "error.page.version": "Версия: {{version}}",
+
+ "error.dev.rootNotFound":
+ "Корневой элемент не найден. Вы забыли добавить его в index.html? Или, может быть, атрибут id был написан неправильно?",
+
+ "error.globalSync.connectFailed": "Не удалось подключиться к серверу. Запущен ли сервер по адресу `{{url}}`?",
+
+ "error.chain.unknown": "Неизвестная ошибка",
+ "error.chain.causedBy": "Причина:",
+ "error.chain.apiError": "Ошибка API",
+ "error.chain.status": "Статус: {{status}}",
+ "error.chain.retryable": "Повторная попытка: {{retryable}}",
+ "error.chain.responseBody": "Тело ответа:\n{{body}}",
+ "error.chain.didYouMean": "Возможно, вы имели в виду: {{suggestions}}",
+ "error.chain.modelNotFound": "Модель не найдена: {{provider}}/{{model}}",
+ "error.chain.checkConfig": "Проверьте названия провайдера/модели в конфиге (opencode.json)",
+ "error.chain.mcpFailed":
+ 'MCP сервер "{{name}}" завершился с ошибкой. Обратите внимание, что OpenCode пока не поддерживает MCP авторизацию.',
+ "error.chain.providerAuthFailed": "Ошибка аутентификации провайдера ({{provider}}): {{message}}",
+ "error.chain.providerInitFailed":
+ 'Не удалось инициализировать провайдера "{{provider}}". Проверьте учётные данные и конфигурацию.',
+ "error.chain.configJsonInvalid": "Конфигурационный файл по адресу {{path}} не является валидным JSON(C)",
+ "error.chain.configJsonInvalidWithMessage":
+ "Конфигурационный файл по адресу {{path}} не является валидным JSON(C): {{message}}",
+ "error.chain.configDirectoryTypo":
+ 'Папка "{{dir}}" в {{path}} невалидна. Переименуйте папку в "{{suggestion}}" или удалите её. Это распространённая опечатка.',
+ "error.chain.configFrontmatterError": "Не удалось разобрать frontmatter в {{path}}:\n{{message}}",
+ "error.chain.configInvalid": "Конфигурационный файл по адресу {{path}} невалиден",
+ "error.chain.configInvalidWithMessage": "Конфигурационный файл по адресу {{path}} невалиден: {{message}}",
+
+ "notification.permission.title": "Требуется разрешение",
+ "notification.permission.description": "{{sessionTitle}} в {{projectName}} требуется разрешение",
+ "notification.question.title": "Вопрос",
+ "notification.question.description": "У {{sessionTitle}} в {{projectName}} есть вопрос",
+ "notification.action.goToSession": "Перейти к сессии",
+
+ "notification.session.responseReady.title": "Ответ готов",
+ "notification.session.error.title": "Ошибка сессии",
+ "notification.session.error.fallbackDescription": "Произошла ошибка",
+
+ "home.recentProjects": "Недавние проекты",
+ "home.empty.title": "Нет недавних проектов",
+ "home.empty.description": "Начните с открытия локального проекта",
+
+ "session.tab.session": "Сессия",
+ "session.tab.review": "Обзор",
+ "session.tab.context": "Контекст",
+ "session.review.filesChanged": "{{count}} файлов изменено",
+ "session.review.loadingChanges": "Загрузка изменений...",
+ "session.review.empty": "Изменений в этой сессии пока нет",
+ "session.messages.renderEarlier": "Показать предыдущие сообщения",
+ "session.messages.loadingEarlier": "Загрузка предыдущих сообщений...",
+ "session.messages.loadEarlier": "Загрузить предыдущие сообщения",
+ "session.messages.loading": "Загрузка сообщений...",
+ "session.messages.jumpToLatest": "Перейти к последнему",
+
+ "session.context.addToContext": "Добавить {{selection}} в контекст",
+
+ "session.new.worktree.main": "Основная ветка",
+ "session.new.worktree.mainWithBranch": "Основная ветка ({{branch}})",
+ "session.new.worktree.create": "Создать новый worktree",
+ "session.new.lastModified": "Последнее изменение",
+
+ "session.header.search.placeholder": "Поиск {{project}}",
+
+ "session.share.popover.title": "Опубликовать в интернете",
+ "session.share.popover.description.shared":
+ "Эта сессия общедоступна. Доступ к ней может получить любой, у кого есть ссылка.",
+ "session.share.popover.description.unshared":
+ "Опубликуйте сессию в интернете. Доступ к ней сможет получить любой, у кого есть ссылка.",
+ "session.share.action.share": "Поделиться",
+ "session.share.action.publish": "Опубликовать",
+ "session.share.action.publishing": "Публикация...",
+ "session.share.action.unpublish": "Отменить публикацию",
+ "session.share.action.unpublishing": "Отмена публикации...",
+ "session.share.action.view": "Посмотреть",
+ "session.share.copy.copied": "Скопировано",
+ "session.share.copy.copyLink": "Копировать ссылку",
+
+ "lsp.tooltip.none": "Нет LSP серверов",
+ "lsp.label.connected": "{{count}} LSP",
+
+ "prompt.loading": "Загрузка запроса...",
+ "terminal.loading": "Загрузка терминала...",
+ "terminal.title": "Терминал",
+ "terminal.title.numbered": "Терминал {{number}}",
+ "terminal.connectionLost.title": "Соединение потеряно",
+ "terminal.connectionLost.description":
+ "Соединение с терминалом прервано. Это может произойти при перезапуске сервера.",
+
+ "common.closeTab": "Закрыть вкладку",
+ "common.dismiss": "Закрыть",
+ "common.requestFailed": "Запрос не выполнен",
+ "common.moreOptions": "Дополнительные опции",
+ "common.learnMore": "Подробнее",
+ "common.rename": "Переименовать",
+ "common.reset": "Сбросить",
+ "common.delete": "Удалить",
+ "common.close": "Закрыть",
+ "common.edit": "Редактировать",
+ "common.loadMore": "Загрузить ещё",
+ "common.key.esc": "ESC",
+
+ "sidebar.menu.toggle": "Переключить меню",
+ "sidebar.settings": "Настройки",
+ "sidebar.help": "Помощь",
+ "sidebar.workspaces.enable": "Включить рабочие пространства",
+ "sidebar.workspaces.disable": "Отключить рабочие пространства",
+ "sidebar.gettingStarted.title": "Начало работы",
+ "sidebar.gettingStarted.line1": "OpenCode включает бесплатные модели, чтобы вы могли начать сразу.",
+ "sidebar.gettingStarted.line2":
+ "Подключите любого провайдера для использования моделей, включая Claude, GPT, Gemini и др.",
+ "sidebar.project.recentSessions": "Недавние сессии",
+ "sidebar.project.viewAllSessions": "Посмотреть все сессии",
+
+ "settings.section.desktop": "Приложение",
+ "settings.tab.general": "Основные",
+ "settings.tab.shortcuts": "Горячие клавиши",
+
+ "settings.general.section.appearance": "Внешний вид",
+ "settings.general.section.notifications": "Системные уведомления",
+ "settings.general.section.sounds": "Звуковые эффекты",
+
+ "settings.general.row.language.title": "Язык",
+ "settings.general.row.language.description": "Изменить язык отображения OpenCode",
+ "settings.general.row.appearance.title": "Внешний вид",
+ "settings.general.row.appearance.description": "Настройте как OpenCode выглядит на вашем устройстве",
+ "settings.general.row.theme.title": "Тема",
+ "settings.general.row.theme.description": "Настройте оформление OpenCode.",
+ "settings.general.row.font.title": "Шрифт",
+ "settings.general.row.font.description": "Настройте моноширинный шрифт для блоков кода",
+ "font.option.ibmPlexMono": "IBM Plex Mono",
+ "font.option.cascadiaCode": "Cascadia Code",
+ "font.option.firaCode": "Fira Code",
+ "font.option.hack": "Hack",
+ "font.option.inconsolata": "Inconsolata",
+ "font.option.intelOneMono": "Intel One Mono",
+ "font.option.jetbrainsMono": "JetBrains Mono",
+ "font.option.mesloLgs": "Meslo LGS",
+ "font.option.robotoMono": "Roboto Mono",
+ "font.option.sourceCodePro": "Source Code Pro",
+ "font.option.ubuntuMono": "Ubuntu Mono",
+ "sound.option.alert01": "Alert 01",
+ "sound.option.alert02": "Alert 02",
+ "sound.option.alert03": "Alert 03",
+ "sound.option.alert04": "Alert 04",
+ "sound.option.alert05": "Alert 05",
+ "sound.option.alert06": "Alert 06",
+ "sound.option.alert07": "Alert 07",
+ "sound.option.alert08": "Alert 08",
+ "sound.option.alert09": "Alert 09",
+ "sound.option.alert10": "Alert 10",
+ "sound.option.bipbop01": "Bip-bop 01",
+ "sound.option.bipbop02": "Bip-bop 02",
+ "sound.option.bipbop03": "Bip-bop 03",
+ "sound.option.bipbop04": "Bip-bop 04",
+ "sound.option.bipbop05": "Bip-bop 05",
+ "sound.option.bipbop06": "Bip-bop 06",
+ "sound.option.bipbop07": "Bip-bop 07",
+ "sound.option.bipbop08": "Bip-bop 08",
+ "sound.option.bipbop09": "Bip-bop 09",
+ "sound.option.bipbop10": "Bip-bop 10",
+ "sound.option.staplebops01": "Staplebops 01",
+ "sound.option.staplebops02": "Staplebops 02",
+ "sound.option.staplebops03": "Staplebops 03",
+ "sound.option.staplebops04": "Staplebops 04",
+ "sound.option.staplebops05": "Staplebops 05",
+ "sound.option.staplebops06": "Staplebops 06",
+ "sound.option.staplebops07": "Staplebops 07",
+ "sound.option.nope01": "Nope 01",
+ "sound.option.nope02": "Nope 02",
+ "sound.option.nope03": "Nope 03",
+ "sound.option.nope04": "Nope 04",
+ "sound.option.nope05": "Nope 05",
+ "sound.option.nope06": "Nope 06",
+ "sound.option.nope07": "Nope 07",
+ "sound.option.nope08": "Nope 08",
+ "sound.option.nope09": "Nope 09",
+ "sound.option.nope10": "Nope 10",
+ "sound.option.nope11": "Nope 11",
+ "sound.option.nope12": "Nope 12",
+ "sound.option.yup01": "Yup 01",
+ "sound.option.yup02": "Yup 02",
+ "sound.option.yup03": "Yup 03",
+ "sound.option.yup04": "Yup 04",
+ "sound.option.yup05": "Yup 05",
+ "sound.option.yup06": "Yup 06",
+
+ "settings.general.notifications.agent.title": "Агент",
+ "settings.general.notifications.agent.description":
+ "Показывать системное уведомление когда агент завершён или требует внимания",
+ "settings.general.notifications.permissions.title": "Разрешения",
+ "settings.general.notifications.permissions.description":
+ "Показывать системное уведомление когда требуется разрешение",
+ "settings.general.notifications.errors.title": "Ошибки",
+ "settings.general.notifications.errors.description": "Показывать системное уведомление когда происходит ошибка",
+
+ "settings.general.sounds.agent.title": "Агент",
+ "settings.general.sounds.agent.description": "Воспроизводить звук когда агент завершён или требует внимания",
+ "settings.general.sounds.permissions.title": "Разрешения",
+ "settings.general.sounds.permissions.description": "Воспроизводить звук когда требуется разрешение",
+ "settings.general.sounds.errors.title": "Ошибки",
+ "settings.general.sounds.errors.description": "Воспроизводить звук когда происходит ошибка",
+
+ "settings.shortcuts.title": "Горячие клавиши",
+ "settings.shortcuts.reset.button": "Сбросить к умолчаниям",
+ "settings.shortcuts.reset.toast.title": "Горячие клавиши сброшены",
+ "settings.shortcuts.reset.toast.description": "Горячие клавиши были сброшены к значениям по умолчанию.",
+ "settings.shortcuts.conflict.title": "Сочетание уже используется",
+ "settings.shortcuts.conflict.description": "{{keybind}} уже назначено для {{titles}}.",
+ "settings.shortcuts.unassigned": "Не назначено",
+ "settings.shortcuts.pressKeys": "Нажмите клавиши",
+ "settings.shortcuts.search.placeholder": "Поиск горячих клавиш",
+ "settings.shortcuts.search.empty": "Горячие клавиши не найдены",
+
+ "settings.shortcuts.group.general": "Основные",
+ "settings.shortcuts.group.session": "Сессия",
+ "settings.shortcuts.group.navigation": "Навигация",
+ "settings.shortcuts.group.modelAndAgent": "Модель и агент",
+ "settings.shortcuts.group.terminal": "Терминал",
+ "settings.shortcuts.group.prompt": "Запрос",
+
+ "settings.providers.title": "Провайдеры",
+ "settings.providers.description": "Настройки провайдеров будут доступны здесь.",
+ "settings.models.title": "Модели",
+ "settings.models.description": "Настройки моделей будут доступны здесь.",
+ "settings.agents.title": "Агенты",
+ "settings.agents.description": "Настройки агентов будут доступны здесь.",
+ "settings.commands.title": "Команды",
+ "settings.commands.description": "Настройки команд будут доступны здесь.",
+ "settings.mcp.title": "MCP",
+ "settings.mcp.description": "Настройки MCP будут доступны здесь.",
+
+ "settings.permissions.title": "Разрешения",
+ "settings.permissions.description": "Контролируйте какие инструменты сервер может использовать по умолчанию.",
+ "settings.permissions.section.tools": "Инструменты",
+ "settings.permissions.toast.updateFailed.title": "Не удалось обновить разрешения",
+
+ "settings.permissions.action.allow": "Разрешить",
+ "settings.permissions.action.ask": "Спрашивать",
+ "settings.permissions.action.deny": "Запретить",
+
+ "settings.permissions.tool.read.title": "Чтение",
+ "settings.permissions.tool.read.description": "Чтение файла (по совпадению пути)",
+ "settings.permissions.tool.edit.title": "Редактирование",
+ "settings.permissions.tool.edit.description":
+ "Изменение файлов, включая редактирование, запись, патчи и мульти-редактирование",
+ "settings.permissions.tool.glob.title": "Glob",
+ "settings.permissions.tool.glob.description": "Сопоставление файлов по паттернам glob",
+ "settings.permissions.tool.grep.title": "Grep",
+ "settings.permissions.tool.grep.description": "Поиск по содержимому файлов с использованием регулярных выражений",
+ "settings.permissions.tool.list.title": "Список",
+ "settings.permissions.tool.list.description": "Список файлов в директории",
+ "settings.permissions.tool.bash.title": "Bash",
+ "settings.permissions.tool.bash.description": "Выполнение команд оболочки",
+ "settings.permissions.tool.task.title": "Task",
+ "settings.permissions.tool.task.description": "Запуск под-агентов",
+ "settings.permissions.tool.skill.title": "Skill",
+ "settings.permissions.tool.skill.description": "Загрузить навык по имени",
+ "settings.permissions.tool.lsp.title": "LSP",
+ "settings.permissions.tool.lsp.description": "Выполнение запросов к языковому серверу",
+ "settings.permissions.tool.todoread.title": "Чтение списка задач",
+ "settings.permissions.tool.todoread.description": "Чтение списка задач",
+ "settings.permissions.tool.todowrite.title": "Запись списка задач",
+ "settings.permissions.tool.todowrite.description": "Обновление списка задач",
+ "settings.permissions.tool.webfetch.title": "Web Fetch",
+ "settings.permissions.tool.webfetch.description": "Получить содержимое по URL",
+ "settings.permissions.tool.websearch.title": "Web Search",
+ "settings.permissions.tool.websearch.description": "Поиск в интернете",
+ "settings.permissions.tool.codesearch.title": "Поиск кода",
+ "settings.permissions.tool.codesearch.description": "Поиск кода в интернете",
+ "settings.permissions.tool.external_directory.title": "Внешняя директория",
+ "settings.permissions.tool.external_directory.description": "Доступ к файлам вне директории проекта",
+ "settings.permissions.tool.doom_loop.title": "Doom Loop",
+ "settings.permissions.tool.doom_loop.description": "Обнаружение повторных вызовов инструментов с одинаковым вводом",
+
+ "workspace.new": "Новое рабочее пространство",
+ "workspace.type.local": "локальное",
+ "workspace.type.sandbox": "песочница",
+ "workspace.create.failed.title": "Не удалось создать рабочее пространство",
+ "workspace.delete.failed.title": "Не удалось удалить рабочее пространство",
+ "workspace.resetting.title": "Сброс рабочего пространства",
+ "workspace.resetting.description": "Это может занять минуту.",
+ "workspace.reset.failed.title": "Не удалось сбросить рабочее пространство",
+ "workspace.reset.success.title": "Рабочее пространство сброшено",
+ "workspace.reset.success.description": "Рабочее пространство теперь соответствует ветке по умолчанию.",
+ "workspace.status.checking": "Проверка наличия неслитых изменений...",
+ "workspace.status.error": "Не удалось проверить статус git.",
+ "workspace.status.clean": "Неслитые изменения не обнаружены.",
+ "workspace.status.dirty": "Обнаружены неслитые изменения в этом рабочем пространстве.",
+ "workspace.delete.title": "Удалить рабочее пространство",
+ "workspace.delete.confirm": 'Удалить рабочее пространство "{{name}}"?',
+ "workspace.delete.button": "Удалить рабочее пространство",
+ "workspace.reset.title": "Сбросить рабочее пространство",
+ "workspace.reset.confirm": 'Сбросить рабочее пространство "{{name}}"?',
+ "workspace.reset.button": "Сбросить рабочее пространство",
+ "workspace.reset.archived.none": "Никакие активные сессии не будут архивированы.",
+ "workspace.reset.archived.one": "1 сессия будет архивирована.",
+ "workspace.reset.archived.many": "{{count}} сессий будет архивировано.",
+ "workspace.reset.note": "Рабочее пространство будет сброшено в соответствие с веткой по умолчанию.",
+}
diff --git a/packages/app/src/i18n/zh.ts b/packages/app/src/i18n/zh.ts
index 92a1ad45b..34a686dfd 100644
--- a/packages/app/src/i18n/zh.ts
+++ b/packages/app/src/i18n/zh.ts
@@ -274,6 +274,7 @@ export const dict = {
"language.fr": "法语",
"language.ja": "日语",
"language.da": "丹麦语",
+ "language.ru": "俄语",
"language.pl": "波兰语",
"toast.language.title": "语言",