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 -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": "语言", diff --git a/packages/ui/src/i18n/ru.ts b/packages/ui/src/i18n/ru.ts new file mode 100644 index 000000000..111d36f9e --- /dev/null +++ b/packages/ui/src/i18n/ru.ts @@ -0,0 +1,90 @@ +export const dict = { + "ui.sessionReview.title": "Изменения сессии", + "ui.sessionReview.diffStyle.unified": "Объединённый", + "ui.sessionReview.diffStyle.split": "Разделённый", + "ui.sessionReview.expandAll": "Развернуть всё", + "ui.sessionReview.collapseAll": "Свернуть всё", + + "ui.sessionTurn.steps.show": "Показать шаги", + "ui.sessionTurn.steps.hide": "Скрыть шаги", + "ui.sessionTurn.summary.response": "Ответ", + "ui.sessionTurn.diff.showMore": "Показать ещё изменений ({{count}})", + + "ui.sessionTurn.retry.retrying": "повтор", + "ui.sessionTurn.retry.inSeconds": "через {{seconds}}с", + + "ui.sessionTurn.status.delegating": "Делегирование работы", + "ui.sessionTurn.status.planning": "Планирование следующих шагов", + "ui.sessionTurn.status.gatheringContext": "Сбор контекста", + "ui.sessionTurn.status.searchingCodebase": "Поиск в кодовой базе", + "ui.sessionTurn.status.searchingWeb": "Поиск в интернете", + "ui.sessionTurn.status.makingEdits": "Внесение изменений", + "ui.sessionTurn.status.runningCommands": "Выполнение команд", + "ui.sessionTurn.status.thinking": "Размышление", + "ui.sessionTurn.status.thinkingWithTopic": "Размышление - {{topic}}", + "ui.sessionTurn.status.gatheringThoughts": "Сбор мыслей", + "ui.sessionTurn.status.consideringNextSteps": "Рассмотрение следующих шагов", + + "ui.messagePart.diagnostic.error": "Ошибка", + "ui.messagePart.title.edit": "Редактировать", + "ui.messagePart.title.write": "Написать", + "ui.messagePart.option.typeOwnAnswer": "Введите свой ответ", + "ui.messagePart.review.title": "Проверьте ваши ответы", + + "ui.list.loading": "Загрузка", + "ui.list.empty": "Нет результатов", + "ui.list.emptyWithFilter.prefix": "Нет результатов для", + "ui.list.emptyWithFilter.suffix": "", + + "ui.messageNav.newMessage": "Новое сообщение", + + "ui.textField.copyToClipboard": "Копировать в буфер обмена", + "ui.textField.copied": "Скопировано", + + "ui.imagePreview.alt": "Предпросмотр изображения", + + "ui.tool.read": "Чтение", + "ui.tool.list": "Список", + "ui.tool.glob": "Glob", + "ui.tool.grep": "Grep", + "ui.tool.webfetch": "Webfetch", + "ui.tool.shell": "Оболочка", + "ui.tool.patch": "Патч", + "ui.tool.todos": "Задачи", + "ui.tool.todos.read": "Читать задачи", + "ui.tool.questions": "Вопросы", + "ui.tool.agent": "Агент {{type}}", + + "ui.common.file.one": "файл", + "ui.common.file.other": "файлов", + "ui.common.question.one": "вопрос", + "ui.common.question.other": "вопросов", + + "ui.common.add": "Добавить", + "ui.common.cancel": "Отмена", + "ui.common.confirm": "Подтвердить", + "ui.common.dismiss": "Закрыть", + "ui.common.next": "Далее", + "ui.common.submit": "Отправить", + + "ui.permission.deny": "Запретить", + "ui.permission.allowAlways": "Разрешить всегда", + "ui.permission.allowOnce": "Разрешить один раз", + + "ui.message.expand": "Развернуть сообщение", + "ui.message.collapse": "Свернуть сообщение", + "ui.message.copy": "Копировать", + "ui.message.copied": "Скопировано!", + "ui.message.attachment.alt": "вложение", + + "ui.patch.action.deleted": "Удалено", + "ui.patch.action.created": "Создано", + "ui.patch.action.moved": "Перемещено", + "ui.patch.action.patched": "Изменено", + + "ui.question.subtitle.answered": "{{count}} отвечено", + "ui.question.answer.none": "(нет ответа)", + "ui.question.review.notAnswered": "(не отвечено)", + "ui.question.multiHint": "(выберите все подходящие)", + "ui.question.custom.placeholder": "Введите ваш ответ...", +}