6d89c1afde
Only the CLI could install a plugin at an exact commit (`--ref <sha>`); the Desktop "Install from Git" dialog, the TUI gateway `plugins.manage install` method and the dashboard `/agent-plugins/install` endpoint all called `_install_plugin_core` without a ref, so a team that wanted everyone on the same private-plugin commit had to leave the app for a terminal. - `dashboard_install_plugin(ref=)` threads the pin to `_install_plugin_core`; the 40-hex validation and HEAD verification are unchanged. The gateway method and dashboard body accept `ref`. - Desktop dialog gains an optional "Pin to commit" field (custom sources only, client-side 40-hex check disables Install on anything shorter). - `plugins.manage list` rows carry `pinned_sha`; the Desktop plugins tab shows a `pinned @ <sha8>` badge and `hermes plugins list` prints `git pinned@<sha8>` in Source, so a team can eyeball that everyone runs the same commit.
3845 lines
249 KiB
TypeScript
3845 lines
249 KiB
TypeScript
import { defineFieldCopy } from '@/app/settings/field-copy'
|
||
|
||
import { defineLocale } from './define-locale'
|
||
|
||
// RU_PLURAL: (count, one, few, many) — русские формы сущ. падежа
|
||
// RU_NOUN: (count, one, few, many) — формы род. множественного
|
||
// count может быть number или string (часть подписей en.ts передаёт строки)
|
||
const ruNum = (count: number | string) => (typeof count === 'string' ? Number(count) || 0 : count)
|
||
|
||
const RU_PLURAL = (count: number | string, one: string, few: string, many: string) => {
|
||
const c = ruNum(count)
|
||
const n = Math.abs(c) % 10
|
||
const nn = Math.abs(c) % 100
|
||
|
||
return n === 1 && nn !== 11 ? one : n >= 2 && n <= 4 && (nn < 12 || nn > 14) ? few : many
|
||
}
|
||
|
||
const RU_NOUN = (count: number | string, one: string, few: string, many: string) => {
|
||
const c = ruNum(count)
|
||
const n = Math.abs(c) % 10
|
||
const nn = Math.abs(c) % 100
|
||
|
||
return n === 1 && nn !== 11 ? one : n >= 2 && n <= 4 && (nn < 12 || nn > 14) ? few : many
|
||
}
|
||
|
||
export const ru = defineLocale({
|
||
sessionImport: {
|
||
title: 'Продолжить из другого приложения',
|
||
subtitle: 'Перенесите разговор в Hermes и продолжите с того места, где остановились.',
|
||
action: 'Импортировать сессию',
|
||
readingFrom: 'Читаем с',
|
||
connectedComputer: 'подключённого компьютера',
|
||
destination: 'Импорт в',
|
||
all: 'Все',
|
||
search: 'Поиск по загруженным сессиям',
|
||
scanning: 'Поиск разговоров',
|
||
scanError: 'Не удалось найти сессии',
|
||
scanHelp: 'Проверьте подключение к серверу и повторите попытку. Старому серверу может требоваться обновление.',
|
||
empty: 'Разговоров пока нет',
|
||
emptyHelp: 'Здесь появятся сессии Claude Code и Codex с этого сервера.',
|
||
noMatches: 'Совпадений нет',
|
||
searchHelp: 'Попробуйте другой заголовок или папку либо загрузите ещё сессии.',
|
||
skipped: 'Некоторые журналы пусты, недоступны или слишком велики для просмотра.',
|
||
more: 'Загрузить ещё сессии',
|
||
messages: 'сообщений',
|
||
choose: 'Разговор, который стоит продолжить',
|
||
chooseHelp: 'Выберите сессию, чтобы прочитать историю перед импортом в Hermes.',
|
||
previewLoading: 'Открываем просмотр',
|
||
previewError: 'Просмотр недоступен',
|
||
previewHelp: 'Исходный файл мог переместиться или измениться. Обновите список и повторите попытку.',
|
||
previewLimit: 'Просмотр сокращён для удобства чтения. Импортируется весь разговор.',
|
||
you: 'Вы',
|
||
snapshot: 'Этот разговор уже есть в Hermes. Откройте существующую копию, чтобы продолжить.',
|
||
copyNotice:
|
||
'Копируется текст разговора. Исходные файлы не меняются. Вывод инструментов и рассуждения не переносятся.',
|
||
importing: 'Импорт…',
|
||
open: 'Открыть в Hermes',
|
||
continue: 'Продолжить в Hermes',
|
||
importError: 'Не удалось импортировать разговор.'
|
||
},
|
||
common: {
|
||
apply: 'Применить',
|
||
back: 'Назад',
|
||
save: 'Сохранить',
|
||
saving: 'Сохранение…',
|
||
cancel: 'Отмена',
|
||
change: 'Изменить',
|
||
choose: 'Выбрать',
|
||
clear: 'Очистить',
|
||
close: 'Закрыть',
|
||
collapse: 'Свернуть',
|
||
confirm: 'Подтвердить',
|
||
connect: 'Подключить',
|
||
connecting: 'Подключение',
|
||
continue: 'Продолжить',
|
||
copied: 'Скопировано',
|
||
copy: 'Копировать',
|
||
copyFailed: 'Не удалось скопировать',
|
||
delete: 'Удалить',
|
||
docs: 'Документация',
|
||
done: 'Готово',
|
||
error: 'Ошибка',
|
||
expand: 'Развернуть',
|
||
failed: 'Ошибка',
|
||
formatJson: 'Форматировать JSON',
|
||
free: 'Бесплатно',
|
||
loading: 'Загрузка…',
|
||
notSet: 'Не задано',
|
||
refresh: 'Обновить',
|
||
remove: 'Убрать',
|
||
replace: 'Заменить',
|
||
retry: 'Повторить',
|
||
run: 'Запустить',
|
||
send: 'Отправить',
|
||
set: 'Установить',
|
||
skip: 'Пропустить',
|
||
update: 'Обновить',
|
||
tryHint: term => `Попробуйте «${term}»`,
|
||
on: 'Вкл',
|
||
off: 'Выкл'
|
||
},
|
||
fileMenu: {
|
||
revealFinder: 'Показать в Finder',
|
||
revealExplorer: 'Показать в Проводнике',
|
||
revealFileManager: 'Открыть содержащую папку',
|
||
revealInSidebar: 'Показать в дереве файлов',
|
||
copyPath: 'Копировать путь',
|
||
copyRelativePath: 'Копировать относительный путь',
|
||
download: 'Скачать',
|
||
downloadSaved: 'Сохранено',
|
||
downloadFailed: 'Не удалось скачать',
|
||
rename: 'Переименовать…',
|
||
delete: 'Удалить',
|
||
renameTitle: 'Переименование',
|
||
renameLabel: 'Новое имя',
|
||
deleteTitle: name => `Удалить ${name}?`,
|
||
deleteBody: 'Элемент будет перемещён в корзину — его можно восстановить оттуда.',
|
||
pathCopied: 'Путь скопирован'
|
||
},
|
||
boot: {
|
||
ready: 'Hermes Desktop готов',
|
||
desktopBootFailedWithMessage: message => `Не удалось запустить приложение: ${message}`,
|
||
steps: {
|
||
connectingGateway: 'Подключение к шлюзу',
|
||
loadingSettings: 'Загрузка настроек Hermes',
|
||
loadingSessions: 'Загрузка последних сеансов',
|
||
retryingRemoteBackend: 'Переподключение к удалённому бэкенду Hermes…',
|
||
startingDesktopConnection: 'Запуск подключения приложения',
|
||
startingHermesDesktop: 'Запуск Hermes Desktop…'
|
||
},
|
||
errors: {
|
||
backgroundExited: 'Фоновый процесс Hermes завершён.',
|
||
backgroundExitedDuringStartup: 'Фоновый процесс Hermes завершился при запуске.',
|
||
backendStopped: 'Бэкенд остановлен',
|
||
desktopBootFailed: 'Не удалось запустить приложение',
|
||
gatewayConnectionLost: 'Соединение с шлюзом потеряно',
|
||
gatewaySignInRequired: 'Требуется вход в шлюз',
|
||
ipcBridgeUnavailable: 'IPC-мост приложения недоступен.'
|
||
},
|
||
failure: {
|
||
title: 'Hermes не удалось запустить',
|
||
description:
|
||
'Фоновый шлюз не запустился. Попробуйте один из шагов восстановления ниже. Ничто из этого не удаляет ваши чаты и настройки.',
|
||
remoteTitle: 'Требуется вход в удалённый шлюз',
|
||
remoteDescription:
|
||
'Сессия удалённого шлюза истекла. Войдите снова, чтобы переподключиться. Ничто из этого не удаляет ваши чаты и настройки.',
|
||
retry: 'Повторить',
|
||
repairInstall: 'Восстановить установку',
|
||
useLocalGateway: 'Использовать локальный шлюз',
|
||
gatewaySettings: 'Настройки шлюза',
|
||
back: 'Назад',
|
||
openLogs: 'Открыть журналы',
|
||
repairHint: 'Восстановление перезапускает установщик — на чистой машине это может занять несколько минут.',
|
||
remoteSignInHint: signInLabel =>
|
||
`Выход из сохранённой сессии удалённого браузера, затем открытие ${signInLabel}. Чтобы перейти на встроенный бэкенд, используйте локальный шлюз.`,
|
||
signOutAndSignIn: 'Выйти и войти',
|
||
remoteFailureHint: 'Проверьте URL шлюза и вход в настройках шлюза или переключитесь на локальный шлюз.',
|
||
hideRecentLogs: 'Скрыть недавние журналы',
|
||
showRecentLogs: 'Показать недавние журналы',
|
||
signedInTitle: 'Вы вошли в систему',
|
||
signedInMessage: 'Переподключение к удалённому шлюзу…',
|
||
signInIncompleteTitle: 'Вход не завершён',
|
||
signInIncompleteMessage: 'Окно входа закрылось до завершения аутентификации.',
|
||
signInFailed: 'Не удалось войти',
|
||
signInToRemoteGateway: 'Войти в удалённый шлюз',
|
||
signInWithProvider: provider => `Войти через ${provider}`,
|
||
identityProvider: 'вашему провайдеру аутентификации'
|
||
}
|
||
},
|
||
notifications: {
|
||
region: 'Уведомления',
|
||
hide: 'Скрыть',
|
||
show: 'Показать',
|
||
more: count =>
|
||
`Ещё ${count} ${count % 10 === 1 && count % 100 !== 11 ? 'уведомление' : count % 10 >= 2 && count % 10 <= 4 && (count % 100 < 12 || count % 100 > 14) ? 'уведомления' : 'уведомлений'}`,
|
||
clearAll: 'Очистить всё',
|
||
dismiss: 'Закрыть уведомление',
|
||
details: 'Подробности',
|
||
copyDetail: 'Копировать подробность',
|
||
copyDetailFailed: 'Не удалось скопировать подробность уведомления',
|
||
backendOutOfDateTitle: 'Устаревший бэкенд',
|
||
backendOutOfDateMessage:
|
||
'Ваш бэкенд Hermes старше этой сборки приложения и может работать некорректно. Обновите их, чтобы они совпали.',
|
||
installMethodUnsupportedTitle: 'Неподдерживаемый способ установки',
|
||
updateHermes: 'Обновить Hermes',
|
||
updateReadyTitle: 'Обновление готово',
|
||
updateReadyMessage: count =>
|
||
`Доступно ${count} ${count % 10 === 1 && count % 100 !== 11 ? 'новое изменение' : count % 10 >= 2 && count % 10 <= 4 && (count % 100 < 12 || count % 100 > 14) ? 'новых изменения' : 'новых изменений'}.`,
|
||
updateReadyMessageUnknown: 'Доступно новое обновление.',
|
||
seeWhatsNew: 'Смотреть, что нового',
|
||
mcp: {
|
||
needsAuthTitle: 'Серверу MCP требуется повторная аутентификация',
|
||
needsAuthMessage: name => `Для MCP ${name} требуется повторная аутентификация.`,
|
||
errorTitle: 'Сервер MCP недоступен',
|
||
errorMessage: name => `MCP ${name} не прошёл проверку работоспособности.`,
|
||
signIn: 'Войти',
|
||
view: 'Просмотр'
|
||
},
|
||
errors: {
|
||
elevenLabsNeedsKey: 'Для STT ElevenLabs нужен ELEVENLABS_API_KEY.',
|
||
elevenLabsRejectedKey: 'ElevenLabs отклонил API-ключ (401).',
|
||
diskFull: 'Диск заполнен — освободите место и повторите.',
|
||
gatewayAuthFailed: 'Аутентификация шлюза не удалась — проверьте API_SERVER_KEY.',
|
||
methodNotAllowed:
|
||
'Бэкенд приложения отклонил запрос (405 Method Not Allowed). Попробуйте перезапустить Hermes Desktop.',
|
||
microphonePermission: 'Доступ к микрофону запрещён.',
|
||
openaiRejectedApiKey: 'OpenAI отклонил API-ключ.',
|
||
openaiRejectedApiKeyWithStatus: status => `OpenAI отклонил API-ключ (${status} invalid_api_key).`,
|
||
openaiTtsNeedsKey: 'Для TTS OpenAI нужен VOICE_TOOLS_OPENAI_KEY или OPENAI_API_KEY.'
|
||
},
|
||
voice: {
|
||
configureSpeechToText: 'Настройте распознавание речи, чтобы использовать голосовой режим.',
|
||
couldNotStartSession: 'Не удалось начать голосовой сеанс',
|
||
microphoneAccessDenied: 'Доступ к микрофону запрещён.',
|
||
microphoneConstraintsUnsupported: 'Ограничения микрофона не поддерживаются этим устройством.',
|
||
microphoneFailed: 'Ошибка микрофона',
|
||
microphoneInUse: 'Микрофон уже используется другим приложением.',
|
||
microphonePermissionDenied: 'Доступ к микрофону запрещён.',
|
||
microphoneStartFailed: 'Не удалось начать запись с микрофона.',
|
||
microphoneUnsupported: 'Это окружение не поддерживает запись с микрофона.',
|
||
noMicrophone: 'Микрофон не найден.',
|
||
noSpeechDetected: 'Речь не обнаружена',
|
||
playbackFailed: 'Не удалось воспроизвести голос',
|
||
recordingFailed: 'Не удалось записать голос',
|
||
sayStopToEnd: phrase => `Скажите «${phrase}», чтобы закончить голосовой чат.`,
|
||
transcriptionFailed: 'Не удалось расшифровать речь',
|
||
transcriptionUnavailable: 'Расшифровка речи пока недоступна.',
|
||
tryRecordingAgain: 'Попробуйте записать ещё раз.',
|
||
unavailable: 'Голос недоступен'
|
||
},
|
||
native: {
|
||
approvalTitle: 'Требуется одобрение',
|
||
approveAction: 'Одобрить',
|
||
rejectAction: 'Отклонить',
|
||
inputTitle: 'Требуется ввод',
|
||
inputBody: 'Hermes ожидает ваш ответ.',
|
||
turnDoneTitle: 'Hermes завершил',
|
||
turnDoneBody: '',
|
||
turnErrorTitle: 'Ход не удался',
|
||
backgroundDoneTitle: 'Фоновая задача завершена',
|
||
backgroundFailedTitle: 'Фоновая задача не удалась',
|
||
creditsTitle: 'Кредиты'
|
||
}
|
||
},
|
||
remoteDisplayBanner: {
|
||
message: reason =>
|
||
`Включён программный рендеринг — обнаружен удалённый дисплей (${reason}). GPU-ускорение отключено, чтобы избежать мерцания.`
|
||
},
|
||
|
||
billingBlock: {
|
||
titleNous: 'Кредиты Nous закончились',
|
||
titleProvider: provider => `Кредиты закончились — ${provider}`,
|
||
fallbackMessage: 'В вашем аккаунте закончились кредиты. Пополните баланс, чтобы продолжить.',
|
||
openBilling: 'Открыть биллинг',
|
||
addCredits: 'Пополнить кредиты',
|
||
dismiss: 'Скрыть'
|
||
},
|
||
|
||
titlebar: {
|
||
hideSidebar: 'Скрыть боковую панель',
|
||
showSidebar: 'Показать боковую панель',
|
||
search: 'Поиск',
|
||
searchTitle: 'Поиск сеансов, видов и действий',
|
||
swapSidebarSides: 'Поменять панели местами',
|
||
hideRightSidebar: 'Скрыть правую панель',
|
||
showRightSidebar: 'Показать правую панель',
|
||
unreadSessions: count =>
|
||
count === 1
|
||
? '1 непрочитанный сеанс'
|
||
: `${count} ${count % 10 === 1 && count % 100 !== 11 ? 'непрочитанный сеанс' : count % 10 >= 2 && count % 10 <= 4 && (count % 100 < 12 || count % 100 > 14) ? 'непрочитанных сеанса' : 'непрочитанных сеансов'}`,
|
||
muteHaptics: 'Выключить вибрацию',
|
||
unmuteHaptics: 'Включить вибрацию',
|
||
openSettings: 'Открыть настройки',
|
||
openStarmap: 'Открыть граф памяти',
|
||
enterHud: 'Режим HUD',
|
||
exitHud: 'Выйти из режима HUD',
|
||
layoutEditor: 'Редактор раскладки',
|
||
layoutEditorTitle: mod => `Редактор раскладки — ${mod}-клик сбрасывает раскладку`
|
||
},
|
||
keybinds: {
|
||
title: 'Горячие клавиши',
|
||
subtitle: open => `Нажмите на сочетание, чтобы переназначить · ${open} снова открывает эту панель.`,
|
||
search: 'Поиск горячих клавиш…',
|
||
rebind: 'Переназначить',
|
||
reset: 'Сбросить по умолчанию',
|
||
resetAll: 'Сбросить всё',
|
||
pressKey: 'Нажмите клавишу…',
|
||
set: 'задано',
|
||
conflictWith: label => `Также назначено на «${label}»`,
|
||
categories: {
|
||
composer: 'Композер',
|
||
profiles: 'Профили',
|
||
session: 'Сеанс',
|
||
navigation: 'Навигация',
|
||
view: 'Вид'
|
||
},
|
||
actions: {
|
||
'keybinds.openPanel': 'Открыть горячие клавиши',
|
||
'nav.commandPalette': 'Открыть палитру команд',
|
||
'nav.commandCenter': 'Открыть центр команд',
|
||
'nav.settings': 'Открыть настройки',
|
||
'nav.profiles': 'Открыть профили',
|
||
'nav.skills': 'Открыть навыки',
|
||
'nav.messaging': 'Открыть мессенджеры',
|
||
'nav.artifacts': 'Открыть артефакты',
|
||
'nav.cron': 'Открыть запланированные задачи',
|
||
'nav.agents': 'Открыть агенты',
|
||
'session.new': 'Новый сеанс',
|
||
'session.newTab': 'Новая вкладка сеанса',
|
||
'session.newWindow': 'Новое окно',
|
||
'session.next': 'Следующий сеанс',
|
||
'session.prev': 'Предыдущий сеанс',
|
||
'session.slot.1': 'Переключить на недавний сеанс 1',
|
||
'session.slot.2': 'Переключить на недавний сеанс 2',
|
||
'session.slot.3': 'Переключить на недавний сеанс 3',
|
||
'session.slot.4': 'Переключить на недавний сеанс 4',
|
||
'session.slot.5': 'Переключить на недавний сеанс 5',
|
||
'session.slot.6': 'Переключить на недавний сеанс 6',
|
||
'session.slot.7': 'Переключить на недавний сеанс 7',
|
||
'session.slot.8': 'Переключить на недавний сеанс 8',
|
||
'session.slot.9': 'Переключить на недавний сеанс 9',
|
||
'session.focusSearch': 'Поиск по сеансам',
|
||
'session.togglePin': 'Закрепить / открепить текущий сеанс',
|
||
'session.archive': 'В архив текущий сеанс',
|
||
'workspace.newWorktree': 'Новый worktree',
|
||
'workspace.openFolder': 'Открыть папку как проект',
|
||
'composer.focus': 'Сфокусировать композер',
|
||
'composer.modelPicker': 'Открыть выбор модели',
|
||
'composer.voice': 'Начать / остановить голосовой диалог',
|
||
'view.toggleSidebar': 'Показать / скрыть панель сеансов',
|
||
'view.toggleRightSidebar': 'Показать / скрыть браузер файлов',
|
||
'view.toggleReview': 'Показать / скрыть панель ревью',
|
||
'view.toggleStatusbar': 'Показать / скрыть строку состояния',
|
||
'view.toggleTabStrip': 'Показать / скрыть вкладки',
|
||
'view.showFiles': 'Показать браузер файлов',
|
||
'view.showBrowser': 'Открыть браузер',
|
||
'view.toggleHud': 'Включить / выключить режим HUD',
|
||
'hud.snapToPointer': 'Переместить HUD под курсор (глобально, пока HUD открыт)',
|
||
'view.showTerminal': 'Показать / скрыть терминал',
|
||
'view.newTerminal': 'Новый терминал',
|
||
'view.nextTerminal': 'Следующий терминал',
|
||
'view.prevTerminal': 'Предыдущий терминал',
|
||
'view.closeTerminal': 'Закрыть терминал',
|
||
'view.terminalSelection': 'Отправить выделенное из терминала в композер',
|
||
'view.terminalCopy': 'Копировать выделенное из терминала',
|
||
'view.terminalPaste': 'Вставить в терминал',
|
||
'view.closeTab': 'Закрыть вкладку',
|
||
'view.reopenTab': 'Восстановить закрытую вкладку',
|
||
'view.flipPanes': 'Поменять панели местами',
|
||
'view.findInPage': 'Найти на странице',
|
||
'view.findNext': 'Следующее вхождение',
|
||
'view.findPrevious': 'Предыдущее вхождение',
|
||
'appearance.toggleMode': 'Сменить светлую / тёмную тему',
|
||
'profile.default': 'Переключить на профиль по умолчанию',
|
||
'profile.switch.1': 'Переключить на профиль 1',
|
||
'profile.switch.2': 'Переключить на профиль 2',
|
||
'profile.switch.3': 'Переключить на профиль 3',
|
||
'profile.switch.4': 'Переключить на профиль 4',
|
||
'profile.switch.5': 'Переключить на профиль 5',
|
||
'profile.switch.6': 'Переключить на профиль 6',
|
||
'profile.switch.7': 'Переключить на профиль 7',
|
||
'profile.switch.8': 'Переключить на профиль 8',
|
||
'profile.switch.9': 'Переключить на профиль 9',
|
||
'profile.switch.10': 'Переключить на профиль 10',
|
||
'profile.switch.11': 'Переключить на профиль 11',
|
||
'profile.switch.12': 'Переключить на профиль 12',
|
||
'profile.switch.13': 'Переключить на профиль 13',
|
||
'profile.switch.14': 'Переключить на профиль 14',
|
||
'profile.switch.15': 'Переключить на профиль 15',
|
||
'profile.switch.16': 'Переключить на профиль 16',
|
||
'profile.switch.17': 'Переключить на профиль 17',
|
||
'profile.switch.18': 'Переключить на профиль 18',
|
||
'profile.next': 'Следующий профиль',
|
||
'profile.prev': 'Предыдущий профиль',
|
||
'profile.toggleAll': 'Показать все профили',
|
||
'profile.create': 'Создать профиль',
|
||
'composer.send': 'Отправить сообщение',
|
||
'composer.newline': 'Вставить перенос строки',
|
||
'composer.steer': 'Направить текущий ход',
|
||
'composer.queue': 'Поставить сообщение в очередь',
|
||
'composer.sendQueued': 'Отправить следующий ход из очереди',
|
||
'composer.mention': 'Ссылка на файлы, папки, URL',
|
||
'composer.slash': 'Палитра slash-команд',
|
||
'composer.help': 'Быстрая справка',
|
||
'composer.history': 'Переключить поповер / историю',
|
||
'composer.cancel': 'Закрыть поповер · отменить запуск'
|
||
}
|
||
},
|
||
findInPage: {
|
||
next: 'Следующее вхождение',
|
||
previous: 'Предыдущее вхождение'
|
||
},
|
||
|
||
language: {
|
||
label: 'Язык',
|
||
description: 'Выберите язык интерфейса приложения.',
|
||
saving: 'Сохранение языка…',
|
||
saveError: 'Не удалось обновить язык',
|
||
switchTo: 'Сменить язык',
|
||
searchPlaceholder: 'Поиск языка…',
|
||
noResults: 'Языки не найдены'
|
||
},
|
||
settings: {
|
||
closeSettings: 'Закрыть настройки',
|
||
exportConfig: 'Экспорт конфигурации',
|
||
importConfig: 'Импорт конфигурации',
|
||
resetToDefaults: 'Сбросить к значениям по умолчанию',
|
||
resetConfirm: 'Сбросить все настройки к значениям Hermes по умолчанию?',
|
||
exportFailed: 'Не удалось экспортировать',
|
||
resetFailed: 'Не удалось сбросить',
|
||
nav: {
|
||
providers: 'Провайдеры',
|
||
providerAccounts: 'Аккаунты',
|
||
providerApiKeys: 'API-ключи',
|
||
providerCustomEndpoints: 'Свои эндпоинты',
|
||
gateway: 'Шлюзы',
|
||
apiKeys: 'Инструменты и ключи',
|
||
keybinds: 'Горячие клавиши',
|
||
keysTools: 'Инструменты',
|
||
keysSettings: 'Настройки',
|
||
mcp: 'MCP',
|
||
archivedChats: 'Архив чатов',
|
||
about: 'О программе',
|
||
billing: 'Оплата',
|
||
notifications: 'Уведомления'
|
||
},
|
||
plugins: {
|
||
title: 'Плагины приложения',
|
||
blurb: 'Встроенные или добавленные в папку desktop-plugins. Отключите, чтобы выгрузить без перезапуска.',
|
||
count: n => `Установлено: ${n}`,
|
||
openFolder: 'Открыть папку плагинов',
|
||
rescan: 'Пересканировать',
|
||
reveal: 'Показать в файловом менеджере',
|
||
enable: 'Включить',
|
||
disable: 'Отключить',
|
||
failed: 'ошибка',
|
||
empty: 'Плагины приложения пока не установлены.',
|
||
kinds: { bundled: 'встроенный', disk: 'на диске', runtime: 'runtime' },
|
||
installModal: {
|
||
title: 'Установка плагина',
|
||
description: 'Перед установкой посмотрите, что содержит этот репозиторий.',
|
||
repoLabel: 'Репозиторий',
|
||
includesHeading: 'Состав пакета',
|
||
agentLabel: 'Плагин агента',
|
||
desktopLabel: 'UI приложения',
|
||
agentTargetLocal: profile => `Устанавливается в локальный бэкенд ${profile} (~/.hermes/plugins/)`,
|
||
agentTargetRemote: profile => `Устанавливается в подключённый бэкенд ${profile}`,
|
||
desktopTarget: 'Устанавливается в локальную папку desktop-plugins этого приложения',
|
||
desktopOnlyNote: 'Пакеты только для приложения не устанавливают плагин агента.',
|
||
insecureWarning:
|
||
'Этот URL использует небезопасную или локальную схему. Для боевой установки предпочитайте https:// или git@.',
|
||
securityHeading: 'Перед установкой',
|
||
securityIntro:
|
||
'Устанавливайте только из проверенных источников — при желании просмотрите репозиторий ниже, чтобы увидеть, что будет добавлено.',
|
||
sourceHeading: 'Исходный код',
|
||
viewRepository: 'Посмотреть репозиторий',
|
||
viewPluginFiles: 'Посмотреть файлы плагина',
|
||
gitCloneLabel: 'URL для git clone',
|
||
enableAgent: 'Включить плагин агента после установки',
|
||
forceReinstall: 'Принудительная переустановка (заменить, если уже установлен)',
|
||
pinToCommit: 'Закрепить на коммите (необязательно)',
|
||
pinToCommitPlaceholder: 'Полный SHA коммита (40 символов)',
|
||
pinToCommitHint:
|
||
'Все, кто установит этот SHA, получат одинаковый код; плагин перестанет обновляться до смены пина. Оставьте пустым для последнего коммита.',
|
||
pinToCommitInvalid: 'Нужен полный SHA коммита из 40 символов (ветки и теги не принимаются).',
|
||
install: 'Установить',
|
||
installing: 'Установка…',
|
||
probing: 'Осмотр репозитория…',
|
||
probeUnavailable: 'Осмотр плагинов недоступен в этом окружении.',
|
||
desktopUnavailable: 'Установка плагинов приложения недоступна в этом окружении.',
|
||
selectComponent: 'Выберите хотя бы один компонент для установки.',
|
||
agentSuccess: name => `Плагин агента ${name} установлен`,
|
||
desktopSuccess: name => `Плагин приложения ${name} установлен`,
|
||
agentFailed: 'Не удалось установить плагин агента',
|
||
desktopFailed: 'Не удалось установить плагин приложения',
|
||
missingEnv: vars => `Не хватает переменных окружения: ${vars}. Добавьте их в Настройки → Ключи.`
|
||
}
|
||
},
|
||
notifications: {
|
||
title: 'Уведомления',
|
||
intro: 'Системные уведомления (не всплывающие внутри приложения). Настраивается для каждого устройства.',
|
||
enableAll: 'Включить уведомления',
|
||
enableAllDesc: 'Если выключено — все уведомления ниже будут заглушены.',
|
||
focusedHint: 'Оповещения о завершении срабатывают только пока Hermes в фоне.',
|
||
kinds: {
|
||
approval: {
|
||
label: 'Нужно одобрение',
|
||
description: 'Команда ожидает вашего одобрения или отклонения.'
|
||
},
|
||
input: {
|
||
label: 'Нужен ввод',
|
||
description: 'Hermes задал вопрос или требует пароль/секрет.'
|
||
},
|
||
turnDone: {
|
||
label: 'Ответ готов',
|
||
description: 'Ход завершился, пока Hermes был в фоне.'
|
||
},
|
||
turnError: {
|
||
label: 'Ход не удался',
|
||
description: 'Ошибки фоновых ходов.'
|
||
},
|
||
backgroundDone: {
|
||
label: 'Фоновая задача завершена',
|
||
description: 'Фоновая команда терминала выполнена.'
|
||
},
|
||
credits: {
|
||
label: 'Оповещения о кредитах',
|
||
description: 'Доступ к кредитам приостановлен или восстановлен.'
|
||
},
|
||
plugin: {
|
||
label: 'Уведомления плагинов',
|
||
description: 'Плагин приложения отправил уведомление, пока Hermes был в фоне.'
|
||
}
|
||
},
|
||
test: 'Отправить тестовое уведомление',
|
||
testTitle: 'Hermes',
|
||
testBody: 'Уведомления работают.',
|
||
testSent:
|
||
'Тест отправлен. Если ничего не появилось, проверьте разрешения на уведомления в системе и режим «Не беспокоить».',
|
||
testUnsupported: 'Эта система не поддерживает системные уведомления.',
|
||
completionSoundTitle: 'Звук завершения',
|
||
completionSoundDesc: 'Воспроизводится, когда ход агента завершён. Выберите пресет и прослушайте здесь.',
|
||
completionSoundPreview: 'Прослушать'
|
||
},
|
||
sections: {
|
||
model: 'Модель',
|
||
chat: 'Чат',
|
||
appearance: 'Внешний вид',
|
||
workspace: 'Рабочее пространство',
|
||
safety: 'Безопасность',
|
||
memory: 'Память и контекст',
|
||
voice: 'Голос',
|
||
advanced: 'Дополнительно'
|
||
},
|
||
searchPlaceholder: {
|
||
about: 'О Hermes Desktop',
|
||
config: 'Поиск настроек…',
|
||
gateway: 'Подключение шлюза…',
|
||
keys: 'Поиск API-ключей…',
|
||
mcp: 'Поиск MCP-серверов…',
|
||
sessions: 'Поиск архивных сеансов…'
|
||
},
|
||
modeOptions: {
|
||
light: { label: 'Светлая', description: 'Яркие поверхности' },
|
||
dark: { label: 'Тёмная', description: 'Мягкое рабочее пространство' },
|
||
system: { label: 'Системная', description: 'Следовать настройкам ОС' }
|
||
},
|
||
appearance: {
|
||
title: 'Внешний вид',
|
||
intro: 'Только для приложения. Режим — это яркость, тема — палитра и оформление чата.',
|
||
colorMode: 'Цветовой режим',
|
||
colorModeDesc: 'Выберите фиксированный режим или позвольте Hermes следовать настройкам системы.',
|
||
toolViewTitle: 'Отображение вызовов инструментов',
|
||
toolViewDesc: 'Режим «Продукт» скрывает сырые данные инструментов, «Технический» показывает полный вход/выход.',
|
||
reasoningCollapsedTitle: 'Сворачивать «мышление» по умолчанию',
|
||
reasoningCollapsedDesc:
|
||
'Стриминговое рассуждение остаётся доступным, но не разворачивается, пока вы его не откроете.',
|
||
uiScaleTitle: 'Масштаб интерфейса',
|
||
uiScaleDesc: percent =>
|
||
`Масштабирует текст и элементы управления во всём приложении. Также работает Cmd/Ctrl с +, − и 0. Сейчас: ${percent}%.`,
|
||
sessionDensityTitle: 'Плотность списка сеансов',
|
||
sessionDensityDesc: 'Выберите, сколько контекста показывать под заголовками сеансов в боковой панели.',
|
||
sessionDensityCompact: 'Компактно',
|
||
sessionDensityComfortable: 'Комфортно',
|
||
sessionDensityDetailed: 'Подробно',
|
||
tabStripTitle: 'Панель вкладок',
|
||
tabStripDesc: 'Показывать вкладки над зоной. Автоматически скрываются, когда в зоне только одна панель.',
|
||
tabStripAuto: 'Авто',
|
||
tabStripAlways: 'Всегда',
|
||
tabStripNever: 'Никогда',
|
||
terminalFontTitle: 'Шрифт терминала',
|
||
terminalFontDesc:
|
||
'Выберите установленный шрифт для терминалов приложения. Nerd Fonts отображают Powerlevel10k и иконки оболочки; оставьте пустым, чтобы использовать встроенный JetBrains Mono.',
|
||
terminalFontPlaceholder: 'MesloLGS NF или CSS-стек шрифтов',
|
||
terminalFontPreview: 'Предпросмотр глифов',
|
||
terminalFontReset: 'Использовать по умолчанию',
|
||
translucencyTitle: 'Полупрозрачность окна',
|
||
translucencyDesc:
|
||
'Рабочий стол виден сквозь всё окно, включая текст. Отдельная настройка для светлой и тёмной тем.',
|
||
translucencyGlassDesc:
|
||
'Матовое стекло: рабочий стол виден как плавное размытие, а текст остаётся чётким. Отдельная настройка для светлой и тёмной тем.',
|
||
translucencyModeClear: 'Прозрачная',
|
||
translucencyModeGlass: 'Стекло',
|
||
translucencyTintTitle: 'Тон',
|
||
translucencyFadeTitle: 'Затухание',
|
||
translucencyFrostTitle: 'Матовость',
|
||
translucencyFrost: {
|
||
'under-window': 'Глубина',
|
||
popover: 'Мягкость',
|
||
titlebar: 'Яркость',
|
||
header: 'Отблеск'
|
||
},
|
||
translucencyScopeTitle: 'Область',
|
||
translucencyScope: {
|
||
window: 'Всё окно',
|
||
sidebar: 'Только боковая панель'
|
||
},
|
||
backdropTitle: 'Фон чата',
|
||
backdropDesc: 'Блёклый силуэт позади диалога.',
|
||
userBubbleTitle: 'Пузырь сообщения',
|
||
userBubbleDesc: 'Насколько прозрачны ваши сообщения. 0 — сплошная заливка, 100 — остаётся только контур.',
|
||
introSplashTitle: 'Экран приветствия',
|
||
introSplashDesc: 'Логотип и подсказка, показываемые на пустом чате.',
|
||
reactionsTitle: 'Реакции на сообщения',
|
||
reactionsDesc: 'Эмодзи-тапбеки в стиле iMessage — реагируйте на сообщения, и Hermes сможет реагировать на ваши.',
|
||
composerPopoutTitle: 'Плавающий композер',
|
||
composerPopoutDesc: 'Позволяет вытягивать композер из его док-зоны. Отключите, чтобы он был закреплён снизу.',
|
||
embedsTitle: 'Встроенные превью',
|
||
embedsDesc:
|
||
'Богатые превью загружаются со сторонних сайтов (YouTube, X, …). «Спрашивать» показывает заглушку, пока вы не разрешите каждый источник; «Всегда» загружает их автоматически; «Выкл» оставляет обычные ссылки.',
|
||
embedsAsk: 'Спрашивать',
|
||
embedsAlways: 'Всегда',
|
||
embedsOff: 'Выкл',
|
||
embedsReset: count =>
|
||
`Сбросить ${count} ${RU_NOUN(count, 'разрешённый сервис', 'разрешённых сервиса', 'разрешённых сервисов')}`,
|
||
resumeLastSessionTitle: 'Открывать последний чат при запуске',
|
||
resumeLastSessionDesc:
|
||
'Продолжайте с того места, где остановились. Выключите, чтобы всегда начинать с нового чата.',
|
||
product: 'Продукт',
|
||
productDesc: 'Дружелюбная активность инструментов с краткими сводками.',
|
||
technical: 'Технический',
|
||
technicalDesc: 'Показывать сырые аргументы/результаты инструментов и низкоуровневые детали.',
|
||
themeTitle: 'Тема',
|
||
themeDesc: 'Только палитры для приложения. Выбранный режим применяется поверх.',
|
||
themeProfileNote: profile => `Сохранено для профиля ${profile} — у каждого профиля своя тема.`,
|
||
installTitle: 'Установить из VS Code',
|
||
installDesc:
|
||
'Вставьте id расширения с Marketplace (напр. dracula-theme.theme-dracula), чтобы преобразовать его цветовую тему в палитру приложения.',
|
||
installPlaceholder: 'publisher.extension',
|
||
installButton: 'Установить',
|
||
installing: 'Установка…',
|
||
installError: 'Не удалось установить эту тему.',
|
||
installed: name => `Установлена «${name}».`,
|
||
removeTheme: 'Удалить тему',
|
||
importedBadge: 'Импортирована',
|
||
pet: {
|
||
title: 'Питомец',
|
||
intro:
|
||
'Заберите анимированного питомца из petdex, который парит над приложением и реагирует на действия Hermes — «бегает», пока выполняются инструменты, радуется успеху и хмурится при ошибках.',
|
||
restartHint:
|
||
'Питомцам нужен быстрый перезапуск — текущее приложение запустилось до появления этой функции. Выйдите из Hermes и откройте снова, затем вернитесь сюда.',
|
||
on: 'Вкл',
|
||
off: 'Выкл',
|
||
scaleTitle: 'Размер',
|
||
scaleDesc: 'Меняет размер парящего питомца. Применяется мгновенно везде.',
|
||
roamTitle: 'Блуждание',
|
||
roamDesc: 'Позволить питомцу самому бродить по окну, пока всё бездействие.',
|
||
chooseTitle: 'Выбрать питомца',
|
||
chooseDesc: 'Выбор установит его (при необходимости) и сделает активным.',
|
||
searchPlaceholder: 'Поиск питомцев…',
|
||
unreachable: 'Не удалось связаться с галереей petdex. Проверьте соединение и откройте страницу заново.',
|
||
noMatch: query => `Нет питомцев, подходящих под «${query}».`,
|
||
installedTag: 'установлен',
|
||
generatedTag: 'Сгенерирован',
|
||
countCapped: (cap, total) => `Показаны ${cap} из ${total} — начните вводить, чтобы сузить выбор.`,
|
||
count: n => `${n} ${RU_PLURAL(n, 'питомец', 'питомца', 'питомцев')}.`,
|
||
uninstall: name => `Удалить ${name}`,
|
||
delete: name => `Удалить навсегда ${name}`,
|
||
deleteTitle: name => `Удалить ${name}?`,
|
||
deleteBody: 'Питомец будет удалён безвозвратно — переустановить его будет нельзя.',
|
||
deleteConfirm: 'Удалить',
|
||
rename: name => `Переименовать ${name}`,
|
||
renameTitle: 'Переименовать питомца',
|
||
renamePlaceholder: 'Имя вашего питомца',
|
||
renameSave: 'Сохранить',
|
||
exportPet: name => `Экспортировать ${name}`,
|
||
adoptFailed: slug => `Не удалось забрать ${slug}`,
|
||
uninstallFailed: slug => `Не удалось удалить ${slug}`,
|
||
renameFailed: slug => `Не удалось переименовать ${slug}`,
|
||
exportFailed: slug => `Не удалось экспортировать ${slug}`,
|
||
noneAvailable: 'Сейчас нет доступных питомцев для включения.',
|
||
turnOnFailed: 'Не удалось включить питомца.',
|
||
turnOffFailed: 'Не удалось выключить питомца.'
|
||
}
|
||
},
|
||
fieldLabels: defineFieldCopy({
|
||
model: 'Модель по умолчанию',
|
||
modelContextLength: 'Окно контекста',
|
||
fallbackProviders: 'Резервные модели',
|
||
toolsets: 'Включённые наборы инструментов',
|
||
timezone: 'Часовой пояс',
|
||
display: {
|
||
personality: 'Личность',
|
||
showReasoning: 'Блоки рассуждений'
|
||
},
|
||
desktop: {
|
||
repoScanEnabled: 'Автоматическое обнаружение репозиториев',
|
||
repoScanRoots: 'Корни обнаружения репозиториев',
|
||
repoScanExcludePaths: 'Исключаемые пути репозиториев'
|
||
},
|
||
agent: {
|
||
maxTurns: 'Макс. шагов агента',
|
||
imageInputMode: 'Вложения изображений',
|
||
apiMaxRetries: 'Повторы API',
|
||
serviceTier: 'Уровень сервиса',
|
||
toolUseEnforcement: 'Принудительное использование инструментов'
|
||
},
|
||
terminal: {
|
||
cwd: 'Рабочий каталог',
|
||
backend: 'Бэкенд выполнения',
|
||
timeout: 'Тайм-аут команд',
|
||
persistentShell: 'Персистентная оболочка',
|
||
envPassthrough: 'Пропуск переменных окружения',
|
||
dockerImage: 'Образ Docker',
|
||
singularityImage: 'Образ Singularity',
|
||
modalImage: 'Образ Modal',
|
||
daytonaImage: 'Образ Daytona'
|
||
},
|
||
fileReadMaxChars: 'Лимит чтения файла',
|
||
toolOutput: {
|
||
maxBytes: 'Лимит вывода терминала',
|
||
maxLines: 'Лимит страниц файла',
|
||
maxLineLength: 'Лимит длины строки'
|
||
},
|
||
codeExecution: {
|
||
mode: 'Режим выполнения кода'
|
||
},
|
||
approvals: {
|
||
mode: 'Режим подтверждения',
|
||
timeout: 'Тайм-аут подтверждения',
|
||
mcpReloadConfirm: 'Подтверждать перезагрузку MCP'
|
||
},
|
||
commandAllowlist: 'Список разрешённых команд',
|
||
security: {
|
||
redactSecrets: 'Скрывать секреты',
|
||
allowPrivateUrls: 'Разрешать частные URL'
|
||
},
|
||
browser: {
|
||
allowPrivateUrls: 'Частные URL браузера',
|
||
autoLocalForPrivateUrls: 'Локальный браузер для частных URL'
|
||
},
|
||
checkpoints: {
|
||
enabled: 'Чекпоинты файлов',
|
||
maxSnapshots: 'Лимит чекпоинтов'
|
||
},
|
||
voice: {
|
||
recordKey: 'Горячая клавиша голосового ввода',
|
||
maxRecordingSeconds: 'Макс. длительность записи',
|
||
autoTts: 'Зачитывать ответы вслух'
|
||
},
|
||
stt: {
|
||
enabled: 'Распознавание речи',
|
||
echoTranscripts: 'Повторять расшифровки',
|
||
provider: 'Провайдер распознавания речи',
|
||
local: {
|
||
model: 'Локальная модель транскрипции',
|
||
language: 'Язык транскрипции'
|
||
},
|
||
openai: {
|
||
model: 'Модель STT OpenAI'
|
||
},
|
||
groq: {
|
||
model: 'Модель STT Groq'
|
||
},
|
||
mistral: {
|
||
model: 'Модель STT Mistral'
|
||
},
|
||
elevenlabs: {
|
||
modelId: 'Модель STT ElevenLabs',
|
||
languageCode: 'Язык ElevenLabs',
|
||
tagAudioEvents: 'Метки звуковых событий',
|
||
diarize: 'Разделение спикеров'
|
||
}
|
||
},
|
||
tts: {
|
||
provider: 'Провайдер синтеза речи',
|
||
edge: {
|
||
voice: 'Голос Edge'
|
||
},
|
||
openai: {
|
||
model: 'Модель TTS OpenAI',
|
||
voice: 'Голос OpenAI'
|
||
},
|
||
elevenlabs: {
|
||
voiceId: 'Голос ElevenLabs',
|
||
modelId: 'Модель ElevenLabs'
|
||
},
|
||
xai: {
|
||
voiceId: 'Голос xAI (Grok)',
|
||
language: 'Язык xAI',
|
||
speed: 'Скорость воспроизведения xAI',
|
||
autoSpeechTags: 'Автомаркеры речи xAI',
|
||
optimizeStreamingLatency: 'Оптимизация задержки стриминга xAI',
|
||
sampleRate: 'Частота дискретизации xAI',
|
||
bitRate: 'Битрейт xAI'
|
||
},
|
||
minimax: {
|
||
model: 'Модель TTS MiniMax',
|
||
voiceId: 'Голос MiniMax'
|
||
},
|
||
mistral: {
|
||
model: 'Модель TTS Mistral',
|
||
voiceId: 'Голос Mistral'
|
||
},
|
||
gemini: {
|
||
model: 'Модель TTS Gemini',
|
||
voice: 'Голос Gemini'
|
||
},
|
||
neutts: {
|
||
model: 'Модель NeuTTS',
|
||
device: 'Устройство NeuTTS'
|
||
},
|
||
kittentts: {
|
||
model: 'Модель KittenTTS',
|
||
voice: 'Голос KittenTTS'
|
||
},
|
||
piper: {
|
||
voice: 'Голос Piper'
|
||
},
|
||
deepinfra: {
|
||
model: 'Модель TTS DeepInfra',
|
||
voice: 'Голос DeepInfra'
|
||
}
|
||
},
|
||
memory: {
|
||
memoryEnabled: 'Персистентная память',
|
||
userProfileEnabled: 'Профиль пользователя',
|
||
memoryCharLimit: 'Бюджет памяти',
|
||
userCharLimit: 'Бюджет профиля',
|
||
provider: 'Провайдер памяти'
|
||
},
|
||
context: {
|
||
engine: 'Движок контекста'
|
||
},
|
||
compression: {
|
||
enabled: 'Авто-сжатие',
|
||
threshold: 'Порог сжатия',
|
||
targetRatio: 'Целевое сжатие',
|
||
protectLastN: 'Защищённые недавние сообщения'
|
||
},
|
||
delegation: {
|
||
model: 'Модель субагента',
|
||
provider: 'Провайдер субагента',
|
||
maxIterations: 'Лимит ходов субагента',
|
||
maxConcurrentChildren: 'Параллельные субагенты',
|
||
childTimeoutSeconds: 'Тайм-аут субагента',
|
||
reasoningEffort: 'Глубина рассуждений субагента'
|
||
},
|
||
updates: {
|
||
nonInteractiveLocalChanges: 'Локальные изменения при обновлении из приложения'
|
||
}
|
||
}),
|
||
fieldDescriptions: defineFieldCopy({
|
||
model: 'Используется для новых чатов, если вы не выберете другую модель в композере.',
|
||
modelContextLength: 'Оставьте 0, чтобы использовать обнаруженное окно контекста выбранной модели.',
|
||
fallbackProviders:
|
||
'Резервные записи provider:model, которые будут пробоваться, если модель по умолчанию не сработает.',
|
||
display: {
|
||
personality: 'Стиль ассистента по умолчанию для новых сеансов.',
|
||
showReasoning: 'Показывать блоки рассуждений, когда бэкенд их предоставляет.'
|
||
},
|
||
desktop: {
|
||
repoScanEnabled: 'Сканировать локальные папки на Git-репозитории, чтобы показывать их в Проектах.',
|
||
repoScanRoots: 'Папки для сканирования. Оставьте пустым, чтобы сканировать домашний каталог.',
|
||
repoScanExcludePaths: 'Папки и их вложенные, которые нужно пропускать при обнаружении репозиториев.'
|
||
},
|
||
timezone: 'Идентификатор часового пояса IANA. Пустое значение — системный часовой пояс.',
|
||
agent: {
|
||
imageInputMode: 'Управляет тем, как вложения изображений отправляются модели.',
|
||
maxTurns: 'Верхний предел ходов с вызовами инструментов, после которого Hermes останавливает запуск.'
|
||
},
|
||
terminal: {
|
||
cwd: 'Папка проекта по умолчанию для инструментов и терминала.',
|
||
persistentShell: 'Сохранять состояние оболочки между командами, если бэкенд это поддерживает.',
|
||
envPassthrough: 'Переменные окружения, которые передавать в выполнение инструментов.',
|
||
dockerImage: 'Образ контейнера, используемый, когда бэкенд выполнения — Docker.',
|
||
singularityImage: 'Образ, используемый, когда бэкенд выполнения — Singularity.',
|
||
modalImage: 'Образ, используемый, когда бэкенд выполнения — Modal.',
|
||
daytonaImage: 'Образ, используемый, когда бэкенд выполнения — Daytona.'
|
||
},
|
||
codeExecution: {
|
||
mode: 'Насколько строго выполнение кода ограничено текущим проектом.'
|
||
},
|
||
fileReadMaxChars: 'Максимальное число символов, которые Hermes может прочитать из одного запроса к файлу.',
|
||
approvals: {
|
||
mode: 'Как Hermes обрабатывает команды, требующие явного подтверждения.',
|
||
timeout: 'Как долго запросы подтверждения ждут перед тайм-аутом.'
|
||
},
|
||
security: {
|
||
redactSecrets: 'Скрывать обнаруженные секреты из видимого для модели содержимого, когда это возможно.'
|
||
},
|
||
checkpoints: {
|
||
enabled: 'Создавать снимки для отката перед правкой файлов.'
|
||
},
|
||
memory: {
|
||
memoryEnabled: 'Сохранять долговременные воспоминания, которые могут помочь будущим сеансам.',
|
||
userProfileEnabled: 'Поддерживать компактный профиль предпочтений пользователя.'
|
||
},
|
||
context: {
|
||
engine: 'Стратегия управления длинными диалогами у предела контекста.'
|
||
},
|
||
compression: {
|
||
enabled: 'Сжимать более старый контекст, когда диалоги становятся большими.'
|
||
},
|
||
voice: {
|
||
autoTts: 'Автоматически зачитывать ответы ассистента.'
|
||
},
|
||
tts: {
|
||
xai: {
|
||
voiceId: 'ID голоса xAI (например, eve) или ID пользовательского голоса.',
|
||
language: 'Код языка речи (например, en, pt-BR) или «auto» для автоопределения.',
|
||
speed: 'Скорость воспроизведения. 0.7 = медленнее, 1.0 = нормально, 1.5 = быстрее.',
|
||
autoSpeechTags:
|
||
'Позволить LLM вставлять выразительные звуковые теги ([laughing], [sighs]) в сценарий перед синтезом.',
|
||
optimizeStreamingLatency:
|
||
'Компромисс между задержкой и качеством. 0 = лучшее качество, 2 = минимальная задержка.',
|
||
sampleRate: 'Частота дискретизации аудио в Гц. Выше = лучшее качество, большие файлы.',
|
||
bitRate: 'Битрейт MP3 в бит/с. Действует только когда кодек — mp3.'
|
||
},
|
||
neutts: {
|
||
device: 'Локальное устройство инференса для NeuTTS.'
|
||
}
|
||
},
|
||
stt: {
|
||
enabled: 'Включать локальное или провайдерное распознавание речи.',
|
||
echoTranscripts: 'Возвращать в чат «сырую» 🎙️ расшифровку голосовых сообщений.',
|
||
elevenlabs: {
|
||
languageCode: 'Необязательный код языка ISO-639-3. Пустое значение — автоопределение ElevenLabs.'
|
||
}
|
||
},
|
||
updates: {
|
||
nonInteractiveLocalChanges:
|
||
'Когда Hermes обновляет себя из приложения (без запроса в терминале), сохранять локальные правки исходников (stash) или выбрасывать (discard). Обновления из терминала всегда спрашивают.'
|
||
}
|
||
}),
|
||
about: {
|
||
heading: 'Hermes Desktop',
|
||
version: value => `Версия ${value}`,
|
||
versionUnavailable: 'Версия недоступна',
|
||
bundleOutOfSync: 'Сборка приложения устарела',
|
||
bundleOutOfSyncDesc:
|
||
'Рантайм Hermes обновлён, но само приложение — ещё старая сборка: новые функции интерфейса (например, Bot Mode) не появятся до обновления. Запустите обновление ниже, чтобы пересобрать приложение. Если предупреждение не исчезнет, переустановите с последнего установщика.',
|
||
bundleOutOfSyncAction: 'Скачать установщик',
|
||
updates: 'Обновления',
|
||
checkNow: 'Проверить сейчас',
|
||
checking: 'Проверка…',
|
||
seeWhatsNew: 'Смотреть, что нового',
|
||
updateNow: 'Обновить сейчас',
|
||
releaseNotes: 'Заметки о выпуске',
|
||
onLatest: 'У вас последняя версия.',
|
||
installing: 'Сейчас устанавливается обновление.',
|
||
cantUpdate: 'Эта сборка не может обновляться изнутри приложения.',
|
||
cantReach: 'Не удалось связаться с сервером обновлений.',
|
||
tapCheck: 'Нажмите «Проверить сейчас», чтобы найти обновления.',
|
||
updateReady: count =>
|
||
`Готово новое обновление (включено ${count} ${RU_PLURAL(count, 'изменение', 'изменения', 'изменений')}).`,
|
||
updateReadyUnknown: 'Готово новое обновление.',
|
||
lastChecked: age => `Проверено ${age}`,
|
||
justNowSuffix: ' · только что',
|
||
automaticUpdates: 'Автоматические обновления',
|
||
automaticUpdatesDesc: 'Hermes автоматически проверяет обновления в фоне и сообщает, когда они готовы.',
|
||
branchCommit: (branch, commit) => `Ветка ${branch} · Коммит ${commit}`,
|
||
never: 'никогда',
|
||
justNow: 'только что',
|
||
minAgo: count => `${count} ${RU_NOUN(count, 'минуту', 'минуты', 'минут')} назад`,
|
||
hoursAgo: count => `${count} ${RU_NOUN(count, 'час', 'часа', 'часов')} назад`,
|
||
daysAgo: count => `${count} ${RU_NOUN(count, 'день', 'дня', 'дней')} назад`
|
||
},
|
||
config: {
|
||
none: 'Нет',
|
||
noneParen: '(нет)',
|
||
builtinOnly: 'Только встроенные',
|
||
notSet: 'Не задано',
|
||
commaSeparated: 'значения через запятую',
|
||
searchPlaceholder: 'Поиск…',
|
||
noResults: 'Ничего не найдено',
|
||
systemDefault: 'Системное по умолчанию',
|
||
loading: 'Загрузка конфигурации Hermes…',
|
||
emptyTitle: 'Настраивать нечего',
|
||
emptyDesc: 'В этом разделе нет настраиваемых параметров.',
|
||
failedLoad: 'Не удалось загрузить настройки',
|
||
autosaveFailed: 'Не удалось сохранить автоматически',
|
||
imported: 'Конфигурация импортирована',
|
||
invalidJson: 'Неверный JSON конфигурации',
|
||
toolsetsWipeConfirm:
|
||
'Удалить все включённые наборы инструментов? Это отключит память, терминал, веб-поиск, делегирование и большинство других инструментов, пока вы не включите их снова.',
|
||
keepAwakeTitle: 'Не давать компьютеру засыпать',
|
||
keepAwakeDesc:
|
||
'Не даёт этой машине засыпать, чтобы долгие или ночные прогоны продолжались. Экран при этом может гаснуть.',
|
||
disableF12Title: 'Отключить F12 DevTools',
|
||
disableF12Desc:
|
||
'Блокирует открытие Developer Tools по F12. Ctrl+Shift+I (на Mac — Cmd+Opt+I) продолжает работать.',
|
||
attachmentSizeTitle: 'Макс. размер превью / загрузки изображений',
|
||
attachmentSizeDesc:
|
||
'Насколько большой локальный файл приложение будет загружать для превью и вложений, в МБ. По умолчанию 16. Для удалённых неграфических вложений действует отдельный лимит 256 МБ. Слишком большое значение загружает весь файл в память и может подвесить или уронить приложение.',
|
||
attachmentSizeUnit: 'МБ',
|
||
attachmentSizeLabel: 'Макс. размер превью / загрузки изображений в мегабайтах'
|
||
},
|
||
quickEntry: {
|
||
enabledTitle: 'Быстрый ввод',
|
||
enabledDesc:
|
||
'Глобальным горячим ключом вызывайте маленький композер откуда угодно и отправляйте запрос, не открывая Hermes.',
|
||
shortcutTitle: 'Горячий ключ быстрого ввода',
|
||
shortcutDesc: 'Нужен хотя бы один модификатор, например CommandOrControl+Shift+Space.',
|
||
active: 'Горячий ключ активен.',
|
||
takenBy: 'Это сочетание уже занято другим приложением — выберите другое.',
|
||
invalidShortcut: 'Некорректное сочетание. Включите хотя бы одну модифицирующую клавишу.'
|
||
},
|
||
credentials: {
|
||
pasteKey: 'Вставить ключ',
|
||
pasteLabelKey: label => `Вставить ключ ${label}`,
|
||
optional: 'Необязательно',
|
||
enterValueFirst: 'Сначала введите значение.',
|
||
couldNotSave: 'Не удалось сохранить учётные данные.',
|
||
remove: 'Удалить',
|
||
getKey: 'Получить ключ',
|
||
saving: 'Сохранение'
|
||
},
|
||
envActions: {
|
||
actions: 'Действия',
|
||
manageInKeys: 'Управлять в API-ключах',
|
||
docs: 'Документация',
|
||
hideValue: 'Скрыть значение',
|
||
revealValue: 'Показать значение',
|
||
replace: 'Заменить',
|
||
set: 'Установить',
|
||
clear: 'Очистить'
|
||
},
|
||
// v2 multi-connection registry: Settings → Gateways.
|
||
connections: {
|
||
title: 'Зарегистрированные шлюзы',
|
||
intro:
|
||
'Управляйте этим устройством и всеми шлюзами Hermes, до которых можно дотянуться через удалённые, SSH или Cloud-соединения.',
|
||
stagedNote:
|
||
'Переключайтесь между шлюзами из раздела «Сеансы». Профили, чаты, мессенджеры и cron-задачи остаются за своим шлюзом; работа на других шлюзах продолжается.',
|
||
launchModeTitle: 'При запуске возвращаться к «Сеансам» на последнем шлюзе',
|
||
launchModeDesc: 'Если выключено, «Сеансы» открываются на основном шлюзе.',
|
||
searchPlaceholder: 'Поиск шлюзов…',
|
||
noSearchResults: 'Шлюзы, подходящие под поиск, не найдены.',
|
||
loadFailed: 'Не удалось загрузить соединения',
|
||
currentPill: 'Текущий',
|
||
primaryPill: 'Основной',
|
||
managedPill: 'Управляется приложением',
|
||
addConnection: 'Добавить соединение',
|
||
editConnection: 'Изменить',
|
||
removeConnection: 'Удалить',
|
||
removeConfirmTitle: 'Удалить это соединение?',
|
||
removeConfirmDesc: label =>
|
||
`«${label}» будет удалено из этого приложения. Сама инстанция не затрагивается — её можно добавить снова в любой момент.`,
|
||
makePrimary: 'Сделать основным',
|
||
testConnection: 'Проверить',
|
||
testOk: 'Доступен',
|
||
testFailed: 'Проверка соединения не удалась',
|
||
saveFailed: 'Не удалось сохранить соединение',
|
||
removeFailed: 'Не удалось удалить соединение',
|
||
updateAll: 'Обновить все инстансы',
|
||
updateAllRunning: 'Обновление всех инстансов…',
|
||
updateAllDone: 'Обновления разосланы',
|
||
updateAllFailed: 'Не удалось разослать обновления',
|
||
updateSkippedCloud: 'Управляется Hermes Cloud',
|
||
kindLocal: 'Локальный',
|
||
kindRemote: 'Удалённый шлюз',
|
||
kindCloud: 'Hermes Cloud',
|
||
kindSsh: 'SSH',
|
||
kindLocalDesc: 'Рантайм Hermes, которым управляет это приложение.',
|
||
kindRemoteDesc: 'Шлюз Hermes, доступный по HTTP(S) — LAN, Tailscale или интернет.',
|
||
kindCloudDesc: 'Хостинговая инстанция, обнаруженная через ваш аккаунт Hermes Cloud.',
|
||
kindSshDesc: 'Установка Hermes, доступная по SSH.',
|
||
labelTitle: 'Имя',
|
||
labelDesc:
|
||
'Обязательно. Показывается везде, где фигурирует эта инстанция; должно быть уникальным (напр. «Домашняя лаборатория», «Рабочий ноутбук»).',
|
||
labelPlaceholder: 'Домашняя лаборатория',
|
||
urlTitle: 'URL шлюза',
|
||
sshHostTitle: 'SSH-хост',
|
||
headersTitle: 'Дополнительные заголовки шлюза',
|
||
headersDesc:
|
||
'Отправляются с каждым HTTP- и WebSocket-запросом к этому шлюзу — например, для прокси доступа вроде Cloudflare Access (CF-Access-Client-Id / CF-Access-Client-Secret). Значения хранятся зашифрованными. Заголовки, которыми управляет Hermes (Authorization, Cookie, Host…), игнорируются.',
|
||
headerValuePlaceholder: 'Значение',
|
||
headerValueSaved: 'Сохранено — оставьте пустым, чтобы не менять',
|
||
headerAdd: 'Добавить заголовок',
|
||
headerRemove: 'Удалить',
|
||
duplicateLocal: 'Это приложение уже управляет локальным соединением — их может быть только одно.',
|
||
duplicateUrl: label => `Соединение с этим URL шлюза уже есть («${label}»).`,
|
||
duplicateSsh: label => `Соединение с этим SSH-хостом уже есть («${label}»).`,
|
||
sameBackendHint: label => `Тот же бэкенд, что и «${label}»`,
|
||
localAddHint: 'Локальное недоступно: управляемое локальное соединение уже существует (их всегда только одно).',
|
||
cloudAddHint:
|
||
'Подсказка: вход в Hermes Cloud выше автоматически обнаруживает ваших агентов — эту форму используйте только для ручной регистрации известного URL инстанса.',
|
||
save: 'Сохранить соединение',
|
||
saving: 'Сохранение…',
|
||
cancel: 'Отмена',
|
||
empty: 'Соединения пока не зарегистрированы.'
|
||
},
|
||
gateway: {
|
||
loading: 'Загрузка настроек шлюза…',
|
||
unavailableTitle: 'Настройки шлюза недоступны',
|
||
unavailableDesc: 'IPC-мост приложения не предоставляет настройки шлюза.',
|
||
title: 'Подключение шлюза',
|
||
envOverride: 'переопределение переменными окружения',
|
||
intro:
|
||
'По умолчанию — локальный. Используйте удалённый, когда приложение должно управлять бэкендом Hermes в другом месте. Соединения шлюзов — на уровне машины; профили обнаруживаются из подключённых шлюзов.',
|
||
envOverrideTitle: 'Переменные окружения управляют этой сессией приложения.',
|
||
envOverrideDesc:
|
||
'Сбросьте HERMES_DESKTOP_REMOTE_URL и HERMES_DESKTOP_REMOTE_TOKEN, чтобы использовать сохранённую настройку ниже.',
|
||
modeTitle: 'Режим подключения',
|
||
localTitle: 'Локальный шлюз',
|
||
localDesc: 'Запускает приватный бэкенд Hermes на localhost. Это значение по умолчанию, работает офлайн.',
|
||
remoteTitle: 'Удалённый шлюз',
|
||
remoteDesc: 'Подключает это приложение к удалённому бэкенду Hermes.',
|
||
remoteAuthHint:
|
||
'Хостинговые шлюзы используют OAuth или логин/пароль; самохостинговые могут использовать токен сессии.',
|
||
cloudTitle: 'Hermes Cloud',
|
||
cloudDesc: 'Войдите в Hermes Cloud один раз и выбирайте агентов из своего аккаунта — без вставки URL.',
|
||
cloudSignInTitle: 'Hermes Cloud',
|
||
cloudSignIn: 'Войти в Hermes Cloud',
|
||
cloudSignedIn: 'Вы вошли в Hermes Cloud',
|
||
cloudNeedsSignIn: 'Войдите в Hermes Cloud, чтобы обнаружить агентов в вашем аккаунте.',
|
||
cloudSignedInDesc: 'Вы вошли. Выберите агента ниже; сессия обновляется автоматически.',
|
||
cloudAgentsTitle: 'Ваши агенты',
|
||
cloudOrgPickerTitle: 'Выберите организацию',
|
||
cloudOrgSelect: 'Выбрать',
|
||
cloudOrgChange: 'Сменить организацию',
|
||
cloudOrgRole: role => `Роль: ${role}`,
|
||
cloudLoadingAgents: 'Загрузка ваших агентов…',
|
||
cloudNoAgents: {
|
||
before: 'Агенты на этом аккаунте не найдены. Создайте агента в',
|
||
linkText: 'портале Nous',
|
||
after: ', затем обновите страницу.'
|
||
},
|
||
cloudRefresh: 'Обновить',
|
||
cloudConnect: 'Подключиться',
|
||
cloudSavedTitle: 'Сохранённые облачные шлюзы',
|
||
cloudSavedDesc:
|
||
'Используйте сохранённый шлюз без изменения шлюза по умолчанию. Войдите ниже, чтобы добавить экземпляры. Имена и вход — в списке сохранённых подключений.',
|
||
cloudUseSaved: 'Использовать шлюз',
|
||
cloudActive: 'Активен в этом окне',
|
||
cloudConnecting: 'Подключение…',
|
||
cloudDiscoverFailed: 'Не удалось загрузить агентов Hermes Cloud',
|
||
cloudConnectFailed: 'Не удалось подключиться к этому агенту',
|
||
cloudSignInFailed: 'Не удалось войти в Hermes Cloud',
|
||
cloudSignedOutTitle: 'Выход из Hermes Cloud',
|
||
cloudSignedOutMessage: 'Сессия Hermes Cloud сброшена.',
|
||
cloudConnectedTitle: 'Подключено',
|
||
cloudConnectedPill: 'Подключено',
|
||
cloudConnectedTo: name => `Подключено к ${name}.`,
|
||
cloudAgentProvisioning: 'Развёртывание…',
|
||
cloudStatusLabel: status => `Статус: ${status}`,
|
||
remoteUrlTitle: 'Удалённый URL',
|
||
remoteUrlDesc: 'Базовый URL удалённого бэкенда дашборда. Поддерживаются префиксы пути, например /hermes.',
|
||
probing: 'Проверяем, как аутентифицируется этот шлюз…',
|
||
probeError:
|
||
'Пока не удалось связаться с этим шлюзом. Проверьте URL — способ аутентификации появится, когда он ответит.',
|
||
signedIn: 'Вы вошли',
|
||
signIn: 'Войти',
|
||
signOut: 'Выйти',
|
||
signInWith: provider => `Войти через ${provider}`,
|
||
authTitle: 'Аутентификация',
|
||
authSignedInPassword: 'Этот шлюз использует логин и пароль. Вы вошли; сессия обновляется автоматически.',
|
||
authSignedInOauth: 'Этот шлюз использует OAuth. Вы вошли; сессия обновляется автоматически.',
|
||
authNeedsPassword: 'Этот шлюз использует логин и пароль. Войдите, чтобы авторизовать это приложение.',
|
||
authNeedsOauth: provider =>
|
||
`Этот шлюз использует OAuth. Войдите через ${provider}, чтобы авторизовать это приложение.`,
|
||
tokenTitle: 'Токен сессии',
|
||
tokenDesc:
|
||
'Токен сессии дашборда для доступа через REST и WebSocket. Оставьте пустым, чтобы сохранить текущий токен.',
|
||
existingToken: value => `Текущий токен ${value}`,
|
||
savedToken: 'сохранён',
|
||
pasteSessionToken: 'Вставьте токен сессии',
|
||
plainTextConfirmTitle: 'Хранить токен шлюза в открытом виде?',
|
||
plainTextConfirmDesc:
|
||
'Служба системного хранилища ключей на этой машине не найдена, поэтому токен будет сохранён без шифрования в файле настроек соединения приложения, и его сможет прочитать любой процесс, работающий от вашего имени. Для шифрованного хранилища установите и включите GNOME Keyring или KWallet.',
|
||
plainTextConfirmAction: 'Сохранить в открытом виде',
|
||
plainTextStoredTitle: 'Токен сохранён в открытом виде',
|
||
plainTextStoredDesc:
|
||
'Безопасное хранилище недоступно, поэтому сохранённый токен хранится без шифрования в файле настроек соединения приложения на этой машине. Установите и включите GNOME Keyring или KWallet для шифрования.',
|
||
testRemote: 'Проверить удалённый',
|
||
saveForRestart: 'Сохранить до следующего перезапуска',
|
||
saveAndReconnect: 'Сохранить и переподключиться',
|
||
diagnostics: 'Диагностика',
|
||
diagnosticsDesc: 'Показать desktop.log в файловом менеджере — полезно, если шлюз не запускается.',
|
||
openLogs: 'Открыть логи',
|
||
incompleteTitle: 'Настройки удалённого шлюза неполные',
|
||
incompleteSignIn: 'Введите удалённый URL и войдите, прежде чем переключаться на удалённый режим.',
|
||
incompleteToken: 'Введите удалённый URL и токен сессии, прежде чем переключаться на удалённый режим.',
|
||
incompleteSignInTest: 'Введите удалённый URL и войдите, прежде чем проверять.',
|
||
incompleteTokenTest: 'Введите удалённый URL и токен сессии, прежде чем проверять.',
|
||
enterUrlFirst: 'Сначала введите удалённый URL.',
|
||
restartingTitle: 'Перезапуск соединения шлюза',
|
||
savedTitle: 'Настройки шлюза сохранены',
|
||
restartingMessage: 'Hermes Desktop переподключится с сохранёнными настройками — оболочка останется открытой.',
|
||
savedMessage: 'Сохранено для следующего перезапуска.',
|
||
connectedTo: (baseUrl, version) => `Подключено к ${baseUrl}${version ? ` · Hermes ${version}` : ''}`,
|
||
reachableTitle: 'Удалённый шлюз доступен',
|
||
signedOutTitle: 'Вы вышли',
|
||
signedOutMessage: 'Сессия удалённого шлюза сброшена.',
|
||
failedLoad: 'Не удалось загрузить настройки шлюза',
|
||
signInFailed: 'Не удалось войти',
|
||
signOutFailed: 'Не удалось выйти',
|
||
testFailed: 'Проверка удалённого шлюза не удалась',
|
||
applyFailed: 'Не удалось применить настройки шлюза',
|
||
saveFailed: 'Не удалось сохранить настройки шлюза',
|
||
sshTitle: 'Подключение по SSH',
|
||
sshDesc:
|
||
'Hermes запускается на удалённой машине по SSH и туннелируется в это приложение — ничего не нужно запускать или открывать самим. Требуется рабочая SSH-аутентификация по ключу на хост.',
|
||
sshTrustHint:
|
||
'Первый предъявленный ключ хоста доверяется и фиксируется; последующие изменения приведут к отказу.',
|
||
sshHostTitle: 'Хост',
|
||
sshHostDesc: 'user@host или псевдоним Host из ~/.ssh/config.',
|
||
sshHostPick: 'Выбрать хост…',
|
||
sshHostPickTitle: 'Хост',
|
||
sshHostPickDesc: 'Псевдоним Host из ~/.ssh/config, либо «Свой», чтобы ввести вручную.',
|
||
sshHostCustom: 'Свой (ввести вручную)…',
|
||
sshUserTitle: 'Пользователь',
|
||
sshUserDesc: 'Пусто = ~/.ssh/config или ваш текущий пользователь.',
|
||
sshUserPlaceholder: 'из ~/.ssh/config',
|
||
sshPortTitle: 'Порт',
|
||
sshPortDesc: 'Пусто = 22 или порт из ~/.ssh/config.',
|
||
sshKeyTitle: 'Файл ключа',
|
||
sshKeyDesc: 'Путь к закрытому ключу. Пусто = ssh-agent или ~/.ssh/config.',
|
||
sshHermesPathTitle: 'Путь к Hermes (необязательно)',
|
||
sshHermesPathDesc: 'Полный путь к бинарнику hermes на удалённой машине. Пусто = автоопределение.',
|
||
sshHermesPathPlaceholder: 'автоопределение',
|
||
sshTestConnection: 'Проверить SSH',
|
||
sshConnect: 'Подключиться',
|
||
sshButtonsHint: '«Сохранить» применится при следующем запуске. «Подключиться» переподключится сейчас.',
|
||
sshReachable: (host, platform) => `Доступен: ${host} (${platform}) — Hermes найден`,
|
||
sshIncompleteHost: 'Введите SSH-хост перед подключением.',
|
||
sshErrUnreachable: 'Не удалось достичь этого хоста по SSH. Проверьте хост, порт и сеть.',
|
||
sshErrAuth:
|
||
'SSH-аутентификация не удалась. Загрузите ключ в ssh-agent (ssh-add) или задайте IdentityFile в ~/.ssh/config — Hermes запускает ssh в неинтерактивном режиме.',
|
||
sshErrHostKey:
|
||
'Ключ хоста ИЗМЕНИЛСЯ с последнего подключения. Убедитесь, что это ожидаемо, затем выполните ssh-keygen -R <host> и переподключитесь.',
|
||
sshErrNotInstalled:
|
||
'Hermes не установлен на удалённой машине. Установите его там (curl -fsSL https://hermes-agent.nousresearch.com/install.sh | sh) или задайте путь к Hermes.',
|
||
sshErrPlatform:
|
||
'Неподдерживаемая удалённая платформа. SSH-режим Hermes Desktop поддерживает удалённые хосты Linux, macOS и Windows.',
|
||
sshErrTimeout: 'SSH-соединение истекло. Хост может быть недоступен или «спит».',
|
||
sshErrUpdateRequired: 'Перед подключением через SSH обновите Hermes на удалённой машине.',
|
||
sshErrUnknown: 'SSH-соединение не удалось.'
|
||
},
|
||
keys: {
|
||
loading: 'Загрузка API-ключей и учётных данных…',
|
||
failedLoad: 'Не удалось загрузить API-ключи',
|
||
empty: 'В этой категории пока ничего не настроено.'
|
||
},
|
||
search: {
|
||
placeholder: 'Поиск по всем настройкам…',
|
||
pill: 'Поиск'
|
||
},
|
||
profileScope: {
|
||
appliesTo: 'Применяется к',
|
||
editsProfile: profile => `Изменения на этой странице применяются к профилю «${profile}».`
|
||
},
|
||
mcp: {
|
||
loading: 'Загрузка MCP-серверов…',
|
||
failedLoad: 'Не удалось загрузить конфигурацию MCP',
|
||
nameRequiredTitle: 'Нужно имя',
|
||
nameRequiredMessage: 'Задайте этому MCP-серверу ключ конфигурации.',
|
||
objectRequired: 'Конфигурация сервера должна быть JSON-объектом',
|
||
invalidJson: 'Неверный JSON MCP',
|
||
saveFailed: 'Не удалось сохранить',
|
||
removeFailed: 'Не удалось удалить',
|
||
gatewayUnavailableTitle: 'Шлюз недоступен',
|
||
gatewayUnavailableMessage: 'Переподключите шлюз, прежде чем перезагружать MCP.',
|
||
reloadedTitle: 'Инструменты MCP перезагружены',
|
||
reloadedMessage: 'Новые схемы инструментов применяются к новым ходам.',
|
||
reloadFailed: 'Не удалось перезагрузить MCP',
|
||
savedTitle: 'MCP-сервер сохранён',
|
||
savedMessage: name => `${name} применится после перезагрузки MCP.`,
|
||
newServer: 'Новый сервер',
|
||
reload: 'Перезагрузить MCP',
|
||
reloading: 'Перезагрузка…',
|
||
emptyTitle: 'MCP-серверов нет',
|
||
emptyDesc: 'Добавьте stdio- или HTTP-сервер, чтобы получить инструменты MCP.',
|
||
disabled: 'отключён',
|
||
editServer: 'Изменить сервер',
|
||
name: 'Имя',
|
||
serverJson: 'JSON сервера',
|
||
remove: 'Удалить',
|
||
saveServer: 'Сохранить сервер',
|
||
test: 'Проверить соединение',
|
||
testing: 'Проверка…',
|
||
testOk: count =>
|
||
`Подключено — доступно ${count} ${RU_PLURAL(count, 'инструмент', 'инструмента', 'инструментов')}`,
|
||
testFailed: 'Не удалось подключиться',
|
||
enableServer: name => `Включить ${name}`,
|
||
disableServer: name => `Отключить ${name}`,
|
||
serverEnabled: name => `${name} включён — применится к новым сеансам.`,
|
||
serverDisabled: name => `${name} отключён — применится к новым сеансам.`,
|
||
toggleFailed: (name, enabled) => `Не удалось ${enabled ? 'включить' : 'отключить'} ${name}`,
|
||
tabServers: 'Серверы',
|
||
tabCatalog: 'Каталог',
|
||
catalogLoading: 'Загрузка каталога MCP…',
|
||
catalogLoadFailed: 'Не удалось загрузить каталог MCP',
|
||
catalogEmpty: 'Записей каталога нет.',
|
||
catalogInstalled: 'Установлен',
|
||
catalogEnabled: 'Включён',
|
||
catalogNeedsInstall: 'Нужна сборка',
|
||
catalogInstall: 'Установить',
|
||
catalogInstalling: 'Установка…',
|
||
catalogInstallStarted: name => `Установка ${name}… применится к новым сеансам после завершения.`,
|
||
catalogInstallFailed: name => `Не удалось установить ${name}`,
|
||
catalogEnvPrompt: name => `${name} требует учётные данные`,
|
||
catalogEnvRequired: 'Заполните обязательные значения перед установкой.',
|
||
capabilitySummary: (tools, prompts, resources) =>
|
||
`${[`${tools} ${RU_NOUN(tools, 'инструмент', 'инструмента', 'инструментов')}`, ...(prompts ? [`${prompts} ${RU_NOUN(prompts, 'промпт', 'промпта', 'промптов')}`] : []), ...(resources ? [`${resources} ${RU_NOUN(resources, 'ресурс', 'ресурса', 'ресурсов')}`] : [])].join(', ')} включено`,
|
||
costTokens: tokens => `~${tokens} ток/вызов`,
|
||
usage30d: uses => `${uses} ${RU_NOUN(uses, 'использование', 'использования', 'использований')}/30д`,
|
||
unusedPill: 'не используется',
|
||
statusConnecting: 'Подключение…',
|
||
statusNeedsAuth: 'Нужна аутентификация',
|
||
statusError: 'Ошибка',
|
||
statusOff: 'Выкл',
|
||
allServers: 'Все серверы',
|
||
authenticatedTitle: 'Аутентифицирован',
|
||
authenticatedMessage: (server, count) =>
|
||
`${server}: ${count} ${RU_PLURAL(count, 'инструмент', 'инструмента', 'инструментов')}`,
|
||
waitingForBrowser: 'Ожидание браузера…',
|
||
authenticate: 'Аутентифицироваться',
|
||
unsavedConnect: 'Не сохранено — сохраните mcp.json, чтобы подключиться.',
|
||
enableTool: tool => `Включить ${tool}`,
|
||
disableTool: tool => `Отключить ${tool}`,
|
||
noOutput: 'Вывода пока нет.',
|
||
deepLinkTitle: 'Добавить MCP-сервер?',
|
||
deepLinkDescription:
|
||
'Ссылка запросила добавить этот MCP-сервер в Hermes. Проверьте конфигурацию ниже — она пришла из ссылки, а не из Hermes.',
|
||
deepLinkStdioWarning:
|
||
'Этот сервер запускает локальный процесс на вашей машине командой, показанной ниже. Продолжайте только если доверяете источнику.',
|
||
deepLinkConfirm: 'Добавить сервер',
|
||
deepLinkNameInvalid: 'Имя: 1–64 символа — буквы, цифры, точки, дефисы или подчёркивания.',
|
||
deepLinkNameConflict: name => `Сервер с именем ${name} уже существует — выберите другое имя или отмените.`,
|
||
deepLinkErrorTitle: 'Ссылка установки MCP отклонена',
|
||
deepLinkErrorName: 'Имя сервера в ссылке отсутствует или некорректно.',
|
||
deepLinkErrorConfig: 'Конфигурация в ссылке не является корректным JSON в base64.',
|
||
deepLinkErrorShape: 'Конфигурация должна быть JSON-объектом со строковым полем `url` или `command`.',
|
||
deepLinkErrorUrl: 'Разрешены только URL серверов http:// и https://.',
|
||
deepLinkErrorTooLarge: 'Пакет конфигурации превышает лимит 32 КБ.',
|
||
importButton: 'Импортировать',
|
||
importPlaceholder:
|
||
'Вставьте фрагмент mcp.json, команду npx/docker, строку claude mcp add, URL или ссылку Cursor…',
|
||
importNoMatch: 'В вставленном тексте не распознана конфигурация сервера.',
|
||
importConfirm: 'Добавить в mcp.json',
|
||
importConfirmMany: count => `Добавить ${count} ${RU_PLURAL(count, 'сервер', 'сервера', 'серверов')} в mcp.json`
|
||
},
|
||
model: {
|
||
loading: 'Загрузка конфигурации модели…',
|
||
appliesDesc:
|
||
'Применяется к новым сеансам. Для горячей смены модели в активном чате используйте выборщик модели в композере.',
|
||
provider: 'Провайдер',
|
||
model: 'Модель',
|
||
applying: 'Применение…',
|
||
defaultsLabel: 'По умолчанию',
|
||
reasoning: 'Рассуждения',
|
||
reasoningOff: 'Выкл',
|
||
defaultsFailed: 'Не удалось сохранить модель по умолчанию',
|
||
auxiliaryTitle: 'Вспомогательные модели',
|
||
resetAllToMain: 'Сбросить всё на основную',
|
||
auxiliaryDesc:
|
||
'Вспомогательные задачи по умолчанию выполняются основной моделью. Назначьте отдельную модель любой задаче, чтобы переопределить.',
|
||
setToMain: 'На основную',
|
||
change: 'Изменить',
|
||
autoUseMain: 'авто · использовать основную модель',
|
||
providerDefault: '(по умолчанию провайдера)',
|
||
fallbackAdd: 'Добавить запасную',
|
||
fallbackEmpty: 'Запасных моделей нет — используется модель по умолчанию, если она не падает.',
|
||
notInCatalog: 'нет в списке моделей этого провайдера — вызовы могут уходить на запасную.',
|
||
tasks: {
|
||
vision: { label: 'Зрение', hint: 'Анализ изображений' },
|
||
web_extract: { label: 'Веб-извлечение', hint: 'Суммаризация страниц' },
|
||
compression: { label: 'Сжатие', hint: 'Компрессия контекста' },
|
||
skills_hub: { label: 'Хаб навыков', hint: 'Поиск навыков' },
|
||
approval: { label: 'Одобрение', hint: 'Умное авто-одобрение' },
|
||
mcp: { label: 'MCP', hint: 'Маршрутизация MCP-инструментов' },
|
||
title_generation: { label: 'Ген. заголовка', hint: 'Заголовки сеансов' },
|
||
curator: { label: 'Куратор', hint: 'Просмотр использования навыков' }
|
||
}
|
||
},
|
||
providers: {
|
||
connectAccount: 'Подключить аккаунт',
|
||
haveApiKey: 'Ввести API-ключ вместо этого?',
|
||
intro:
|
||
'Войдите по подписке — копировать API-ключ не нужно. Hermes проведёт вход в браузере прямо здесь, в приложении.',
|
||
connected: 'Подключено',
|
||
collapse: 'Свернуть',
|
||
connectAnother: 'Подключить другой провайдер',
|
||
otherProviders: 'Другие провайдеры',
|
||
disconnect: 'Отключить',
|
||
disconnectInTerminal: 'Отключить (выполнит команду удаления в терминале)',
|
||
removeConfirm: provider => `Удалить ${provider}?`,
|
||
removeExternalGeneric: provider => `${provider} управляется собственным CLI — удалите его там.`,
|
||
removeKeyManaged: provider => `${provider} настроен по API-ключу. Удалите его в разделе API-ключи.`,
|
||
removeTerminalConfirm: (provider, command) =>
|
||
`Отключить ${provider}? В терминале будет выполнена команда "${command}" для сброса учётных данных.`,
|
||
removeTerminalRunning: provider => `Выполняется отключение ${provider} в терминале…`,
|
||
removedTitle: 'Аккаунт удалён',
|
||
removedMessage: provider => `${provider} удалён.`,
|
||
failedRemove: provider => `Не удалось удалить ${provider}`,
|
||
noProviderKeys: 'API-ключи провайдеров недоступны.',
|
||
searchKeys: 'Поиск провайдеров…',
|
||
noKeysMatch: 'Провайдеры, подходящие под поиск, не найдены.',
|
||
localEndpoint: {
|
||
title: 'Локальный / свой эндпоинт',
|
||
description: 'Направьте Hermes на любой OpenAI-совместимый эндпоинт (Zyphra, vLLM, llama.cpp, Ollama и т. д.).'
|
||
},
|
||
loading: 'Загрузка провайдеров…'
|
||
},
|
||
sessions: {
|
||
loading: 'Загрузка архивных сеансов…',
|
||
archivedTitle: 'Архивные сеансы',
|
||
archivedIntro:
|
||
'Архивированные чаты скрыты из боковой панели, но сохраняют все сообщения. Чтобы архивировать чат из боковой панели — Ctrl/⌘-клик по нему.',
|
||
emptyArchivedTitle: 'Архив пуст',
|
||
emptyArchivedDesc: 'Архивируйте чат, чтобы скрыть его отсюда.',
|
||
unarchive: 'Восстановить',
|
||
deletePermanently: 'Удалить безвозвратно',
|
||
messages: count => `${count} ${RU_PLURAL(count, 'сообщение', 'сообщения', 'сообщений')}`,
|
||
restored: 'Восстановлено',
|
||
deleteConfirm: title => `Безвозвратно удалить «${title}»? Это действие необратимо.`,
|
||
autoArchiveTitle: 'Авто-архивация старых чатов',
|
||
autoArchiveDesc:
|
||
'Автоматически архивировать чаты, к которым вы давно не возвращались. Закреплённые чаты никогда не архивируются, ничего не удаляется — архивные чаты просто переезжают сюда.',
|
||
autoArchiveDaysLabel: 'Архивировать через',
|
||
autoArchiveDaysUnit: 'дн. бездействия',
|
||
autoArchiveFailed: 'Не удалось обновить авто-архивацию',
|
||
defaultDirTitle: 'Папка проекта по умолчанию',
|
||
defaultDirDesc:
|
||
'Новые сеансы начинаются в этой папке, если вы не выбрали другую. Оставьте пустым, чтобы использовать домашнюю директорию.',
|
||
defaultDirUpdated:
|
||
'Папка проекта по умолчанию обновлена — начните новый чат (Ctrl/⌘+N), чтобы она вступила в силу',
|
||
defaultsTo: label => `По умолчанию: ${label}.`,
|
||
change: 'Изменить',
|
||
choose: 'Выбрать',
|
||
clear: 'Очистить',
|
||
notSet: 'Не задано',
|
||
failedLoad: 'Не удалось загрузить архивные сеансы',
|
||
unarchiveFailed: 'Не удалось восстановить',
|
||
deleteFailed: 'Не удалось удалить',
|
||
updateDirFailed: 'Не удалось обновить папку по умолчанию',
|
||
clearDirFailed: 'Не удалось очистить папку по умолчанию'
|
||
},
|
||
toolsets: {
|
||
loadingConfig: 'Загрузка конфигурации',
|
||
savedTitle: 'Учётные данные сохранены',
|
||
savedMessage: key => `${key} обновлён.`,
|
||
removedTitle: 'Учётные данные удалены',
|
||
removedMessage: key => `${key} удалён.`,
|
||
failedSave: key => `Не удалось сохранить ${key}`,
|
||
failedRemove: key => `Не удалось удалить ${key}`,
|
||
failedReveal: key => `Не удалось показать ${key}`,
|
||
removeConfirm: key => `Удалить ${key} из .env?`,
|
||
set: 'Установить',
|
||
notSet: 'Не задано',
|
||
selectedTitle: 'Провайдер выбран',
|
||
selectedMessage: provider => `Сейчас активен ${provider}.`,
|
||
failedSelect: provider => `Не удалось выбрать ${provider}`,
|
||
failedLoad: 'Не удалось загрузить конфигурацию инструментов',
|
||
noProviderOptions:
|
||
'У этого набора инструментов нет вариантов провайдера — включите его, и он будет работать с вашей текущей конфигурацией.',
|
||
noProviders: 'Для этого набора инструментов сейчас нет доступных провайдеров.',
|
||
ready: 'Готово',
|
||
needsSignIn: 'Нужен вход',
|
||
needsSetup: 'Требуется настройка',
|
||
activeBackend: 'Активен',
|
||
activeBackendHint: 'Это ваш активный бэкенд',
|
||
useBackend: 'Использовать этот бэкенд',
|
||
nousIncluded: 'Входит в подписку Nous — войдите в Nous Portal, чтобы активировать.',
|
||
nousAuthNeededTitle: 'Войдите в Nous Portal',
|
||
nousAuthNeededMessage: provider => `${provider} сохранён, но не активируется, пока вы не войдёте в Nous Portal.`,
|
||
nousAuthSignIn: 'Войти',
|
||
nousAuthDoneTitle: 'Nous Portal подключён',
|
||
nousAuthDoneMessage: 'Ваши бэкенды по подписке теперь активны.',
|
||
nousAuthFailed: 'Вход в Nous Portal не завершён',
|
||
noApiKeyRequired: 'API-ключ не требуется.',
|
||
postSetupHint: step =>
|
||
`Этому бэкенду нужна однократная установка (${step}). Выполняется на этой машине — может занять несколько минут.`,
|
||
postSetupInstalledHint: 'Установлено. Повторите настройку, только если что-то сломано.',
|
||
postSetupRun: 'Запустить настройку',
|
||
postSetupRerun: 'Повторить настройку',
|
||
postSetupInstalled: 'Установлено',
|
||
postSetupRunning: 'Установка…',
|
||
postSetupStarting: 'Запуск…',
|
||
postSetupCompleteTitle: 'Настройка завершена',
|
||
postSetupCompleteMessage: step => `${step} установлен.`,
|
||
postSetupErrorTitle: 'Настройка завершилась с ошибками',
|
||
postSetupErrorMessage: step => `Посмотрите журнал ${step}.`,
|
||
postSetupFailed: step => `Не удалось выполнить настройку ${step}`,
|
||
webSearchActive: backend => `Поиск: ${backend}`,
|
||
webExtractActive: backend => `Извлечение: ${backend}`,
|
||
webCapabilityUnset: 'не задано',
|
||
webUseForSearch: 'Использовать для поиска',
|
||
webUseForExtract: 'Использовать для извлечения',
|
||
webUsedForSearch: 'Бэкенд поиска',
|
||
webUsedForExtract: 'Бэкенд извлечения',
|
||
webCapabilitySelectedMessage: (provider, capability) => `${provider} теперь отвечает за веб-${capability}.`,
|
||
failedSelectCapability: provider => `Не удалось настроить ${provider}`,
|
||
loadingModels: 'Загрузка каталога моделей…',
|
||
modelSectionTitle: 'Модель',
|
||
modelCount: count => `${count} ${RU_PLURAL(count, 'модель', 'модели', 'моделей')}`,
|
||
modelInUse: 'В использовании',
|
||
modelDefault: 'по умолчанию',
|
||
modelInactiveHint: 'Сначала выберите этот бэкенд, чтобы изменить его модель.',
|
||
modelSelectedTitle: 'Модель выбрана',
|
||
modelSelectedMessage: model => `${model} применится к новым сеансам.`,
|
||
failedSelectModel: model => `Не удалось выбрать ${model}`,
|
||
terminalBackend: {
|
||
sectionTitle: 'Бэкенд выполнения',
|
||
loading: 'Проверка бэкендов выполнения…',
|
||
failedLoad: 'Не удалось загрузить бэкенды терминала',
|
||
ready: 'Готово',
|
||
needsSetup: 'Нужна настройка',
|
||
unavailable: 'Недоступен',
|
||
inUse: 'В использовании',
|
||
selectedTitle: 'Бэкенд выбран',
|
||
selectedMessage: backend =>
|
||
`Команды терминала теперь выполняются через ${backend}. Применится к новым сеансам.`,
|
||
failedSelect: backend => `Не удалось выбрать ${backend}`,
|
||
needsSetupHint: 'Этот бэкенд можно выбрать сейчас — команды будут падать, пока настройка не завершена.'
|
||
}
|
||
}
|
||
},
|
||
skills: {
|
||
tabSkills: 'Навыки',
|
||
tabToolsets: 'Инструменты',
|
||
configuringProfile: 'Настраивается:',
|
||
tabMcp: 'MCP',
|
||
all: 'Все',
|
||
searchSkills: 'Поиск навыков...',
|
||
searchToolsets: 'Поиск инструментов...',
|
||
refresh: 'Обновить навыки',
|
||
refreshing: 'Обновление навыков',
|
||
loading: 'Загрузка возможностей...',
|
||
noSkillsTitle: 'Навыки не найдены',
|
||
noSkillsDesc: 'Попробуйте более широкий поиск или другую категорию.',
|
||
noToolsetsTitle: 'Toolsets не найдены',
|
||
noToolsetsDesc: 'Попробуйте более широкий запрос.',
|
||
noDescription: 'Без описания.',
|
||
configured: 'Настроено',
|
||
needsKeys: 'Нужны ключи',
|
||
visionModelHint:
|
||
'Зрение использует вашу конфигурацию вспомогательной модели — модель с поддержкой изображений выбирается там, а не здесь по провайдеру.',
|
||
visionModelLink: 'Выбрать модель зрения в Настройки → Модели',
|
||
toolsetsEnabled: (enabled, total) => `Включено наборов инструментов: ${enabled}/${total}`,
|
||
configureToolset: label => `Настроить ${label}`,
|
||
toggleToolset: (label, enabled) => `${enabled ? 'Включить' : 'Отключить'} набор инструментов ${label}`,
|
||
skillsLoadFailed: 'Не удалось загрузить навыки',
|
||
toolsetsRefreshFailed: 'Не удалось обновить наборы инструментов',
|
||
skillEnabled: 'Навык включён',
|
||
skillDisabled: 'Навык отключён',
|
||
toolsetEnabled: 'Набор инструментов включён',
|
||
toolsetDisabled: 'Набор инструментов отключён',
|
||
appliesToNewSessions: name => `${name} применится к новым сеансам.`,
|
||
failedToUpdate: name => `Не удалось обновить ${name}`,
|
||
sortMostUsed: 'Самые используемые',
|
||
sortAlpha: 'А–Я',
|
||
sortMostUsedDesc: '↓ Самые используемые',
|
||
sortLeastUsedAsc: '↑ Меньше всего используемые',
|
||
enableAll: 'Включить все',
|
||
disableAll: 'Отключить все',
|
||
disableUnused: 'Отключить неиспользуемые',
|
||
bulkUpdated: count => `Обновлено ${count} ${RU_NOUN(count, 'элемент', 'элемента', 'элементов')} для новых сеансов.`,
|
||
bulkNoChange: 'Менять нечего.',
|
||
usageCount: count => `использован ${count}×`,
|
||
provenance: {
|
||
agent: 'Научен',
|
||
bundled: 'Встроенный',
|
||
hub: 'Хаб'
|
||
},
|
||
emptyNoneFound: noun => `Не найдено: ${noun}`,
|
||
emptyNothingMatches: query => `Ничего не подходит под «${query}».`,
|
||
emptyNoneAvailable: noun => `${noun} пока недоступны.`,
|
||
changesApplyNewSessions: 'Изменения применяются к новым сеансам.',
|
||
skillUpdated: 'Навык обновлён',
|
||
edit: 'Изменить',
|
||
archive: 'В архив',
|
||
skillArchivedTitle: 'Навык в архиве',
|
||
skillArchivedMessage: 'Восстановить через hermes curator restore.',
|
||
hub: {
|
||
searchPlaceholder: 'Поиск в хабе навыков',
|
||
search: 'Поиск',
|
||
searching: 'Поиск...',
|
||
connectingHubs: 'Подключение к хабам навыков...',
|
||
connectedHubs: 'Подключённые хабы:',
|
||
featured: 'Избранные навыки',
|
||
landingHint:
|
||
'Ищите в хабе, чтобы просматривать устанавливаемые навыки из официального индекса, GitHub и источников сообщества.',
|
||
noResults: 'Совпадающие навыки в хабе не найдены.',
|
||
resultCount: (count, ms) =>
|
||
`${count} ${RU_PLURAL(count, 'результат', 'результата', 'результатов')}${ms !== null ? ` за ${ms}мс` : ''}`,
|
||
timedOut: sources => `Тайм-аут: ${sources}`,
|
||
installed: 'Установлен',
|
||
install: 'Установить',
|
||
installing: 'Установка...',
|
||
uninstall: 'Удалить',
|
||
uninstalling: 'Удаление...',
|
||
updateAll: 'Обновить установленные',
|
||
updating: 'Обновление...',
|
||
preview: 'Предпросмотр',
|
||
scan: 'Сканировать',
|
||
scanning: 'Сканирование...',
|
||
close: 'Закрыть',
|
||
files: 'Файлы',
|
||
noReadme: 'Для этого навыка нет предпросмотра SKILL.md.',
|
||
trust: {
|
||
builtin: 'встроенный',
|
||
trusted: 'доверенный',
|
||
community: 'сообщество'
|
||
},
|
||
verdictSafe: 'Безопасен',
|
||
verdictCaution: 'Осторожно',
|
||
verdictDangerous: 'Опасен',
|
||
policyAllow: 'Установка разрешена',
|
||
policyAsk: 'Проверьте перед установкой',
|
||
policyBlock: 'Установка заблокирована политикой',
|
||
findings: count => `${count} ${RU_NOUN(count, 'находка', 'находки', 'находок')}`,
|
||
noFindings: 'Находок безопасности нет.',
|
||
installStarted: name => `Установка ${name}...`,
|
||
uninstallStarted: name => `Удаление ${name}...`,
|
||
updateStarted: 'Обновление установленных навыков...',
|
||
actionFailed: 'Действие с навыком не удалось',
|
||
actionLog: 'Журнал действий',
|
||
alreadyInstalled: name => `«${name}» уже установлен`,
|
||
pickerTitle: 'Хаб навыков',
|
||
pickerBrowse: 'Открыть весь хаб',
|
||
pickerHide: 'Скрыть браузер хаба',
|
||
pickerHint: 'Нажмите «+ Добавить к этому агенту» на любом навыке — он установится и появится в списке выше.',
|
||
loadFailed: 'Не удалось загрузить хаб навыков',
|
||
previewFailed: 'Не удалось получить предпросмотр навыка',
|
||
scanFailed: 'Не удалось выполнить проверку безопасности',
|
||
searchFailed: 'Поиск в хабе не удался'
|
||
}
|
||
},
|
||
starmap: {
|
||
title: 'Граф памяти',
|
||
subtitle: (nodes, clusters) =>
|
||
`${nodes} ${RU_NOUN(nodes, 'навык', 'навыка', 'навыков')} в ${clusters} ${RU_NOUN(clusters, 'категория', 'категории', 'категорий')}`,
|
||
close: 'Закрыть граф памяти',
|
||
refresh: 'Обновить',
|
||
memory: 'Память',
|
||
filterAll: 'Все',
|
||
filterUsed: 'Использованные',
|
||
filterLearned: 'Наученные',
|
||
viewGraph: 'Граф',
|
||
loadFailed: 'Не удалось загрузить граф памяти',
|
||
loading: 'Загрузка…',
|
||
emptyTitle: 'Пока ничего не изучено',
|
||
emptyDesc: 'По мере того как Hermes создаёт навыки и память для вашей работы, они появятся здесь.',
|
||
share: 'Поделиться картой',
|
||
shareHint:
|
||
'Скопируйте код, чтобы поделиться этой картой, или вставьте код для загрузки. Включает только раскладку, а не вашу память или текст навыков.',
|
||
shareTitle: 'Импорт / экспорт карты',
|
||
sharePlaceholder: 'Вставьте код карты…',
|
||
copy: 'Скопировать код карты',
|
||
copied: 'Скопировано!',
|
||
importMap: 'Импортировать карту',
|
||
importBtn: 'Загрузить',
|
||
importEmpty: 'Вставьте код карты для загрузки.',
|
||
importSuccess: nodes => `Загружена карта с ${nodes} ${RU_NOUN(nodes, 'узлом', 'узла', 'узлов')}.`,
|
||
importedBadge: 'импортированная карта',
|
||
resetToMine: 'Вернуться к моей карте'
|
||
},
|
||
agents: {
|
||
extendedTranscript: 'Подробный журнал',
|
||
transcriptTruncated: 'Последние 16 КиБ',
|
||
transcriptUnavailable: 'Текущий журнал недоступен',
|
||
|
||
close: 'Закрыть агентов',
|
||
title: 'Дерево запусков',
|
||
subtitle: 'Активные субагенты текущего хода в реальном времени.',
|
||
emptyTitle: 'Нет активных субагентов',
|
||
emptyDesc: 'Когда ход делегирует работу, дочерние агенты стримят свой прогресс сюда.',
|
||
running: 'Выполняется',
|
||
failed: 'Ошибка',
|
||
done: 'Готово',
|
||
streaming: 'Стримится',
|
||
files: 'Файлы',
|
||
moreFiles: count => `+ещё ${count} ${RU_NOUN(count, 'файл', 'файла', 'файлов')}`,
|
||
moreAgents: count => `Ещё ${count} агентов`,
|
||
queued: 'В очереди',
|
||
waitingActivity: 'Ожидание активности',
|
||
steer: 'Направить',
|
||
steerPlaceholder: 'Инструкции этому субагенту',
|
||
steerQueued: 'В очереди до следующей контрольной точки',
|
||
stopRequested: 'Запрошена остановка',
|
||
requestRejected: 'Субагент не принял запрос',
|
||
delegation: index => `Делегирование ${index}`,
|
||
workers: count => `${count} ${RU_NOUN(count, 'воркер', 'воркера', 'воркеров')}`,
|
||
workersActive: count => `${count} ${RU_NOUN(count, 'активен', 'активно', 'активных')}`,
|
||
agentsCount: count => `${count} ${RU_PLURAL(count, 'агент', 'агента', 'агентов')}`,
|
||
activeCount: count => `${count} ${RU_NOUN(count, 'активен', 'активно', 'активных')}`,
|
||
failedCount: count => `${count} ${RU_NOUN(count, 'с ошибкой', 'с ошибками', 'с ошибками')}`,
|
||
toolsCount: count => `${count} ${RU_NOUN(count, 'инструмент', 'инструмента', 'инструментов')}`,
|
||
filesCount: count => `${count} ${RU_NOUN(count, 'файл', 'файла', 'файлов')}`,
|
||
updatedAgo: age => `обновлено ${age}`,
|
||
ageNow: 'только что',
|
||
ageSeconds: seconds => `${seconds}с назад`,
|
||
ageMinutes: minutes => `${minutes}м назад`,
|
||
ageHours: hours => `${hours}ч назад`,
|
||
ageDays: days => `${days}д назад`,
|
||
durationSeconds: seconds => `${seconds}с`,
|
||
durationMinutes: (minutes, seconds) => `${minutes}м ${seconds}с`,
|
||
tokens: value => `${value} ток`
|
||
},
|
||
commandCenter: {
|
||
close: 'Закрыть командный центр',
|
||
paletteTitle: 'Палитра команд',
|
||
back: 'Назад',
|
||
searchPlaceholder: 'Поиск сеансов, представлений и действий',
|
||
goTo: 'Перейти',
|
||
goToSession: 'Перейти к сеансу',
|
||
branches: 'Ветви',
|
||
projects: 'Проекты',
|
||
openFolder: 'Открыть папку как проект…',
|
||
openFolderAt: path => `Открыть папку как проект — ${path}`,
|
||
newSessionInProject: project => `Новый сеанс в ${project}`,
|
||
commands: 'Команды',
|
||
startInBranch: branch => `Новый диалог в ${branch}`,
|
||
commandCenter: 'Командный центр',
|
||
appearance: 'Внешний вид',
|
||
settings: 'Настройки',
|
||
changeTheme: 'Сменить тему',
|
||
changeColorMode: 'Сменить цветовой режим…',
|
||
pets: {
|
||
title: 'Питомцы',
|
||
placeholder: 'Поиск питомцев…',
|
||
loading: 'Загрузка галереи petdex…',
|
||
error: 'Не удалось подключиться к галерее petdex.',
|
||
staleBackend: 'Перезапустите Hermes, чтобы использовать питомцев — бэкенд старше этой функции.',
|
||
empty: 'Совпадающих питомцев нет.',
|
||
turnOff: 'Отключить',
|
||
turnOn: 'Включить',
|
||
installed: 'Установлен',
|
||
generatedTag: 'Сгенерирован',
|
||
adoptFailed: 'Не удалось усыновить этого питомца.',
|
||
toggleFailed: enabled => `Не удалось ${enabled ? 'включить' : 'отключить'} питомца.`,
|
||
noneAvailable: 'Питомцев пока нет — выберите ниже для установки.'
|
||
},
|
||
generatePet: {
|
||
title: 'Сгенерировать питомца',
|
||
placeholder: 'Опишите питомца для генерации…',
|
||
promptHint: 'Введите описание и нажмите Enter, чтобы получить четыре варианта облика.',
|
||
readyHint: 'Нажмите Enter, чтобы получить четыре варианта облика по вашему описанию.',
|
||
generate: 'Сгенерировать',
|
||
generating: 'Генерация…',
|
||
retry: 'Повторить',
|
||
hatch: 'Вылупить',
|
||
spawning: 'Создаём…',
|
||
hatching: 'Вылупливаем вашего питомца…',
|
||
hatchingSub: 'Оживляем его…',
|
||
hatched: 'Он вылупился!',
|
||
hatchRow: (_state, done, total) => `Рисуем кадр ${done} из ${total}…`,
|
||
hatchComposing: 'Собираем по частям…',
|
||
hatchSaving: 'Почти готово…',
|
||
namePlaceholder: 'Имя для вашего питомца',
|
||
staleBackend: 'Обновите Hermes, чтобы генерировать питомцев.',
|
||
backgroundHint: 'Можно закрыть — Hermes уведомит, когда будет готово.',
|
||
slowProviderHint: 'Это может занять несколько минут',
|
||
remix: 'Ремикс',
|
||
remixConfirmTitle: 'Сделать ремикс из этого облика?',
|
||
remixConfirmBody:
|
||
'Будет сгенерирован новый набор вариантов с этим как отправной точкой. Это может занять несколько минут.',
|
||
genericError: 'Генерация не удалась — попробуйте снова или выберите подсказку.',
|
||
referenceImageTooLarge: 'Изображение-референс слишком большое. Используйте меньше 16 МБ.',
|
||
referenceImageInvalid: 'Не удалось прочитать это изображение-референс. Попробуйте PNG, JPG, WebP или GIF.',
|
||
adopt: 'Усыновить',
|
||
startOver: 'Начать заново'
|
||
},
|
||
installTheme: {
|
||
title: 'Установить тему…',
|
||
pageTitle: 'Установка темы',
|
||
placeholder: 'Поиск в VS Code Marketplace...',
|
||
loading: 'Поиск в Marketplace...',
|
||
error: 'Не удалось подключиться к Marketplace.',
|
||
empty: 'Совпадающих тем нет.',
|
||
install: 'Установить',
|
||
installing: 'Установка...',
|
||
installed: 'Установлена',
|
||
installs: count => `${count} ${RU_NOUN(count, 'установка', 'установки', 'установок')}`
|
||
},
|
||
settingsFields: 'Поля настроек',
|
||
mcpServers: 'MCP-серверы',
|
||
archivedChats: 'Архивные чаты',
|
||
sections: { maintenance: 'Обслуживание', sessions: 'Сеансы', system: 'Система', usage: 'Использование' },
|
||
sectionDescriptions: {
|
||
maintenance: 'Диагностика, резервные копии, курир и данные памяти',
|
||
sessions: 'Поиск и управление сеансами',
|
||
system: 'Статус, журналы и системные действия',
|
||
usage: 'Токены, стоимость и активность навыков со временем'
|
||
},
|
||
nav: {
|
||
newChat: { title: 'Новый сеанс', detail: 'Начать новый сеанс' },
|
||
settings: { title: 'Настройки', detail: 'Настройка Hermes desktop' },
|
||
skills: { title: 'Возможности', detail: 'Навыки, инструменты и MCP-серверы' },
|
||
messaging: { title: 'Сообщения', detail: 'Настройка Telegram, Slack, Discord и других' },
|
||
artifacts: { title: 'Артефакты', detail: 'Просмотр сгенерированных результатов' }
|
||
},
|
||
sectionEntries: {
|
||
sessions: { title: 'Панель сеансов', detail: 'Поиск, закрепление и управление сеансами' },
|
||
system: { title: 'Системная панель', detail: 'Статус шлюза, журналы, перезапуск/обновление' },
|
||
usage: { title: 'Панель использования', detail: 'Токены, стоимость и активность навыков' }
|
||
},
|
||
providerNavigate: 'Перейти',
|
||
providerSessions: 'Сеансы',
|
||
refresh: 'Обновить',
|
||
refreshing: 'Обновление...',
|
||
noResults: 'Совпадающие результаты не найдены.',
|
||
pinSession: 'Закрепить сеанс',
|
||
unpinSession: 'Открепить сеанс',
|
||
exportSession: 'Экспортировать сеанс',
|
||
deleteSession: 'Удалить сеанс',
|
||
noSessions: 'Сеансов пока нет.',
|
||
gatewayRunning: 'Шлюз сообщений работает',
|
||
gatewayStopped: 'Шлюз сообщений остановлен',
|
||
hermesActiveSessions: (version, count) => `Hermes ${version} · Активные сеансы: ${count}`,
|
||
restartGateway: 'Перезапустить шлюз',
|
||
openBrowser: 'Открыть браузер',
|
||
gatewayRestartFailed: 'Не удалось перезапустить шлюз.',
|
||
updateHermes: 'Обновить Hermes',
|
||
reloadWindow: 'Перезагрузить окно',
|
||
actionRunning: 'выполняется',
|
||
actionDone: 'готово',
|
||
actionFailed: 'ошибка',
|
||
actionStartedWaiting: 'Действие запущено, ожидание статуса...',
|
||
loadingStatus: 'Загрузка статуса...',
|
||
recentLogs: 'Последние записи журнала',
|
||
noLogs: 'Журналы ещё не загружены.',
|
||
days: count => `${count}д`,
|
||
statSessions: 'Сеансы',
|
||
statApiCalls: 'Вызовы API',
|
||
statTokens: 'Токены вход/выход',
|
||
statCost: 'Оценка стоимости',
|
||
actualCost: cost => `фактически ${cost}`,
|
||
loadingUsage: 'Загрузка использования...',
|
||
noUsage: period => `Нет использования за последние ${period} ${RU_NOUN(period, 'день', 'дня', 'дней')}.`,
|
||
retry: 'Повторить',
|
||
dailyTokens: 'Токены за день',
|
||
input: 'вход',
|
||
output: 'выход',
|
||
noDailyActivity: 'Ежедневной активности нет.',
|
||
topModels: 'Топ моделей',
|
||
noModelUsage: 'Использование моделей пока отсутствует.',
|
||
topSkills: 'Топ навыков',
|
||
noSkillActivity: 'Активности навыков пока нет.',
|
||
actions: count => `${count} ${RU_NOUN(count, 'действие', 'действия', 'действий')}`,
|
||
logFile: 'Файл журнала',
|
||
logLevel: 'Уровень',
|
||
logSearchPlaceholder: 'Фильтр строк журнала...',
|
||
maintenance: {
|
||
runOps: 'Диагностика',
|
||
doctor: 'Запустить doctor',
|
||
doctorDesc: 'Проверка здоровья установки, конфигурации и провайдеров',
|
||
securityAudit: 'Аудит безопасности',
|
||
securityAuditDesc: 'Сканирование конфигурации и навыков на предмет рискованных настроек',
|
||
backup: 'Создать резервную копию',
|
||
backupDesc: 'Сжатие конфигурации, памяти, навыков и сеансов в zip',
|
||
debugShare: 'Поделиться отладкой',
|
||
debugShareDesc: 'Загрузка анонимизированного отчёта + журналов, получение ссылок (автоудаление через 6 ч)',
|
||
debugShareRunning: 'Загрузка отладочного отчёта...',
|
||
debugShareLinks: 'Ссылки для шаринга',
|
||
debugShareFailed: 'Ошибка шаринга отладки',
|
||
copyLink: 'Скопировать ссылку',
|
||
linkCopied: 'Ссылка скопирована',
|
||
curator: 'Курир навыков',
|
||
curatorDesc: 'Фоновый обзор, архивирующий устаревшие навыки, созданные агентом',
|
||
curatorPaused: 'Приостановлен',
|
||
curatorActive: 'Активен',
|
||
curatorDisabled: 'Отключён',
|
||
curatorLastRun: when => `Последний запуск ${when}`,
|
||
curatorNeverRan: 'Никогда не запускался',
|
||
pause: 'Приостановить',
|
||
resume: 'Продолжить',
|
||
runNow: 'Запустить сейчас',
|
||
memoryData: 'Данные памяти',
|
||
memoryDataDesc: 'Встроенные файлы памяти, внедряемые в каждый сеанс',
|
||
memoryProvider: name => `Активный провайдер: ${name}`,
|
||
builtinMemory: 'встроенный',
|
||
memoryFile: 'Память агента (MEMORY.md)',
|
||
userFile: 'Профиль пользователя (USER.md)',
|
||
bytes: size => size,
|
||
empty: 'пусто',
|
||
resetMemory: 'Сбросить память',
|
||
resetUser: 'Сбросить профиль',
|
||
resetAll: 'Сбросить оба',
|
||
resetConfirm: target => `Удалить ${target}? Это действие необратимо.`,
|
||
resetDone: files => `Удалено: ${files}.`,
|
||
resetFailed: 'Не удалось сбросить память',
|
||
actionStarted: name => `${name} запущен — следим за журналом...`,
|
||
actionFailed: name => `Не удалось запустить ${name}`,
|
||
running: 'Выполняется...',
|
||
viewLog: 'Журнал действия'
|
||
}
|
||
},
|
||
messaging: {
|
||
search: 'Поиск в сообщениях...',
|
||
loading: 'Загрузка платформ сообщений...',
|
||
loadFailed: 'Не удалось загрузить платформы сообщений',
|
||
states: {
|
||
connected: 'Подключено',
|
||
connecting: 'Подключение',
|
||
disabled: 'Отключено',
|
||
fatal: 'Ошибка',
|
||
gateway_stopped: 'Шлюз сообщений остановлен',
|
||
not_configured: 'Нужна настройка',
|
||
pending_restart: 'Нужен перезапуск',
|
||
retrying: 'Повторная попытка',
|
||
startup_failed: 'Не удалось запустить'
|
||
},
|
||
unknown: 'Неизвестно',
|
||
hintPendingRestart: 'Перезапустите шлюз из строки состояния, чтобы применить это изменение.',
|
||
hintGatewayStopped: 'Запустите шлюз из строки состояния для подключения.',
|
||
credentialsSet: 'Учётные данные заданы',
|
||
needsSetup: 'Нужна настройка',
|
||
gatewayStopped: 'Шлюз сообщений остановлен',
|
||
getCredentials: 'Получить учётные данные',
|
||
openSetupGuide: 'Открыть руководство по настройке',
|
||
required: 'Обязательно',
|
||
recommended: 'Рекомендуется',
|
||
advanced: count => `Расширенные (${count})`,
|
||
noTokenNeeded: 'Этой платформе здесь не нужен токен. Используйте руководство выше, затем включите её ниже.',
|
||
enabled: 'Включено',
|
||
disabled: 'Отключено',
|
||
unsavedChanges: 'Несохранённые изменения',
|
||
saving: 'Сохранение...',
|
||
saveChanges: 'Сохранить изменения',
|
||
saved: 'Сохранено',
|
||
replaceValue: 'Заменить текущее значение',
|
||
openDocs: 'Открыть документацию',
|
||
clearField: key => `Очистить ${key}`,
|
||
enableAria: name => `Включить ${name}`,
|
||
disableAria: name => `Отключить ${name}`,
|
||
platformEnabled: name => `${name} включено`,
|
||
platformDisabled: name => `${name} отключено`,
|
||
restartToApply: 'Это изменение вступит в силу после перезапуска шлюза.',
|
||
setupSaved: name => `Настройка ${name} сохранена`,
|
||
restartToReconnect: 'Новые учётные данные вступят в силу после перезапуска шлюза.',
|
||
keyCleared: key => `${key} очищено`,
|
||
setupUpdated: name => `Настройка ${name} обновлена.`,
|
||
failedUpdate: name => `Не удалось обновить ${name}`,
|
||
failedSave: name => `Не удалось сохранить ${name}`,
|
||
failedClear: key => `Не удалось очистить ${key}`,
|
||
pendingRequests: count => `Ожидающие запросы (${count})`,
|
||
pendingAria: count =>
|
||
`${count} ${RU_NOUN(count, 'ожидающий запрос на сопряжение', 'ожидающих запроса на сопряжение', 'ожидающих запросов на сопряжение')}`,
|
||
approvedUsers: count => `Одобрённые пользователи (${count})`,
|
||
approve: 'Одобрить',
|
||
approving: 'Одобрение...',
|
||
revoke: 'Отозвать',
|
||
revoking: 'Отзыв...',
|
||
revokeAria: name => `Отозвать ${name}`,
|
||
revokeTitle: 'Отозвать доступ',
|
||
revokeDesc: name => `${name} потеряет доступ и перестанет распознаваться начиная со следующего сообщения.`,
|
||
approvedUser: name => `${name} одобрен`,
|
||
approvedHint: 'Они распознаются автоматически начиная с их следующего сообщения.',
|
||
revokedUser: name => `${name} отозван`,
|
||
failedApprove: name => `Не удалось одобрить ${name}`,
|
||
failedRevoke: name => `Не удалось отозвать ${name}`,
|
||
pairingLockedOut: 'Слишком много неудачных одобрений — эта платформа заблокирована. Попробуйте позже.',
|
||
waitingSince: minutes => (minutes < 1 ? 'только что' : `${minutes}м назад`),
|
||
restartNeeded: 'Сохранено. Перезапустите шлюз сообщений, чтобы применить новые настройки.',
|
||
restartNow: 'Перезапустить',
|
||
restarting: 'Перезапуск…',
|
||
restartFailedManual: 'Не удалось перезапустить шлюз — перезапустите его вручную и проверьте журналы.',
|
||
telegramQr: {
|
||
title: 'Выберите способ подключения Telegram-бота',
|
||
subtitle:
|
||
'Оба способа подключают бота под вашим контролем и сохраняют его данные только в этой установке Hermes.',
|
||
quickSetup: 'Быстрая настройка',
|
||
recommended: 'Рекомендуется',
|
||
quickHelp:
|
||
'Отсканируйте QR-код и подтвердите в Telegram. Hermes создаст бота и определит ваш Telegram ID автоматически.',
|
||
createWithQr: 'Создать по QR',
|
||
starting: 'Запуск…',
|
||
replaceWarning:
|
||
'Данные Telegram уже настроены. Новая QR-настройка или токен заменят текущего бота при сохранении.',
|
||
scanHint: 'Отсканируйте в приложении Telegram на телефоне или откройте ссылку на этом компьютере.',
|
||
waiting: 'Ожидание Telegram…',
|
||
expiresIn: remaining => `Истекает через ${remaining}`,
|
||
expired: 'Истёк',
|
||
openTelegram: 'Открыть Telegram',
|
||
ready: 'Бот создан',
|
||
allowedUsers: 'Разрешённые пользователи',
|
||
ownerDetected: 'Владелец определён',
|
||
addAtLeastOne: 'Добавьте хотя бы один Telegram ID.',
|
||
userIdPlaceholder: 'Telegram ID пользователя',
|
||
add: 'Добавить',
|
||
numericOnly: 'Telegram ID должны быть числовыми.',
|
||
saveAndRestart: 'Сохранить и перезапустить',
|
||
applying: 'Сохранение…',
|
||
pairingExpired: 'Срок QR-настройки истёк. Начните новую.',
|
||
stillWaiting: detail => `Всё ещё ждём Telegram. Повтор после: ${detail}`,
|
||
savedRestarting: 'Telegram сохранён; шлюз перезапускается…',
|
||
savedRestartFailed: detail => `Telegram сохранён; перезапуск шлюза не удался${detail}`
|
||
},
|
||
fieldCopy: {
|
||
TELEGRAM_BOT_TOKEN: {
|
||
label: 'Токен бота',
|
||
help: 'Создайте бота через @BotFather и вставьте выданный им токен.',
|
||
placeholder: 'Вставьте токен бота Telegram'
|
||
},
|
||
TELEGRAM_ALLOWED_USERS: {
|
||
label: 'Разрешённые ID пользователей Telegram',
|
||
help: 'Рекомендуется. Числовые ID через @userinfobot через запятую. Без этого писать вашему боту может кто угодно.'
|
||
},
|
||
TELEGRAM_PROXY: { label: 'URL прокси', help: 'Нужен только в сетях, где Telegram заблокирован.' },
|
||
DISCORD_BOT_TOKEN: {
|
||
label: 'Токен бота',
|
||
help: 'Создайте приложение в Discord Developer Portal, добавьте бота и вставьте его токен.'
|
||
},
|
||
DISCORD_ALLOWED_USERS: {
|
||
label: 'Разрешённые ID пользователей Discord',
|
||
help: 'Рекомендуется. ID пользователей Discord через запятую.'
|
||
},
|
||
DISCORD_REPLY_TO_MODE: { label: 'Стиль ответов', help: 'first, all или off.' },
|
||
DISCORD_ALLOW_ALL_USERS: {
|
||
label: 'Разрешить всех пользователей Discord',
|
||
help: 'Только для разработки. Если true, писать боту в ЛС может кто угодно без allowlist.'
|
||
},
|
||
DISCORD_HOME_CHANNEL: {
|
||
label: 'ID домашнего канала',
|
||
help: 'Канал, куда бот шлёт проактивные сообщения (результаты cron, напоминания).'
|
||
},
|
||
DISCORD_HOME_CHANNEL_NAME: {
|
||
label: 'Название домашнего канала',
|
||
help: 'Отображаемое имя домашнего канала в журналах и выводе статуса.'
|
||
},
|
||
BLUEBUBBLES_ALLOW_ALL_USERS: {
|
||
label: 'Разрешить всех пользователей iMessage',
|
||
help: 'Если true, allowlist BlueBubbles пропускается.'
|
||
},
|
||
MATTERMOST_ALLOW_ALL_USERS: { label: 'Разрешить всех пользователей Mattermost' },
|
||
MATTERMOST_HOME_CHANNEL: { label: 'Домашний канал' },
|
||
QQ_ALLOW_ALL_USERS: { label: 'Разрешить всех пользователей QQ' },
|
||
QQBOT_HOME_CHANNEL: { label: 'Домашний канал QQ', help: 'Канал или группа по умолчанию для доставки cron.' },
|
||
QQBOT_HOME_CHANNEL_NAME: { label: 'Название домашнего канала QQ' },
|
||
SLACK_BOT_TOKEN: {
|
||
label: 'Токен бота Slack',
|
||
help: 'Используйте токен бота из OAuth & Permissions после установки вашего приложения Slack.',
|
||
placeholder: 'Вставьте токен бота Slack'
|
||
},
|
||
SLACK_APP_TOKEN: {
|
||
label: 'Токен приложения Slack',
|
||
help: 'Используйте токен уровня приложения, необходимый для Socket Mode.',
|
||
placeholder: 'Вставьте токен приложения Slack'
|
||
},
|
||
SLACK_ALLOWED_USERS: {
|
||
label: 'Разрешённые ID пользователей Slack',
|
||
help: 'Рекомендуется. ID пользователей Slack через запятую.'
|
||
},
|
||
MATTERMOST_URL: { label: 'URL сервера', placeholder: 'https://mattermost.example.com' },
|
||
MATTERMOST_TOKEN: { label: 'Токен бота' },
|
||
MATTERMOST_ALLOWED_USERS: {
|
||
label: 'Разрешённые ID пользователей',
|
||
help: 'Рекомендуется. ID пользователей Mattermost через запятую.'
|
||
},
|
||
MATRIX_HOMESERVER: { label: 'URL homeserver', placeholder: 'https://matrix.org' },
|
||
MATRIX_ACCESS_TOKEN: { label: 'Токен доступа' },
|
||
MATRIX_USER_ID: { label: 'ID пользователя бота', placeholder: '@hermes:example.org' },
|
||
MATRIX_ALLOWED_USERS: {
|
||
label: 'Разрешённые ID пользователей Matrix',
|
||
help: 'Рекомендуется. ID пользователей через запятую в формате @user:server.'
|
||
},
|
||
SIGNAL_HTTP_URL: {
|
||
label: 'URL моста Signal',
|
||
placeholder: 'http://127.0.0.1:8080',
|
||
help: 'URL работающего REST-моста signal-cli.'
|
||
},
|
||
SIGNAL_ACCOUNT: { label: 'Номер телефона', help: 'Номер, зарегистрированный в вашем мосте signal-cli.' },
|
||
SIGNAL_ALLOWED_USERS: {
|
||
label: 'Разрешённые пользователи Signal',
|
||
help: 'Рекомендуется. Идентификаторы Signal через запятую.'
|
||
},
|
||
WHATSAPP_ENABLED: {
|
||
label: 'Включить мост WhatsApp',
|
||
help: 'Устанавливается автоматически переключателем ниже. Не меняйте, если точно не нужно.'
|
||
},
|
||
WHATSAPP_MODE: { label: 'Режим моста' },
|
||
WHATSAPP_ALLOWED_USERS: {
|
||
label: 'Разрешённые пользователи WhatsApp',
|
||
help: 'Рекомендуется. Номера телефонов или ID WhatsApp через запятую.'
|
||
}
|
||
},
|
||
platformIntro: {}
|
||
},
|
||
webhooks: {
|
||
search: 'Поиск вебхуков...',
|
||
loading: 'Загрузка вебхуков...',
|
||
loadFailed: 'Не удалось загрузить вебхуки',
|
||
subscriptions: count => `Подписки (${count})`,
|
||
hint: 'Изменения подписок применяются на лету, когда приёмник запущен. Отключённые подписки отклоняют входящие события.',
|
||
empty: 'Подписок вебхуков пока нет.',
|
||
disabledTitle: 'Приёмник вебхуков отключён',
|
||
disabledBody:
|
||
'Вебхуки — это отдельная платформа шлюза. Включите их здесь, чтобы принимать входящие HTTP-события; чат-каналы нужны только когда подписка доставляет в Telegram, Discord, Slack или другой канал.',
|
||
enable: 'Включить вебхуки',
|
||
enabling: 'Включение...',
|
||
enabled: name => `Включено: «${name}»`,
|
||
disabled: name => `Отключено: «${name}»`,
|
||
enableRow: 'Включить',
|
||
disableRow: 'Отключить',
|
||
delete: 'Удалить',
|
||
deleting: 'Удаление...',
|
||
deleted: 'Вебхук удалён',
|
||
deleteTitle: 'Удалить вебхук',
|
||
deleteDescPrefix: 'Это навсегда удалит ',
|
||
deleteDescSuffix: '. Это действие необратимо.',
|
||
deleteFailed: name => `Не удалось удалить «${name}»`,
|
||
toggleFailed: (name, enabled) => `Не удалось ${enabled ? 'включить' : 'отключить'} «${name}»`,
|
||
newSubscription: 'Новая подписка',
|
||
restarting: 'Перезапуск шлюза...',
|
||
restartNeeded: 'Вебхуки включены, но шлюз всё ещё нужно перезапустить, чтобы приёмник заработал.',
|
||
restartGateway: 'Перезапустить шлюз',
|
||
restartingGateway: 'Перезапуск...',
|
||
restartFailed: detail => `Не удалось перезапустить шлюз${detail}`,
|
||
enabledRestarting: 'Вебхуки включены; шлюз перезапускается...',
|
||
all: '(все)',
|
||
deliverOnly: 'только доставка',
|
||
createdTitle: 'Подписка создана',
|
||
createdSecretHint: 'Скопируйте секрет сейчас — он показывается только один раз.',
|
||
webhookUrl: 'URL вебхука',
|
||
secretOnce: 'Секрет (показывается один раз)',
|
||
done: 'Готово',
|
||
fieldName: 'Имя',
|
||
fieldNamePlaceholder: 'например, github-push',
|
||
fieldDescription: 'Описание',
|
||
fieldDescriptionPlaceholder: 'Что делает этот вебхук (необязательно)',
|
||
fieldEvents: 'События',
|
||
fieldEventsPlaceholder: 'через запятую, пусто — все',
|
||
fieldSkills: 'Навыки',
|
||
fieldSkillsPlaceholder: 'имена навыков через запятую (необязательно)',
|
||
fieldDeliver: 'Доставить в',
|
||
fieldDeliverOnly: 'Доставлять только payload',
|
||
fieldPrompt: 'Промпт',
|
||
fieldPromptPlaceholder: 'Инструкции для агента при срабатывании этого вебхука (необязательно)',
|
||
nameRequired: 'Имя обязательно',
|
||
create: 'Создать',
|
||
creating: 'Создание...',
|
||
created: 'Создано',
|
||
createFailed: detail => `Не удалось создать: ${detail}`,
|
||
copy: 'Копировать',
|
||
deliverOptions: {
|
||
log: 'Журнал',
|
||
telegram: 'Telegram',
|
||
discord: 'Discord',
|
||
slack: 'Slack',
|
||
email: 'Email',
|
||
github_comment: 'Комментарий GitHub'
|
||
}
|
||
},
|
||
profiles: {
|
||
close: 'Закрыть профили',
|
||
nameHint: 'Строчные буквы, цифры, дефисы и подчёркивания. Должно начинаться с буквы или цифры.',
|
||
title: 'Профили',
|
||
count: count => `${count} ${RU_PLURAL(count, 'профиль', 'профиля', 'профилей')}`,
|
||
search: 'Поиск профилей...',
|
||
loading: 'Загрузка профилей...',
|
||
newProfile: 'Новый профиль',
|
||
importProfile: 'Импортировать профиль…',
|
||
exportProfile: 'Экспортировать профиль…',
|
||
imported: 'Профиль импортирован',
|
||
exported: 'Профиль экспортирован',
|
||
failedImport: 'Не удалось импортировать профиль',
|
||
failedExport: 'Не удалось экспортировать профиль',
|
||
allProfiles: 'Все профили',
|
||
showAllProfiles: 'Показать все профили',
|
||
switchToProfile: name => `Переключиться на ${name}`,
|
||
switchToConnection: name => `Переключиться на ${name}`,
|
||
switchConnectionFailed: name => `Не удалось подключиться к ${name}`,
|
||
manageProfiles: 'Управлять профилями…',
|
||
connectGateway: 'Управлять шлюзами…',
|
||
actions: 'Действия',
|
||
color: 'Цвет…',
|
||
colorFor: 'Цвет',
|
||
setColor: color => `Установить цвет ${color}`,
|
||
autoColor: 'Авто',
|
||
noProfiles: 'Профилей пока нет.',
|
||
selectPrompt: 'Выберите профиль, чтобы посмотреть его детали.',
|
||
refresh: 'Обновить профили',
|
||
refreshing: 'Обновление профилей',
|
||
default: 'по умолчанию',
|
||
skills: count => `${count} ${RU_PLURAL(count, 'навык', 'навыка', 'навыков')}`,
|
||
env: 'env',
|
||
defaultBadge: 'По умолчанию',
|
||
rename: 'Переименовать',
|
||
renameMenu: 'Переименовать…',
|
||
editSoul: 'Изменить SOUL.md…',
|
||
copySetup: 'Скопировать команду установки',
|
||
copying: 'Копирование...',
|
||
modelLabel: 'Модель',
|
||
skillsLabel: 'Навыки',
|
||
notSet: 'Не задано',
|
||
soulDesc: 'Системный промпт и инструкции по персоне, встроенные в этот профиль.',
|
||
soulOptional: 'необязательно',
|
||
soulPlaceholder: mode =>
|
||
`Системный промпт / персона этого профиля.\nОставьте пустым, чтобы сохранить ${mode} по умолчанию.`,
|
||
soulPlaceholderCloned: 'склонированный',
|
||
soulPlaceholderEmpty: 'пустой',
|
||
unsavedChanges: 'Несохранённые изменения',
|
||
loadingSoul: 'Загрузка SOUL.md...',
|
||
emptySoul: 'Пустой SOUL.md — начните писать персону...',
|
||
saving: 'Сохранение...',
|
||
saveSoul: 'Сохранить SOUL.md',
|
||
deleteTitle: 'Удалить профиль?',
|
||
deleteDescPrefix: 'Это удалит ',
|
||
deleteDescMid: ' и сотрёт его ',
|
||
deleteDescSuffix: ' каталог. Это действие необратимо.',
|
||
deleting: 'Удаление...',
|
||
createDesc: 'Профили — это независимые среды Hermes: отдельные настройки, навыки и SOUL.md.',
|
||
nameLabel: 'Имя',
|
||
cloneFrom: 'Клонировать из',
|
||
cloneFromNone: 'Нет (пустой)',
|
||
cloneFromDesc: 'Копирует настройки, навыки и SOUL.md из выбранного исходного профиля.',
|
||
cloneFromDefault: 'Клонировать из профиля по умолчанию',
|
||
cloneFromDefaultDesc: 'Скопируйте настройки, навыки и SOUL.md из вашего профиля по умолчанию.',
|
||
invalidName: hint => `Некорректное имя. ${hint}`,
|
||
nameRequired: 'Имя обязательно.',
|
||
creating: 'Создание...',
|
||
createAction: 'Создать профиль',
|
||
renameTitle: 'Переименовать профиль',
|
||
renameDescPrefix: 'Переименование обновляет каталог профиля и все wrapper-скрипты в ',
|
||
renameDescSuffix: '.',
|
||
displayNameTitle: 'Название этого агента',
|
||
displayNameDesc:
|
||
'Устанавливает отображаемое имя, показываемое во всём приложении. Внутренний ID профиля остаётся «default».',
|
||
displayNameLabel: 'Отображаемое имя',
|
||
newNameLabel: 'Новое имя',
|
||
renaming: 'Переименование...',
|
||
created: 'Профиль создан',
|
||
renamed: 'Профиль переименован',
|
||
deleted: 'Профиль удалён',
|
||
setupCopied: 'Команда установки скопирована',
|
||
soulSaved: 'SOUL.md сохранён',
|
||
failedLoad: 'Не удалось загрузить профили',
|
||
failedDelete: 'Не удалось удалить профиль',
|
||
failedCopy: 'Не удалось скопировать команду установки',
|
||
failedLoadSoul: 'Не удалось загрузить SOUL.md',
|
||
failedSaveSoul: 'Не удалось сохранить SOUL.md',
|
||
failedCreate: 'Не удалось создать профиль',
|
||
failedRename: 'Не удалось переименовать профиль'
|
||
},
|
||
cron: {
|
||
close: 'Закрыть cron',
|
||
title: 'Запланированные задачи',
|
||
count: count => `${count} ${RU_PLURAL(count, 'задача', 'задачи', 'задач')}`,
|
||
modelImpact: {
|
||
title: 'Запланированные задачи остаются на исходной модели',
|
||
message: count =>
|
||
`${count} незакреплённых запланированных задач продолжат работать на модели, с которой были созданы. Закрепите их или задайте cron.model, чтобы перевести.`,
|
||
detailMore: (names, remaining) => `${names} и ещё ${remaining}`,
|
||
review: 'Проверить запланированные задачи',
|
||
saveFailed: 'Hermes не сохранил это изменение модели.'
|
||
},
|
||
search: 'Поиск cron-задач...',
|
||
loading: 'Загрузка cron-задач...',
|
||
states: {
|
||
enabled: 'включено',
|
||
scheduled: 'запланировано',
|
||
running: 'выполняется',
|
||
paused: 'приостановлено',
|
||
disabled: 'отключено',
|
||
error: 'ошибка',
|
||
completed: 'завершено'
|
||
},
|
||
deliveryLabels: {
|
||
local: 'Это приложение',
|
||
telegram: 'Telegram',
|
||
discord: 'Discord',
|
||
slack: 'Slack',
|
||
email: 'Email'
|
||
},
|
||
scheduleLabels: {
|
||
daily: 'Ежедневно',
|
||
weekdays: 'Будни',
|
||
weekly: 'Еженедельно',
|
||
monthly: 'Ежемесячно',
|
||
hourly: 'Каждый час',
|
||
'every-15-minutes': 'Каждые 15 минут',
|
||
custom: 'Свой'
|
||
},
|
||
scheduleHints: {
|
||
daily: 'Каждый день в 9:00',
|
||
weekdays: 'С понедельника по пятницу в 9:00',
|
||
weekly: 'Каждый понедельник в 9:00',
|
||
monthly: 'В первый день каждого месяца в 9:00',
|
||
hourly: 'В начале каждого часа',
|
||
'every-15-minutes': 'Каждые 15 минут',
|
||
custom: 'Синтаксис cron или естественный язык'
|
||
},
|
||
days: {
|
||
'0': 'Воскресенье',
|
||
'1': 'Понедельник',
|
||
'2': 'Вторник',
|
||
'3': 'Среда',
|
||
'4': 'Четверг',
|
||
'5': 'Пятница',
|
||
'6': 'Суббота',
|
||
'7': 'Воскресенье'
|
||
},
|
||
dayFallback: value => `день ${value}`,
|
||
everyDayAt: time => `Каждый день в ${time}`,
|
||
weekdaysAt: time => `Будни в ${time}`,
|
||
everyDayOfWeekAt: (day, time) => `Каждый ${day} в ${time}`,
|
||
monthlyOnDayAt: (dayOfMonth, time) => `Ежемесячно ${dayOfMonth}-го числа в ${time}`,
|
||
topOfHour: 'В начале каждого часа',
|
||
everyHourAt: minute => `Каждый час на :${minute}`,
|
||
newCron: 'Новый cron',
|
||
emptyDescNew:
|
||
'Запланируйте промпт, который будет выполняться по cron-выражению. Hermes выполнит его и доставит результаты в выбранное вами место.',
|
||
emptyDescSearch: 'Попробуйте более широкий запрос.',
|
||
emptyTitleNew: 'Запланированных задач пока нет',
|
||
emptyTitleSearch: 'Нет совпадений',
|
||
last: 'Последний:',
|
||
next: 'Следующий:',
|
||
noRuns: 'Запусков пока не было',
|
||
manage: 'Управлять',
|
||
showRuns: 'Показать запуски',
|
||
hideRuns: 'Скрыть запуски',
|
||
runHistory: 'История запусков',
|
||
actionsTitle: 'Действия с cron-задачей',
|
||
resume: 'Продолжить cron',
|
||
pause: 'Приостановить cron',
|
||
resumeTitle: 'Продолжить',
|
||
pauseTitle: 'Приостановить',
|
||
triggerNow: 'Запустить сейчас',
|
||
edit: 'Изменить cron',
|
||
deleteTitle: 'Удалить cron-задачу?',
|
||
deleteDescPrefix: 'Это навсегда удалит ',
|
||
deleteDescSuffix: '. Она перестанет срабатывать сразу.',
|
||
deleting: 'Удаление...',
|
||
resumed: 'Cron продолжен',
|
||
paused: 'Cron приостановлен',
|
||
triggered: 'Cron запущен',
|
||
deleted: 'Cron удалён',
|
||
created: 'Cron создан',
|
||
updated: 'Cron обновлён',
|
||
failedLoad: 'Не удалось загрузить cron-задачи',
|
||
failedUpdate: 'Не удалось обновить cron-задачу',
|
||
failedTrigger: 'Не удалось запустить cron-задачу',
|
||
failedDelete: 'Не удалось удалить cron-задачу',
|
||
failedSave: 'Не удалось сохранить cron-задачу',
|
||
editTitle: 'Изменить cron-задачу',
|
||
createTitle: 'Новая cron-задача',
|
||
editDesc: 'Обновите расписание, промпт или место доставки. Изменения вступят в силу при следующем запуске.',
|
||
createDesc:
|
||
'Запланируйте промпт для автоматического выполнения. Используйте синтаксис cron или фразу вроде «каждые 15 минут».',
|
||
nameLabel: 'Имя',
|
||
namePlaceholder: 'Утренний брифинг',
|
||
promptLabel: 'Промпт',
|
||
promptPlaceholder: 'Суммируй мои непрочитанные треды Slack и пришли топ-5 на почту...',
|
||
frequencyLabel: 'Частота',
|
||
deliverLabel: 'Доставить в',
|
||
deliverNeedsHomeChannel: 'сначала задайте домашний канал',
|
||
modelLabel: 'Модель',
|
||
modelDefault: 'По умолчанию (глобальная модель)',
|
||
customScheduleLabel: 'Своё расписание',
|
||
customPlaceholder: '0 9 * * * или будни в 9:00',
|
||
customHint: 'Cron-выражение или фразы вроде «каждый час» или «будни в 9:00».',
|
||
optional: 'Необязательно',
|
||
promptRequired: 'Промпт обязателен.',
|
||
promptScheduleRequired: 'Промпт и расписание обязательны.',
|
||
scheduleRequired: 'Расписание обязательно.',
|
||
scriptOnlyEditHint: 'Задача только со скриптом (без AI-промпта). ID задачи:',
|
||
saveChanges: 'Сохранить изменения',
|
||
createAction: 'Создать cron',
|
||
tabs: {
|
||
jobs: 'Задачи',
|
||
blueprints: 'Шаблоны'
|
||
},
|
||
blueprints: {
|
||
tab: 'Шаблоны',
|
||
startFrom: 'Начать с',
|
||
custom: 'Свой',
|
||
subtitle: 'Готовые автоматизации',
|
||
dialogDesc: 'Заполните детали и запланируйте.',
|
||
scheduleIt: 'Запланировать',
|
||
scheduling: 'Планирование...',
|
||
scheduled: 'Шаблон запланирован',
|
||
loading: 'Загрузка шаблонов...',
|
||
failedLoad: 'Не удалось загрузить шаблоны',
|
||
emptyTitle: 'Шаблоны недоступны',
|
||
emptyDesc: 'На этом бэкенде нет шаблонов автоматизации.'
|
||
}
|
||
},
|
||
artifacts: {
|
||
search: 'Поиск артефактов...',
|
||
refresh: 'Обновить артефакты',
|
||
refreshing: 'Обновление артефактов',
|
||
indexing: 'Индексация недавних артефактов сеансов',
|
||
tabAll: 'Все',
|
||
tabImages: 'Изображения',
|
||
tabFiles: 'Файлы',
|
||
tabLinks: 'Ссылки',
|
||
noArtifactsTitle: 'Артефакты не найдены',
|
||
noArtifactsDesc: 'Сгенерированные изображения и файловые результаты появятся здесь по мере их создания в сеансах.',
|
||
failedLoad: 'Не удалось загрузить артефакты',
|
||
openFailed: 'Не удалось открыть',
|
||
itemsImage: 'изображения',
|
||
itemsLink: 'ссылки',
|
||
itemsFile: 'файлы',
|
||
itemsGeneric: 'элементы',
|
||
zero: '0',
|
||
rangeOf: (start, end, total) => `${start}–${end} из ${total}`,
|
||
goToPage: (itemLabel, page) => `Перейти на страницу ${page} ${itemLabel}`,
|
||
colTitleLink: 'Название ссылки',
|
||
colTitleFile: 'Имя',
|
||
colTitleDefault: 'Название / имя',
|
||
colLocationLink: 'URL',
|
||
colLocationFile: 'Путь',
|
||
colLocationDefault: 'Место',
|
||
colSession: 'Сеанс',
|
||
kindImage: 'изображение',
|
||
kindFile: 'файл',
|
||
kindLink: 'ссылка',
|
||
chat: 'Чат',
|
||
copyUrl: 'Копировать URL',
|
||
copyPath: 'Копировать путь'
|
||
},
|
||
|
||
artifactCard: {
|
||
kind: { code: 'Код', html: 'Интерактивная страница', svg: 'Графика' },
|
||
generating: lines => `Генерация… ${lines} ${RU_NOUN(lines, 'строка', 'строки', 'строк')}`,
|
||
versionBadge: count => `${count} ${RU_NOUN(count, 'версия', 'версии', 'версий')}`,
|
||
open: 'Открыть'
|
||
},
|
||
|
||
artifactPreview: {
|
||
versionOf: (current, total) => `v${current} из ${total}`,
|
||
olderVersion: 'Более старая версия',
|
||
newerVersion: 'Более новая версия',
|
||
latest: 'Последняя',
|
||
copyContent: 'Копировать содержимое',
|
||
download: 'Скачать',
|
||
openInBrowser: 'Открыть в браузере',
|
||
openInBrowserFailed: 'Не удалось открыть в браузере',
|
||
missingTitle: 'Артефакт недоступен',
|
||
missingBody: 'Этот артефакт больше нет в локальном реестре.'
|
||
},
|
||
sidebar: {
|
||
gatewayGroups: {
|
||
grouping: 'Шлюз и профиль',
|
||
rename: 'Переименовать группу',
|
||
aliasLabel: 'Отображаемое имя',
|
||
aliasHint: 'Меняется только отображаемое имя; имена шлюза и профиля остаются прежними.',
|
||
resetName: 'Сбросить имя',
|
||
moveUp: 'Переместить вверх',
|
||
moveDown: 'Переместить вниз',
|
||
reorder: 'Изменить порядок групп',
|
||
actions: 'Действия с группой'
|
||
},
|
||
nav: {
|
||
'new-session': 'Новый сеанс',
|
||
skills: 'Возможности',
|
||
messaging: 'Сообщения',
|
||
artifacts: 'Артефакты',
|
||
cron: 'Запланированные задачи'
|
||
},
|
||
searchAria: 'Поиск сеансов',
|
||
searchPlaceholder: 'Поиск сеансов…',
|
||
clearSearch: 'Очистить поиск',
|
||
noMatch: query => `Нет сеансов по запросу «${query}».`,
|
||
results: 'Результаты',
|
||
pinned: 'Закреплённые',
|
||
sessions: 'Сеансы',
|
||
cronJobs: 'Cron-задачи',
|
||
groupAriaGrouped: 'Показать сеансы одним списком',
|
||
groupAriaUngrouped: 'Сгруппировать сеансы по рабочим пространствам',
|
||
showProjects: 'Показать проекты',
|
||
showSessions: 'Показать сеансы',
|
||
groupTitleGrouped: 'Не группировать сеансы',
|
||
groupTitleUngrouped: 'Группировать по рабочему пространству',
|
||
allPinned: 'Здесь всё закреплено. Открепите чат, чтобы он появился в недавних.',
|
||
shiftClickHint: 'Shift-клик по чату, чтобы закрепить',
|
||
noWorkspace: 'Без рабочего пространства',
|
||
projectEmpty: 'Сеансов пока нет',
|
||
projectLoadFailed: 'Не удалось загрузить сеансы',
|
||
noSessions: 'Сеансов пока нет',
|
||
noFilterMatches: 'Нет сеансов по этим фильтрам',
|
||
projects: {
|
||
showAllSessions: 'Показать все сессии',
|
||
sectionLabel: 'Проекты',
|
||
home: 'Главная',
|
||
newButton: 'Новый проект',
|
||
createTitle: 'Новый проект',
|
||
createDesc: 'Назовите рабочее пространство и добавьте одну или несколько папок.',
|
||
renameTitle: 'Переименовать проект',
|
||
addFolderTitle: 'Добавить папку',
|
||
namePlaceholder: 'например, Skunkworks',
|
||
foldersLabel: 'Папки',
|
||
ideaLabel: 'Идея',
|
||
ideaPlaceholder: 'О чём этот проект? (сохраняется в IDEA.md)',
|
||
ideaGenerate: 'Сгенерировать идею',
|
||
ideaGenerating: 'Генерация…',
|
||
ideaShuffle: 'Перемешать шаблоны',
|
||
noFolders: 'Папки ещё не добавлены.',
|
||
addFolder: 'Добавить папку',
|
||
primaryBadge: 'основная',
|
||
removeFolder: 'Удалить',
|
||
create: 'Создать',
|
||
menu: 'Действия',
|
||
menuRename: 'Переименовать',
|
||
menuAppearance: 'Внешний вид',
|
||
noColor: 'Без цвета',
|
||
menuAddFolder: 'Добавить папку',
|
||
menuSetActive: 'Сделать активным',
|
||
menuDelete: 'Удалить',
|
||
moveToProject: 'Переместить в проект',
|
||
movedTo: name => `Перемещено в ${name}`,
|
||
moveFailed: 'Не удалось переместить сеанс',
|
||
moveNoFolder: 'У этого проекта нет папки для перемещения',
|
||
moveNoProjects: 'Нет других проектов',
|
||
reveal: 'Показать в папке',
|
||
copyPath: 'Копировать путь',
|
||
removeFromSidebar: 'Скрыть из боковой панели',
|
||
createFailed: 'Не удалось создать проект',
|
||
staleBackend:
|
||
'Обновите бэкенд Hermes, чтобы создавать проекты — ваш бэкенд старше этого desktop-приложения (Настройки → Обновления → Бэкенд).',
|
||
deleteConfirm: 'Это удалит сохранённый проект из Hermes. Файлы, git-репозитории и worktrees не пострадают.',
|
||
startWork: 'Новый worktree',
|
||
newWorktreeTitle: 'Новый worktree',
|
||
newWorktreeDesc: 'Назовите ветку для этого worktree.',
|
||
branchPlaceholder: 'например, my-feature',
|
||
branchOff: () => ({ after: '', before: 'от ветки ' }),
|
||
baseBranchPlaceholder: 'Поиск веток…',
|
||
baseBranchNone: 'Ветки не найдены',
|
||
startWorkFailed: 'Не удалось создать worktree',
|
||
worktreeStaleBackend:
|
||
'Обновите бэкенд Hermes, чтобы создавать worktrees по этому удалённому соединению — он старше git worktree API.',
|
||
worktreeProjectLabel: 'Проект',
|
||
worktreeProjectPlaceholder: 'Поиск проектов…',
|
||
worktreeProjectNone: 'Нет проектов с папкой',
|
||
convertBranch: 'Преобразовать ветку…',
|
||
convertBranchTitle: 'Преобразовать ветку',
|
||
convertBranchDesc: 'Откройте закоммиченные ветки или создайте worktree для свободной ветки.',
|
||
convertBranchPlaceholder: 'Поиск веток…',
|
||
convertBranchInstead: 'Преобразовать существующую ветку',
|
||
branchOpenExisting: 'открыть',
|
||
branchSwitchHome: 'сменить home',
|
||
branchCreateWorktree: 'новый worktree',
|
||
branchTrackRemote: 'отслеживать удалённую',
|
||
branchesLoading: 'Загрузка веток…',
|
||
noBranches: 'Ветки не найдены',
|
||
removeWorktree: 'Удалить worktree',
|
||
removeWorktreeFailed: 'Не удалось удалить worktree (есть незакоммиченные изменения?)',
|
||
removeWorktreeConfirm:
|
||
'Удалить из git (сотрёт каталог worktree; ветка останется) или просто скрыть лану из боковой панели, оставив worktree на диске.',
|
||
removeWorktreeDirty:
|
||
'В этом worktree есть незакоммиченные изменения. Удалить принудительно (сбросит эти изменения) или просто скрыть лану и оставить на диске.',
|
||
forceRemove: 'Удалить принудительно',
|
||
enter: label => `Открыть ${label}`,
|
||
reorder: label => `Изменить порядок ${label}`,
|
||
toggle: (label, open) => `${open ? 'Показать' : 'Скрыть'} сеансы ${label}`,
|
||
back: 'Все проекты'
|
||
},
|
||
newSessionIn: label => `Новый сеанс в ${label}`,
|
||
showMoreIn: (count, label) => `Показать ещё ${count} в ${label}`,
|
||
loading: 'Загрузка…',
|
||
loadMore: 'Загрузить ещё',
|
||
loadCount: step => `Загрузить ещё ${step}`,
|
||
messageCount: count => `${count} ${RU_PLURAL(count, 'сообщение', 'сообщения', 'сообщений')}`,
|
||
toolCallCount: count =>
|
||
`${count} ${RU_PLURAL(count, 'вызов инструмента', 'вызова инструмента', 'вызовов инструмента')}`,
|
||
row: {
|
||
pin: 'Закрепить',
|
||
unpin: 'Открепить',
|
||
markUnread: 'Отметить как непрочитанное',
|
||
markRead: 'Отметить как прочитанное',
|
||
unreadFailed: 'Не удалось обновить состояние непрочитанных',
|
||
copyId: 'Копировать ID',
|
||
export: 'Экспорт',
|
||
branchFrom: 'Ветка',
|
||
rename: 'Переименовать',
|
||
archive: 'В архив',
|
||
newWindow: 'Новое окно',
|
||
openInTerminal: 'Открыть в терминале',
|
||
hideTabBar: 'Скрыть панель вкладок',
|
||
openInNewTab: 'Открыть в новой вкладке',
|
||
openInSplit: 'Открыть в сплит-виде',
|
||
copyIdFailed: 'Не удалось скопировать ID сеанса',
|
||
sessionActions: 'Действия с сеансом',
|
||
sessionRunning: 'Сеанс выполняется',
|
||
needsInput: 'Нужен ваш ввод',
|
||
waitingForAnswer: 'Ждёт вашего ответа',
|
||
finishedUnread: 'Завершён — не прочитан',
|
||
backgroundRunning: 'Фоновая задача выполняется',
|
||
draftSession: 'Черновик — ещё ничего не отправлено',
|
||
handoffOrigin: platform => `Передано из ${platform}`,
|
||
ownedByProfile: profile => `Профиль: ${profile}`,
|
||
renamed: 'Переименовано',
|
||
renameFailed: 'Переименование не удалось',
|
||
renameTitle: 'Переименовать сеанс',
|
||
renameDesc: 'Оставьте пустым, чтобы очистить.',
|
||
untitledPlaceholder: 'Сеанс без названия',
|
||
deleteTitle: 'Удалить сеанс?',
|
||
deleteDesc: title => `Это навсегда удалит «${title}». Это действие необратимо.`,
|
||
deleting: 'Удаление…',
|
||
deleted: 'Сеанс удалён',
|
||
untitledChat: id => `Чат ${id}`,
|
||
messageCount: count => `${count} ${RU_PLURAL(count, 'сообщение', 'сообщения', 'сообщений')}`,
|
||
todoProgress: 'Задачи выполнены',
|
||
ageNow: 'сейчас',
|
||
ageDay: 'д',
|
||
ageHour: 'ч',
|
||
ageMin: 'м'
|
||
},
|
||
dateDivider: {
|
||
today: 'Ранее сегодня',
|
||
yesterday: 'Вчера',
|
||
thisWeek: 'Ранее на этой неделе',
|
||
lastWeek: 'На прошлой неделе',
|
||
thisMonth: 'Ранее в этом месяце'
|
||
},
|
||
statusDivider: {
|
||
working: 'Работает',
|
||
done: 'Готово'
|
||
},
|
||
markAllRead: 'Отметить все как прочитанные'
|
||
},
|
||
composer: {
|
||
message: 'Сообщение',
|
||
wakingProfile: profile => `Пробуждаем ${profile}…`,
|
||
placeholderStarting: 'Запуск Hermes...',
|
||
placeholderReconnecting: 'Переподключение к Hermes…',
|
||
placeholderFollowUp: 'Отправить продолжение',
|
||
newSessionPlaceholders: [
|
||
'Что будем делать?',
|
||
'Дайте Hermes задачу',
|
||
'О чём вы думаете?',
|
||
'Опишите, что нужно',
|
||
'Что обсудим?',
|
||
'Спросите о чём угодно',
|
||
'Начните с цели'
|
||
],
|
||
followUpPlaceholders: [
|
||
'Отправьте продолжение',
|
||
'Добавьте контекст',
|
||
'Уточните запрос',
|
||
'Что дальше?',
|
||
'Продолжаем',
|
||
'Запустите дальше',
|
||
'Скорректируйте или продолжите'
|
||
],
|
||
startVoice: 'Начать голосовой разговор',
|
||
openDirective: 'Открыть',
|
||
queueMessage: 'Вставить сообщение в очередь',
|
||
steer: 'Направить текущий запуск',
|
||
stop: 'Стоп',
|
||
send: 'Отправить',
|
||
speaking: 'Говорит',
|
||
transcribing: 'Расшифровка',
|
||
thinking: 'Думает',
|
||
muted: 'Приглушено',
|
||
listening: 'Слушает',
|
||
muteMic: 'Выключить микрофон',
|
||
unmuteMic: 'Включить микрофон',
|
||
stopListening: 'Перестать слушать и отправить',
|
||
stopShort: 'Стоп',
|
||
endConversation: 'Завершить голосовой разговор',
|
||
endShort: 'Завершить',
|
||
stopDictation: 'Остановить диктовку',
|
||
transcribingDictation: 'Расшифровка диктовки',
|
||
voiceControls: 'Голос',
|
||
voiceDictation: 'Голосовая диктовка',
|
||
speakReplies: 'Зачитывать ответы вслух',
|
||
stopSpeakingReplies: 'Перестать зачитывать ответы вслух',
|
||
wakeWordListening: phrase => `Слово-пробуждение: «${phrase}» — слушает`,
|
||
wakeWordOff: phrase => `Слово-пробуждение: «${phrase}» — выключено`,
|
||
wakeWordPausedVoice: phrase => `Слово-пробуждение: «${phrase}» — приостановлено во время голосового чата`,
|
||
lookupLoading: 'Ищем…',
|
||
lookupNoMatches: 'Нет совпадений.',
|
||
lookupTry: 'Попробуйте',
|
||
lookupOr: 'или',
|
||
commonCommands: 'Частые команды',
|
||
hotkeys: 'Горячие клавиши',
|
||
helpFooter: 'открывает полную панель · backspace закрывает',
|
||
commandDescs: {
|
||
'/help': 'полный список команд + горячих клавиш',
|
||
'/clear': 'начать новый сеанс',
|
||
'/resume': 'возобновить прошлый сеанс',
|
||
'/details': 'уровень детализации транскрипта',
|
||
'/copy': 'скопировать выделенное или последнее сообщение ассистента',
|
||
'/quit': 'выйти из hermes'
|
||
},
|
||
hotkeyDescs: {
|
||
'composer.mention': 'ссылки на файлы, папки, URL, git',
|
||
'composer.slash': 'палитра слэш-команд',
|
||
'composer.help': 'эта быстрая справка (удалите, чтобы закрыть)',
|
||
'composer.sendNewline': 'отправить · Shift+Enter — новая строка',
|
||
'composer.sendQueued': 'отправить следующий ход в очереди',
|
||
'keybinds.openPanel': 'все горячие клавиши',
|
||
'composer.cancel': 'закрыть поповер · отменить запуск',
|
||
'composer.history': 'переключать поповер / историю'
|
||
},
|
||
attachUrlTitle: 'Прикрепить URL',
|
||
attachUrlDesc: 'Hermes загрузит страницу и добавит её как контекст для этого хода.',
|
||
urlPlaceholder: 'https://example.com/post',
|
||
urlHintPre: 'Укажите полный URL, например ',
|
||
attach: 'Прикрепить',
|
||
queued: count => `${count} в очереди`,
|
||
queuedPaused: count => `${count} в очереди — пауза`,
|
||
attachmentOnly: 'Ход только с вложениями',
|
||
emptyTurn: 'Пустой ход',
|
||
attachments: count => `${count} ${RU_NOUN(count, 'вложение', 'вложения', 'вложений')}`,
|
||
editingInComposer: 'Редактирование в композере',
|
||
editingQueuedInComposer: 'Редактирование хода в очереди в композере',
|
||
queueEdit: 'Изменить',
|
||
queueSendNext: 'Дальше',
|
||
queueSteer: 'Направить — изменить текущий ход сейчас',
|
||
queueSend: 'Отправить',
|
||
queueDelete: 'Удалить',
|
||
queueResume: 'Продолжить',
|
||
queueResumeTip: 'Приостановлено стопом — продолжить отправку ходов из очереди',
|
||
queueStuckTitle: 'Сообщение из очереди не отправлено',
|
||
queueStuckBody:
|
||
'Ход из очереди несколько раз не удалось отправить. Он всё ещё в очереди — попробуйте отправить снова.',
|
||
previewUnavailable: 'Предпросмотр недоступен',
|
||
previewLabel: label => `Предпросмотр ${label}`,
|
||
couldNotPreview: label => `Не удалось предпросмотреть ${label}`,
|
||
removeAttachment: label => `Удалить ${label}`,
|
||
dictating: 'Диктовка',
|
||
preparingAudio: 'Подготовка аудио',
|
||
speakingResponse: 'Зачитывает ответ',
|
||
readingAloud: 'Читает вслух',
|
||
themeSuggestions: 'Предложения тем desktop',
|
||
noMatchingThemes: 'Нет совпадающих тем.',
|
||
themeTryPre: 'Попробуйте ',
|
||
themeTryPost: '.',
|
||
attachLabel: 'Прикрепить',
|
||
files: 'Файлы…',
|
||
folder: 'Папка…',
|
||
images: 'Изображения…',
|
||
pasteImage: 'Вставить изображение',
|
||
url: 'URL…',
|
||
promptSnippets: 'Фрагменты промптов…',
|
||
tipPre: 'Подсказка: введите ',
|
||
tipPost: ' чтобы ссылаться на файлы inline.',
|
||
snippetsTitle: 'Фрагменты промптов',
|
||
snippetsDesc: 'Выберите стартовый промпт, чтобы вставить в композер.',
|
||
dropFiles: 'Перетащите файлы, чтобы прикрепить',
|
||
dropSession: 'Перетащите, чтобы связать этот чат',
|
||
mcpSuggestions: {
|
||
label: server => `Добавить ${server}`,
|
||
tip: keyword => `Предложено, потому что вы упомянули «${keyword}» — нажмите, чтобы подключить`,
|
||
connecting: server => `Подключаем ${server}…`,
|
||
cancelTip: 'Нажмите, чтобы отменить',
|
||
added: server => `Добавлен ${server}`,
|
||
addedTip: 'Подключено — его инструменты готовы в этом чате',
|
||
connectFailed: server => `Не удалось подключить ${server}`
|
||
},
|
||
skillSuggestions: {
|
||
label: skill => `Использовать навык: ${skill}`,
|
||
tip: skill => `Вы упомянули «${skill}» — нажмите, чтобы начать с этого навыка`,
|
||
done: skill => `Добавлено /${skill}`,
|
||
doneTip: 'Навык загрузится при отправке'
|
||
},
|
||
githubSuggestions: {
|
||
label: 'Настроить GitHub',
|
||
tip: 'GitHub работает через навыки gh CLI здесь — нажмите, чтобы подключить аккаунт',
|
||
done: 'Добавлено /github-auth',
|
||
doneTip: 'Отправьте сообщение, и агент проведёт вас через вход в GitHub'
|
||
},
|
||
repairSuggestions: {
|
||
label: server => `Переподключить ${server}`,
|
||
tip: server => `Недавний вызов ${server} завершился ошибкой соединения`,
|
||
working: server => `Переподключаем ${server}…`,
|
||
workingTip: 'Нажмите, чтобы отменить',
|
||
done: server => `Переподключено ${server}`,
|
||
doneTip: 'Свежие учётные данные активны в этом чате',
|
||
failed: server => `Не удалось переподключить ${server}`
|
||
},
|
||
cronSuggestions: {
|
||
label: 'Запланировать это',
|
||
tip: phrase => `«${phrase}» звучит как повторяющееся — запланируйте выполнение по расписанию`,
|
||
prefix: 'Настроить это как запланированную задачу:',
|
||
done: 'Отмечено для планирования',
|
||
doneTip: 'Отправьте, и агент создаст задачу'
|
||
},
|
||
snippets: {
|
||
codeReview: {
|
||
label: 'Рецензия кода',
|
||
description: 'Аудит текущих изменений на предмет регрессий, упущенных граничных случаев и недостающих тестов.',
|
||
text: 'Пожалуйста, проверьте это на баги, регрессии и недостающие тесты.'
|
||
},
|
||
implementationPlan: {
|
||
label: 'План реализации',
|
||
description: 'Опишите подход перед правкой кода, чтобы diff остался сфокусированным.',
|
||
text: 'Пожалуйста, составьте краткий план реализации перед изменением кода.'
|
||
},
|
||
explainThis: {
|
||
label: 'Объяснить это',
|
||
description: 'Разберите, как работает выделенный код, и дайте ссылки на ключевые файлы.',
|
||
text: 'Пожалуйста, объясните, как это работает, и укажите ключевые файлы.'
|
||
}
|
||
}
|
||
},
|
||
statusStack: {
|
||
agents: 'Агенты',
|
||
background: count => `${count} ${RU_NOUN(count, 'фоновая задача', 'фоновые задачи', 'фоновых задач')}`,
|
||
goalActive: 'Цель активна',
|
||
goalBlocked: 'Цель заблокирована',
|
||
goalDone: 'Цель выполнена',
|
||
goalPaused: 'Цель на паузе',
|
||
goalWaiting: 'Цель ожидает',
|
||
subagents: count => `${count} ${RU_PLURAL(count, 'субагент', 'субагента', 'субагентов')}`,
|
||
todos: (done, total) => `Задачи ${done}/${total}`,
|
||
running: 'Выполняется',
|
||
stop: 'Стоп',
|
||
dismiss: 'Скрыть',
|
||
exit: code => `exit ${code}`,
|
||
control: {
|
||
goalActiveTurns: (turn, maxTurns) => `Ход ${turn}/${maxTurns}`,
|
||
goalDoneTurns: turns => `${turns} ходов`,
|
||
goalTurn: turn => `Ход ${turn}`,
|
||
goalActions: 'Действия с целью',
|
||
viewDetails: 'Подробнее',
|
||
addCriterion: 'Добавить критерий',
|
||
addCriterionDialogTitle: 'Добавить критерий',
|
||
addCriterionPlaceholder: 'Введите текст критерия...',
|
||
criterionLabel: 'Критерий',
|
||
pauseGoal: 'Приостановить цель',
|
||
resumeGoal: 'Возобновить цель',
|
||
resumeNow: 'Возобновить сейчас',
|
||
clearGoal: 'Очистить цель',
|
||
clearGoalConfirmTitle: 'Очистить цель?',
|
||
clearGoalConfirmBody: 'Вы уверены, что хотите очистить активную цель? Это действие необратимо.',
|
||
copyCriterion: index => `Скопировать критерий ${index}`,
|
||
removeCriterion: index => `Удалить критерий ${index}`,
|
||
removeCriterionConfirmTitle: index => `Удалить критерий ${index}?`,
|
||
removeCriterionConfirmBody: index => `Вы уверены, что хотите удалить критерий ${index}?`,
|
||
clearCriteria: 'Очистить все критерии',
|
||
clearCriteriaConfirmTitle: 'Очистить все критерии?',
|
||
clearCriteriaConfirmBody: 'Вы уверены, что хотите удалить все критерии этой цели?',
|
||
criteriaHeader: count => `Критерии · ${count}`,
|
||
noCriteria: 'Нет критериев',
|
||
goalDetailsTitle: 'Детали цели',
|
||
objectiveLabel: 'Задача',
|
||
contractOutcome: 'Результат',
|
||
contractVerification: 'Проверка',
|
||
contractConstraints: 'Ограничения',
|
||
contractBoundaries: 'Границы',
|
||
contractStopWhen: 'Условие остановки',
|
||
waitBarrierTitle: 'Условие ожидания',
|
||
waitUntil: target => `Ожидание до ${target}`,
|
||
waitSession: target => `Ожидание сессии ${target}`,
|
||
waitPid: pid => `Ожидание процесса ${pid}`,
|
||
qualityGatesTitle: 'Контроли качества',
|
||
gateCommand: 'Команда',
|
||
gateAttempts: (attempts, max) => `${attempts}/${max} попыток`,
|
||
gateTimeout: seconds => `таймаут ${seconds}с`,
|
||
gateLastExit: code => (code === null ? 'В ожидании' : `Код возврата: ${code}`),
|
||
loopActive: 'Цикл активен',
|
||
loopPaused: 'Цикл приостановлен',
|
||
loopDeferred: 'Цикл отложен',
|
||
loopFinished: 'Цикл завершен',
|
||
loopRuns: runs => `${runs} запусков`,
|
||
loopRunCount: (current, total) => `Запуск ${current}/${total}`,
|
||
loopNext: time => `следующий ${time}`,
|
||
loopEverySeconds: seconds => `каждые ${seconds}с`,
|
||
loopEveryMinutes: minutes => `каждые ${minutes}м`,
|
||
loopEveryHours: hours => `каждые ${hours}ч`,
|
||
loopSelfPaced: 'автономный',
|
||
loopActions: 'Действия цикла',
|
||
pauseLoop: 'Приостановить цикл',
|
||
resumeLoop: 'Возобновить цикл',
|
||
stopLoop: 'Остановить цикл',
|
||
stopLoopConfirmTitle: 'Остановить цикл?',
|
||
stopLoopConfirmBody: 'Вы уверены, что хотите остановить этот цикл?',
|
||
dismissLoop: 'Закрыть цикл',
|
||
loopPromptLabel: 'Промпт',
|
||
loopCadenceLabel: 'Интервал',
|
||
loopUntilLabel: 'Условие окончания',
|
||
loopDeferredNotice: 'Активная цель в данный момент управляет сессией.',
|
||
loopAwaitingResponse: 'Ожидание ответа',
|
||
heartbeatActive: 'Пульс активен',
|
||
heartbeatPaused: 'Пульс приостановлен',
|
||
heartbeatEveryMinutes: minutes => `каждые ${minutes}м`,
|
||
heartbeatEveryHours: hours => `каждые ${hours}ч`,
|
||
heartbeatEverySeconds: seconds => `каждые ${seconds}с`,
|
||
heartbeatNext: time => `следующий ${time}`,
|
||
heartbeatDueWaitingForIdle: 'пора — ожидание простоя',
|
||
heartbeatActions: 'Действия пульса',
|
||
pauseHeartbeat: 'Приостановить пульс',
|
||
resumeHeartbeat: 'Возобновить пульс',
|
||
clearHeartbeat: 'Очистить пульс',
|
||
clearHeartbeatConfirmTitle: 'Очистить пульс?',
|
||
clearHeartbeatConfirmBody: 'Вы уверены, что хотите очистить этот пульс?',
|
||
heartbeatFiredCount: count => `Сработал ${count} раз`,
|
||
actionFailed: msg => `Ошибка действия: ${msg}`,
|
||
actionSucceeded: 'Действие выполнено успешно',
|
||
copySuccess: 'Критерий скопирован в буфер обмена',
|
||
copyFailure: 'Не удалось скопировать критерий в буфер обмена',
|
||
continuationFailed: 'Не удалось отправить продолжение цели',
|
||
continuationQueued: 'Цель возобновлена — продолжение поставлено в очередь до конца текущего хода',
|
||
continuationBusy: 'Цель возобновлена — сессия занята, выполните /interrupt, чтобы продолжить',
|
||
controlUnavailable: msg => `Управление сессией недоступно: ${msg}`,
|
||
dismissError: 'Скрыть ошибку',
|
||
add: 'Добавить'
|
||
},
|
||
coding: {
|
||
title: 'Рабочее дерево',
|
||
noBranch: 'Без ветки',
|
||
detached: 'отсоединена',
|
||
clean: 'Чисто',
|
||
changed: count => `${count} изменено`,
|
||
ahead: count => `${count} впереди`,
|
||
behind: count => `${count} позади`,
|
||
review: 'Проверить',
|
||
close: 'Закрыть',
|
||
openChanges: 'Открыть изменения',
|
||
openFile: 'Открыть файл',
|
||
stage: 'Добавить в индекс',
|
||
unstage: 'Убрать из индекса',
|
||
stageAll: 'Добавить всё в индекс',
|
||
viewAsTree: 'Вид деревом',
|
||
viewAsList: 'Вид списком',
|
||
revert: 'Отменить',
|
||
revertAll: 'Отменить всё',
|
||
revertConfirm:
|
||
'Сбросить изменения в этом файле и вернуть его в закоммиченное состояние? Это действие необратимо.',
|
||
revertAllConfirm: 'Сбросить все изменения и вернуть файлы в закоммиченное состояние? Это действие необратимо.',
|
||
staged: 'В индексе',
|
||
noChanges: 'Изменений нет',
|
||
notRepo: 'Не git-репозиторий',
|
||
noDiff: 'Нет diff для показа',
|
||
scopeUncommitted: 'Незакоммиченные',
|
||
scopeBranch: 'Ветка',
|
||
scopeLastTurn: 'Последний ход',
|
||
commit: 'Коммит',
|
||
commitAndPush: 'Коммит и Push',
|
||
commitPlaceholder: shortcut => `Сообщение (${shortcut} — коммит)`,
|
||
generateCommitMessage: 'Сгенерировать сообщение коммита',
|
||
stopGenerating: 'Остановить генерацию',
|
||
createPr: 'Создать PR',
|
||
openPr: 'Открыть PR',
|
||
ghMissing: 'Установите GitHub CLI (gh) и войдите, чтобы открывать PR',
|
||
agentShip: 'Попросить Hermes открыть PR',
|
||
agentShipUnavailable: 'Чат, которому принадлежат эти изменения, не на экране.',
|
||
agentShipPrompt:
|
||
'Проверьте текущие изменения, закоммитьте их с ясным conventional-commit сообщением, запушьте ветку и создайте pull request.',
|
||
newBranch: 'Новая ветка',
|
||
branchOffFrom: base => `Новая ветка от ${base}`,
|
||
switchTo: branch => `Переключиться на ${branch}`,
|
||
switchFailed: branch => `Не удалось переключиться на ${branch}`,
|
||
worktrees: 'Worktrees'
|
||
}
|
||
},
|
||
updates: {
|
||
stages: {
|
||
idle: 'Готовимся…',
|
||
prepare: 'Готовимся…',
|
||
fetch: 'Скачиваем…',
|
||
pull: 'Почти готово…',
|
||
pydeps: 'Завершаем…',
|
||
update: 'Обновляем Hermes…',
|
||
rebuild: 'Пересобираем desktop-приложение…',
|
||
restart: 'Перезапускаем Hermes…',
|
||
done: 'Обновление завершено',
|
||
manual: 'Обновление из терминала',
|
||
guiSkew: 'Обновите desktop-приложение',
|
||
error: 'Обновление приостановлено'
|
||
},
|
||
checking: 'Ищем обновления…',
|
||
checkFailedTitle: 'Не удалось проверить обновления',
|
||
tryAgain: 'Попробовать снова',
|
||
notAvailableTitle: 'Обновление недоступно',
|
||
unsupportedMessage: 'Эта версия Hermes не может обновлять себя из приложения.',
|
||
connectionRetry: 'Проверьте соединение и попробуйте снова.',
|
||
latestBody: 'У вас последняя версия.',
|
||
latestBodyBackend: 'Бэкенд работает на последней версии.',
|
||
allSetTitle: 'Всё готово',
|
||
availableTitle: 'Доступно новое обновление',
|
||
availableBody: 'Новая версия Hermes готова к установке.',
|
||
availableTitleBackend: 'Доступно обновление бэкенда',
|
||
availableBodyBackend: 'Новая версия подключённого бэкенда Hermes готова к установке.',
|
||
availableBodyNoChangelog: 'Новая версия готова. Заметки о выпуске недоступны для этого типа установки.',
|
||
updateNow: 'Обновить сейчас',
|
||
maybeLater: 'Возможно позже',
|
||
moreChanges: count => `+ ещё ${count} ${RU_NOUN(count, 'изменение', 'изменения', 'изменений')} включено.`,
|
||
manualTitle: 'Обновление из терминала',
|
||
manualBody:
|
||
'Hermes установлен из командной строки, поэтому обновления тоже выполняются там. Вставьте это в терминал:',
|
||
manualPickedUp: 'Hermes подхватит новую версию при следующем запуске.',
|
||
guiSkewTitle: 'Обновите desktop-приложение',
|
||
guiSkewBody:
|
||
'Бэкенд обновлён, но пакет этого desktop-приложения не изменился. Обновите или переустановите desktop-приложение Hermes (ваш AppImage / .deb / .rpm), чтобы версии совпали.',
|
||
copy: 'Копировать',
|
||
copied: 'Скопировано',
|
||
done: 'Готово',
|
||
applyingBody:
|
||
'Обновлятор Hermes возьмёт процесс на себя в своём окне и автоматически перезапустит Hermes, когда закончит. Пожалуйста, не открывайте Hermes вручную во время обновления.',
|
||
applyingBodyBackend:
|
||
'Удалённый бэкенд применяет обновление и перезапустится. Hermes переподключится автоматически, когда он снова заработает.',
|
||
applyingClose: 'Это окно закроется во время обновления, затем Hermes откроется сам.',
|
||
errorTitle: 'Обновление не завершилось',
|
||
errorBody: 'Не переживайте — ничего не потеряно. Можно попробовать снова прямо сейчас.',
|
||
blockerTitle: 'Закрыть локальные предпросмотры, чтобы обновить Hermes?',
|
||
blockerBody:
|
||
'Hermes нужно остановить эти локальные предпросмотры перед обновлением. Ваши файлы не будут изменены или удалены.',
|
||
foreignBlockerTitle: 'Закрыть другие процессы, чтобы обновить Hermes',
|
||
foreignBlockerBody:
|
||
'Hermes не может безопасно закрыть эти процессы автоматически. Закройте приложение, терминал или службу, которой принадлежит каждый из них, и повторите обновление.',
|
||
mixedBlockerBody:
|
||
'Hermes может закрыть локальные предпросмотры, перечисленные ниже. Остальные процессы нужно закрыть вручную, прежде чем обновление сможет продолжиться.',
|
||
closePreviewsAndUpdate: 'Закрыть предпросмотры и обновить',
|
||
closePreviewsAndCheckAgain: 'Закрыть предпросмотры и проверить снова',
|
||
localPreview: 'Локальный предпросмотр',
|
||
portLabel: port => `Порт ${port}`,
|
||
pidLabel: pid => `PID ${pid}`,
|
||
technicalDetails: 'Технические детали',
|
||
notNow: 'Не сейчас',
|
||
clientAlsoBehindTitle: 'Desktop-приложение отстает',
|
||
clientAlsoBehindMessage:
|
||
'Бэкенд в актуальном состоянии, но это desktop-приложение ещё на старой версии. Обновите его, чтобы получить последние исправления.',
|
||
clientAlsoBehindAction: 'Обновить desktop-приложение',
|
||
everythingDispatched: 'Обновление запущено',
|
||
everythingSkipped: 'Пропущено',
|
||
everythingRowFailed: 'Обновление не удалось',
|
||
everythingFanoutFailedTitle: 'Не удалось обновить другие инстанции',
|
||
applyStatus: {
|
||
preparing: 'Обновляем бэкенд…',
|
||
pulling: 'Бэкенд обновляется…',
|
||
restarting: 'Бэкенд перезапускается для загрузки обновления…',
|
||
notAvailable: 'Обновление недоступно для этого бэкенда.',
|
||
failed: 'Не удалось обновить бэкенд.',
|
||
noReturn: 'Бэкенд не вернулся в сеть. Обновление могло не завершиться — проверьте хост бэкенда.'
|
||
}
|
||
},
|
||
install: {
|
||
stageStates: {
|
||
pending: 'Ожидает',
|
||
running: 'Установка',
|
||
succeeded: 'Готово',
|
||
skipped: 'Пропущено',
|
||
failed: 'Ошибка'
|
||
},
|
||
oneTimeTitle: 'Hermes требует одноразовой установки',
|
||
unsupportedDesc: platform =>
|
||
`Автоматическая установка при первом запуске пока недоступна на ${platform}. Откройте Терминал и выполните команду ниже, затем перезапустите это приложение. При следующих запусках этот шаг будет пропущен.`,
|
||
installCommand: 'Команда установки',
|
||
copyCommand: 'Копировать команду',
|
||
viewDocs: 'Открыть документацию по установке',
|
||
installTo: 'Будет установлено в',
|
||
retryAfterRun: 'Я выполнил — попробовать снова',
|
||
setupChoiceTitle: 'Настройка Hermes Desktop',
|
||
setupChoiceDesc:
|
||
'Подключите это приложение к уже работающему шлюзу Hermes или установите Hermes локально на этот компьютер.',
|
||
connectExistingTitle: 'Подключиться к существующему Hermes',
|
||
connectExistingShort: 'Подключить существующий',
|
||
connectExistingDesc:
|
||
'Используйте удалённый бэкенд с сессионным токеном или входом через браузер. Локальная установка не начнётся.',
|
||
installLocalTitle: 'Установить Hermes локально',
|
||
installLocalDesc: 'Скачайте Hermes, создайте его Python-окружение и запустите бэкенд на этом компьютере.',
|
||
localStartUnavailable: 'Не удалось начать локальную установку. Перезапустите Hermes Desktop и попробуйте снова.',
|
||
remoteSetupTitle: 'Подключиться к существующему Hermes',
|
||
remoteSetupDesc: 'Введите URL вашего шлюза. Hermes Desktop определит, нужен токен или вход через браузер.',
|
||
remoteUrlTitle: 'URL шлюза',
|
||
remoteUrlDesc: 'Используйте базовый URL шлюза Hermes, включая https:// для удалённых.',
|
||
remoteUrlPlaceholder: 'https://gateway.example.com/hermes',
|
||
probing: 'Определяем аутентификацию шлюза...',
|
||
probeError: 'Не удалось подключиться к этому шлюзу Hermes.',
|
||
identityProvider: 'ваш провайдер аутентификации',
|
||
authTitle: 'Аутентификация',
|
||
authNeedsOauth: provider => `Сначала войдите через ${provider}, чтобы проверить этот шлюз.`,
|
||
authSignedIn: 'Вход через браузер завершён.',
|
||
connected: 'Подключено',
|
||
signIn: 'Войти',
|
||
signInWith: provider => `Войти через ${provider}`,
|
||
enterUrlFirst: 'Сначала введите URL шлюза.',
|
||
signInIncomplete: 'Окно входа закрылось до завершения аутентификации.',
|
||
tokenTitle: 'Сессионный токен',
|
||
tokenDesc: 'Вставьте сессионный токен из файла .env удалённого шлюза.',
|
||
pasteSessionToken: 'Вставьте сессионный токен',
|
||
incompleteSignInTest: 'Войдите, чтобы проверить этот шлюз с OAuth-защитой.',
|
||
incompleteTokenTest: 'Введите сессионный токен, чтобы проверить этот шлюз.',
|
||
testConnection: 'Проверить соединение',
|
||
testSucceeded: (baseUrl, version) => `Подключено к ${baseUrl}${version ? ` (${version})` : ''}.`,
|
||
applyRemote: 'Применить и переподключиться',
|
||
backToSetup: 'Назад',
|
||
failedTitle: 'Установка не удалась',
|
||
settingUpTitle: 'Настройка Hermes Agent',
|
||
finishingTitle: 'Завершаем',
|
||
failedDesc:
|
||
'Один из шагов установки завершился ошибкой. На Windows это может произойти, если запущена другая инстанция Hermes CLI или desktop. Остановите все работающие инстанции Hermes и повторите. Подробности — ниже или в журнале desktop.',
|
||
activeDesc:
|
||
'Это одноразовая настройка. Установщик Hermes скачивает зависимости и настраивает вашу машину. При следующих запусках этот шаг будет пропущен.',
|
||
progress: (completed, total) => `Выполнено ${completed} из ${total} шагов`,
|
||
currentStage: stage => ` — сейчас: ${stage}`,
|
||
fetchingManifest: 'Загружаем манифест установщика...',
|
||
error: 'Ошибка',
|
||
hideOutput: 'Скрыть вывод установщика',
|
||
showOutput: 'Показать вывод установщика',
|
||
lines: count => `${count} ${RU_PLURAL(count, 'строка', 'строки', 'строк')}`,
|
||
noOutput: 'Вывода пока нет.',
|
||
cancelling: 'Отмена...',
|
||
cancelInstall: 'Отменить установку',
|
||
transcriptSaved: 'Полный транскрипт сохранён в',
|
||
copiedOutput: 'Скопировано!',
|
||
copyOutput: 'Копировать вывод',
|
||
reloadRetry: 'Перезагрузить и повторить'
|
||
},
|
||
onboarding: {
|
||
headerTitle: 'Настроим для вас Hermes Agent',
|
||
headerDesc: 'Подключите провайдера модели, чтобы начать общение. Большинство вариантов — в один клик.',
|
||
preparingInstall: 'Hermes завершает установку. Обычно это занимает меньше минуты при первом запуске.',
|
||
starting: 'Запускаем Hermes…',
|
||
lookingUpProviders: 'Ищем провайдеров...',
|
||
collapse: 'Свернуть',
|
||
otherProviders: 'Другие провайдеры',
|
||
haveApiKey: 'У меня есть API-ключ',
|
||
chooseLater: 'Выберу провайдера позже',
|
||
recommended: 'Рекомендуется',
|
||
connected: 'Подключено',
|
||
featuredPitch: 'Одна подписка, 300+ передовых моделей — рекомендуемый способ запускать Hermes',
|
||
fireworksPitch: 'Прямой API моделей — передовые модели на хостинге Fireworks',
|
||
openRouterPitch: 'Один ключ, сотни моделей — надёжный вариант по умолчанию',
|
||
apiKeyOptions: {
|
||
fireworks: {
|
||
short: 'прямой API моделей',
|
||
description: 'Прямой доступ к моделям на хостинге Fireworks AI.'
|
||
},
|
||
openrouter: {
|
||
short: 'один ключ, много моделей',
|
||
description: 'Сотни моделей за одним ключом. Хороший вариант по умолчанию для новых установок.'
|
||
},
|
||
openai: { short: 'модели класса GPT', description: 'Прямой доступ к моделям OpenAI.' },
|
||
gemini: { short: 'модели Gemini', description: 'Прямой доступ к моделям Google Gemini.' },
|
||
xai: { short: 'модели Grok', description: 'Прямой доступ к моделям xAI Grok.' },
|
||
local: {
|
||
short: 'self-hosted',
|
||
description:
|
||
'Укажите Hermes локальный или self-hosted OpenAI-совместимый endpoint (vLLM, llama.cpp, Ollama и т.д.).'
|
||
}
|
||
},
|
||
backToSignIn: 'Назад ко входу',
|
||
getKey: 'Получить ключ',
|
||
replaceCurrent: 'Заменить текущее значение',
|
||
pasteApiKey: 'Вставьте API-ключ',
|
||
localApiKeyPlaceholder: 'API-ключ (необязательно — только если ваш endpoint его требует)',
|
||
couldNotSave: 'Не удалось сохранить учётные данные.',
|
||
connecting: 'Подключение',
|
||
update: 'Обновить',
|
||
flowSubtitles: {
|
||
pkce: 'Откроет браузер для входа, затем продолжит здесь',
|
||
device_code: 'Откроет страницу подтверждения в браузере — Hermes подключится автоматически',
|
||
external: 'Войдите один раз в терминале, затем вернитесь в чат'
|
||
},
|
||
startingSignIn: provider => `Начинаем вход для ${provider}...`,
|
||
verifyingCode: provider => `Проверяем ваш код через ${provider}...`,
|
||
connectedProvider: provider => `${provider} подключён`,
|
||
connectedPicking: provider => `${provider} подключён. Выбираем модель по умолчанию...`,
|
||
signInFailed: 'Вход не удался. Попробуйте снова.',
|
||
pickDifferentProvider: 'Выбрать другого провайдера',
|
||
signInWith: provider => `Войти через ${provider}`,
|
||
openedBrowser: provider => `Мы открыли ${provider} в вашем браузере.`,
|
||
authorizeThere: 'Авторизуйте Hermes там.',
|
||
copyAuthCode: 'Скопируйте код авторизации и вставьте его ниже.',
|
||
pasteAuthCode: 'Вставьте код авторизации',
|
||
reopenAuthPage: 'Открыть страницу авторизации снова',
|
||
autoBrowser: provider =>
|
||
`Мы открыли ${provider} в вашем браузере. Авторизуйте Hermes там, и подключение произойдёт автоматически — ничего копировать и вставлять не нужно.`,
|
||
reopenSignInPage: 'Открыть страницу входа снова',
|
||
waitingAuthorize: 'Ждём вашей авторизации...',
|
||
externalPending: provider =>
|
||
`${provider} входит через собственный CLI. Выполните эту команду в терминале, затем вернитесь и выберите «Я вошёл»:`,
|
||
signedIn: 'Я вошёл',
|
||
deviceCodeOpened: provider => `Мы открыли ${provider} в вашем браузере. Введите там этот код:`,
|
||
reopenVerification: 'Открыть страницу подтверждения снова',
|
||
copy: 'Копировать',
|
||
defaultModel: 'Модель по умолчанию',
|
||
freeTier: 'Бесплатный тариф',
|
||
pro: 'Pro',
|
||
free: 'Free',
|
||
price: (input, output) => `${input} вход / ${output} выход за Mtok`,
|
||
change: 'Изменить',
|
||
startChatting: 'Начать',
|
||
docs: provider => `Документация ${provider}`
|
||
},
|
||
modelPicker: {
|
||
title: 'Сменить модель',
|
||
current: 'текущая:',
|
||
unknown: '(неизвестно)',
|
||
search: 'Фильтр провайдеров и моделей...',
|
||
noModels: 'Модели не найдены.',
|
||
addProvider: 'Добавить провайдера',
|
||
loadFailed: 'Не удалось загрузить модели',
|
||
noAuthenticatedProviders: 'Нет провайдеров с аутентификацией.',
|
||
pro: 'Pro',
|
||
proNeedsSubscription: 'Модели Pro требуют платной подписки Nous.',
|
||
free: 'Free',
|
||
freeTier: 'Бесплатный тариф',
|
||
priceTitle: 'Цена вход / выход за миллион токенов',
|
||
wasPrice: 'было'
|
||
},
|
||
|
||
modelVisibility: {
|
||
title: 'Модели',
|
||
search: 'Поиск моделей',
|
||
noAuthenticatedProviders: 'Нет провайдеров с аутентификацией.',
|
||
addProvider: 'Добавить провайдера…'
|
||
},
|
||
shell: {
|
||
windowControls: 'Управление окном',
|
||
paneControls: 'Управление панелями',
|
||
appControls: 'Управление приложением',
|
||
modelMenu: {
|
||
search: 'Поиск моделей',
|
||
noModels: 'Модели не найдены',
|
||
editModels: 'Изменить модели…',
|
||
refreshModels: 'Обновить модели',
|
||
fast: 'Быстрая'
|
||
},
|
||
modelOptions: {
|
||
noOptions: 'Для этой модели нет опций',
|
||
options: 'Опции',
|
||
thinking: 'Размышление',
|
||
fast: 'Быстрая',
|
||
effort: 'Усилия',
|
||
minimal: 'Минимально',
|
||
low: 'Низкое',
|
||
medium: 'Среднее',
|
||
high: 'Высокое',
|
||
xhigh: 'Очень высокое',
|
||
max: 'Максимум',
|
||
ultra: 'Ультра',
|
||
updateFailed: 'Не удалось обновить опцию модели',
|
||
fastFailed: 'Не удалось обновить быстрый режим'
|
||
},
|
||
gatewayMenu: {
|
||
gateway: 'Шлюз',
|
||
connected: 'Подключён',
|
||
connecting: 'Подключение',
|
||
offline: 'Недоступен',
|
||
inferenceReady: 'Инференс готов',
|
||
inferenceNotReady: 'Инференс не готов',
|
||
checkingInference: 'Проверка инференса',
|
||
disconnected: 'Отключён',
|
||
reconnectGateway: 'Переподключить шлюз',
|
||
openSystem: 'Открыть системную панель',
|
||
connection: label => `Соединение: ${label}`,
|
||
recentActivity: 'Недавняя активность',
|
||
viewAllLogs: 'Все журналы →',
|
||
messagingPlatforms: 'Платформы сообщений'
|
||
},
|
||
approvalMode: {
|
||
title: 'Режим подтверждения',
|
||
ariaLabel: mode => `Режим подтверждения: ${mode}`,
|
||
manual: 'Ручной',
|
||
manualDescription: 'Спрашивать перед действиями, требующими подтверждения',
|
||
smart: 'Умный',
|
||
smartDescription: 'Автоматически оценивать действия и спрашивать при необходимости',
|
||
off: 'Выкл',
|
||
offDescription: 'Выполнять без запросов подтверждения'
|
||
},
|
||
statusbar: {
|
||
unknown: 'неизвестно',
|
||
restart: 'перезапуск',
|
||
update: 'обновление',
|
||
updateInProgress: 'Обновление выполняется',
|
||
commitsBehind: (count, branch) => `${count} ${RU_NOUN(count, 'коммит', 'коммита', 'коммитов')} позади ${branch}`,
|
||
desktopVersion: version => `Hermes Desktop v${version}`,
|
||
backendVersion: version => `Бэкенд v${version}`,
|
||
clientLabel: version => `клиент v${version}`,
|
||
connectionSsh: host => `SSH: ${host}`,
|
||
connectionRemote: host => `Удалённый: ${host}`,
|
||
connectionCloud: host => `Облако: ${host}`,
|
||
connectionCloudTooltip: host => `Hermes Cloud · ${host}`,
|
||
connectionSshTooltip: host => `SSH · ${host}`,
|
||
connectionRemoteTooltip: host => `Удалённый · ${host}`,
|
||
backendLabel: version => `бэкенд v${version}`,
|
||
commit: sha => `коммит ${sha}`,
|
||
branch: branch => `ветка ${branch}`,
|
||
closeCommandCenter: 'Закрыть командный центр',
|
||
openCommandCenter: 'Открыть командный центр',
|
||
showTerminal: 'Показать терминал',
|
||
hideTerminal: 'Скрыть терминал',
|
||
gateway: 'Шлюз',
|
||
gatewayReady: 'готов',
|
||
gatewayNeedsSetup: 'нужна настройка',
|
||
gatewayChecking: 'проверка',
|
||
gatewayConnecting: 'подключение',
|
||
gatewayOffline: 'недоступен',
|
||
gatewayRestarting: 'перезапуск…',
|
||
gatewayTitle: 'Шлюз',
|
||
customizeTitle: 'Показывать в статус-баре',
|
||
hideStatusbar: 'Скрыть статус-бар',
|
||
resetStatusbar: 'Сбросить к значениям по умолчанию',
|
||
toggleApprovalMode: 'Подтверждения',
|
||
toggleBackendVersion: 'Версия бэкенда',
|
||
toggleCacheHitRate: 'Попадания в кэш',
|
||
toggleCommandCenter: 'Командный центр',
|
||
toggleContextUsage: 'Шкала контекста',
|
||
toggleRunningTimer: 'Таймер хода',
|
||
toggleSessionTimer: 'Таймер сеанса',
|
||
toggleTerminal: 'Терминал',
|
||
toggleTokensPerSecond: 'Токенов в секунду',
|
||
toggleVersion: 'Версия и обновления',
|
||
toggleWorkspace: 'Рабочее пространство',
|
||
cacheHitRateTitle: 'Доля попаданий в кэш промпта за сеанс — кэшированные токены дешевле, чем выше, тем дешевле',
|
||
tokensPerSecondTitle: 'Выходных токенов в секунду, среднее за последние 10 вызовов модели',
|
||
agents: 'Агенты',
|
||
closeAgents: 'Закрыть агентов',
|
||
openAgents: 'Открыть агентов',
|
||
subagents: count => `${count} ${RU_PLURAL(count, 'субагент', 'субагента', 'субагентов')}`,
|
||
failed: count => `${count} ${RU_NOUN(count, 'сбой', 'сбоя', 'сбоев')}`,
|
||
running: count => `${count} ${RU_NOUN(count, 'выполняется', 'выполняются', 'выполняется')}`,
|
||
cron: 'Cron',
|
||
openCron: 'Открыть cron-задачи',
|
||
webhooks: 'Вебхуки',
|
||
openWebhooks: 'Открыть вебхуки',
|
||
starmap: 'Граф памяти',
|
||
openStarmap: 'Открыть граф памяти',
|
||
turnRunning: 'Выполняется',
|
||
contextUsage: 'Использование контекста',
|
||
contextUsagePanel: {
|
||
categories: {
|
||
conversation: 'Диалог',
|
||
mcp: 'MCP',
|
||
memory: 'Память',
|
||
rules: 'Правила',
|
||
skills: 'Навыки',
|
||
subagent_definitions: 'Определения субагентов',
|
||
system_prompt: 'Системный промпт',
|
||
tool_definitions: 'Определения инструментов'
|
||
},
|
||
empty: 'Данных контекста пока нет',
|
||
loading: 'Загрузка разбивки…',
|
||
percentFull: percent => `${percent}% занято`,
|
||
title: 'Использование контекста',
|
||
tokenSummary: (used, max) => `${used} / ${max} токенов`
|
||
},
|
||
session: 'Сеанс',
|
||
yoloOn: 'YOLO включён — автоматическое подтверждение опасных команд. Shift-клик переключает глобально.',
|
||
yoloOff: 'YOLO выключен. Shift-клик переключает глобально.',
|
||
modelNone: 'нет',
|
||
noModel: 'модель не выбрана',
|
||
switchModel: 'Сменить модель',
|
||
openModelPicker: 'Открыть выбор модели',
|
||
modelPinned: 'закреплено вами; новые чаты используют её вместо модели по умолчанию из настроек',
|
||
modelTitle: (provider, model) => `Модель · ${provider}: ${model}`,
|
||
providerModelTitle: (provider, model) => `${provider} · ${model}`
|
||
}
|
||
},
|
||
rightSidebar: {
|
||
aria: 'Правая боковая панель',
|
||
panelsAria: 'Панели правой боковой панели',
|
||
files: 'Файловая система',
|
||
terminal: 'Терминал',
|
||
noFolderSelected: 'Папка не выбрана',
|
||
changeCwdTitle: 'Изменить рабочий каталог',
|
||
remotePickerTitle: 'Выбрать удалённую папку',
|
||
remotePickerDescription: 'Просмотрите папки на подключённом бэкенде.',
|
||
remotePickerSelect: 'Выбрать папку',
|
||
folderTip: cwd => cwd,
|
||
openFolder: 'Открыть папку',
|
||
refreshTree: 'Обновить дерево',
|
||
collapseAll: 'Свернуть все папки',
|
||
previewUnavailable: 'Предпросмотр недоступен',
|
||
couldNotPreview: path => `Не удалось предпросмотреть ${path}`,
|
||
noProjectTitle: 'Проект не открыт',
|
||
noProjectBody: 'Откройте проект, чтобы просматривать его файлы и проверять изменения.',
|
||
noProjectOpen: 'Проект не открыт',
|
||
noDiffs: 'Нет изменений',
|
||
unreadableTitle: 'Недоступно',
|
||
unreadableBody: error => `Не удалось прочитать эту папку (${error}).`,
|
||
emptyTitle: 'Пусто',
|
||
emptyBody: 'Эта папка пуста.',
|
||
treeErrorTitle: 'Ошибка дерева',
|
||
treeErrorBody: 'Дерево файлов столкнулось с ошибкой при отображении этой папки.',
|
||
tryAgain: 'Попробовать снова',
|
||
loadingTree: 'Загрузка дерева файлов',
|
||
loadingFiles: 'Загрузка файлов',
|
||
terminalHide: 'Скрыть терминал',
|
||
terminalsAria: 'Терминалы',
|
||
terminalNew: 'Новый терминал',
|
||
terminalCloseOthers: 'Закрыть другие',
|
||
terminalCloseAll: 'Закрыть все',
|
||
addToChat: 'Добавить в чат'
|
||
},
|
||
preview: {
|
||
tab: 'Предпросмотр',
|
||
closePane: 'Закрыть панель предпросмотра',
|
||
loading: 'Загрузка предпросмотра',
|
||
unavailable: 'Предпросмотр недоступен',
|
||
opening: 'Открываем...',
|
||
hide: 'Скрыть',
|
||
openPreview: 'Открыть предпросмотр',
|
||
openInBrowser: 'Открыть в браузере',
|
||
linkHint: '⌘/Ctrl-клик — панель предпросмотра',
|
||
sourceLineTitle: 'Клик — выбрать · Shift-клик — расширить · перетащите в композер',
|
||
source: 'ИСТОЧНИК',
|
||
renderedPreview: 'ПРЕДПРОСМОТР',
|
||
diff: 'DIFF',
|
||
unknownSize: 'размер неизвестен',
|
||
binaryTitle: 'Похоже на бинарный файл',
|
||
binaryBody: label => `Предпросмотр ${label} может показать нечитаемый текст.`,
|
||
largeTitle: 'Этот файл большой',
|
||
largeBody: (label, size) => `${label} — ${size}. Hermes покажет только первые 512 КБ.`,
|
||
previewAnyway: 'Предпросмотр всё равно',
|
||
truncated: 'Показаны первые 512 КБ.',
|
||
noInlineTitle: 'Нет inline-предпросмотра',
|
||
noInlineBody: mimeType => `${mimeType || 'Этот тип файла'} всё равно можно прикрепить как контекст.`,
|
||
edit: 'Изменить',
|
||
editing: 'Изменение',
|
||
unsavedChanges: 'Несохранённые изменения',
|
||
saveFailed: message => `Не удалось сохранить: ${message}`,
|
||
diskChangedTitle: 'Файл изменился на диске',
|
||
diskChangedBody:
|
||
'Этот файл изменился с момента открытия. Перезаписать его вашей версией или сбросить правки и перезагрузить?',
|
||
overwrite: 'Перезаписать',
|
||
discardReload: 'Сбросить и перезагрузить',
|
||
console: {
|
||
deselect: 'Снять выделение записи',
|
||
select: 'Выбрать запись',
|
||
copyFailed: 'Не удалось скопировать вывод консоли',
|
||
copyEntry: 'Скопировать эту запись',
|
||
sendEntry: 'Отправить эту запись в чат',
|
||
messages: count => `${count} ${RU_PLURAL(count, 'сообщение консоли', 'сообщения консоли', 'сообщений консоли')}`,
|
||
resize: 'Изменить размер консоли предпросмотра',
|
||
title: 'Консоль предпросмотра',
|
||
selected: count => `${count} ${count === 1 ? 'выделено' : 'выделено'}`,
|
||
sendToChat: 'Отправить в чат',
|
||
copySelected: 'Скопировать выбранное в буфер',
|
||
copyAll: 'Скопировать всё в буфер',
|
||
copy: 'Копировать',
|
||
clear: 'Очистить',
|
||
empty: 'Сообщений консоли пока нет.',
|
||
promptHeader: 'Консоль предпросмотра:',
|
||
sentTitle: 'Отправлено в чат',
|
||
sentMessage: count =>
|
||
`${count} ${RU_NOUN(count, 'запись лога', 'записи лога', 'записей лога')} добавлено в композер`
|
||
},
|
||
web: {
|
||
appFailedToBoot: 'Приложение предпросмотра не запустилось',
|
||
serverNotFound: 'Сервер не найден',
|
||
remoteLoopback:
|
||
'Этот адрес указывает на машину, на которой работает ваш агент, а не на эту. Панель браузера загружает страницы локально, поэтому для удалённого dev-сервера нужен порт-форвардинг или доступный hostname.',
|
||
failedToLoad: 'Не удалось загрузить предпросмотр',
|
||
tryAgain: 'Попробовать снова',
|
||
restarting: 'Hermes перезапускается...',
|
||
askRestart: 'Попросить Hermes перезапустить сервер',
|
||
lookingRestart: taskId => `Hermes ищет сервер предпросмотра для перезапуска (${taskId})`,
|
||
restartingTitle: 'Перезапуск сервера предпросмотра',
|
||
restartingMessage: 'Hermes работает в фоне. Следите за прогрессом в консоли предпросмотра.',
|
||
startRestartFailed: message => `Не удалось запустить перезапуск сервера: ${message}`,
|
||
restartFailed: 'Перезапуск сервера не удался',
|
||
hideConsole: 'Скрыть консоль предпросмотра',
|
||
showConsole: 'Показать консоль предпросмотра',
|
||
hideDevTools: 'Скрыть DevTools предпросмотра',
|
||
openDevTools: 'Открыть DevTools предпросмотра',
|
||
goBack: 'Назад',
|
||
goForward: 'Вперёд',
|
||
reload: 'Перезагрузить страницу',
|
||
address: 'Адрес',
|
||
addressPlaceholder: 'Введите адрес',
|
||
blankPageBody: 'Введите адрес выше, чтобы просматривать, или попросите Hermes открыть страницу.',
|
||
finishedRestarting: message => `Hermes завершил перезапуск сервера предпросмотра${message ? `: ${message}` : ''}`,
|
||
failedRestarting: message => `Перезапуск сервера не удался: ${message}`,
|
||
unknownError: 'неизвестная ошибка',
|
||
restartedTitle: 'Сервер предпросмотра перезапущен',
|
||
reloadingNow: 'Перезагружаем предпросмотр.',
|
||
restartFailedTitle: 'Перезапуск предпросмотра не удался',
|
||
restartFailedMessage: 'Hermes не смог перезапустить сервер.',
|
||
stillWorking:
|
||
'Hermes всё ещё работает, но результата перезапуска пока нет. Команда сервера может выполняться в foreground.',
|
||
workspaceReloading: 'Рабочее пространство изменилось, перезагружаем предпросмотр',
|
||
fileChanged: url => `Файл изменился, перезагружаем предпросмотр: ${url}`,
|
||
filesChanged: (count, url) =>
|
||
`${count} ${RU_NOUN(count, 'изменение файла', 'изменения файла', 'изменений файла')}, перезагружаем предпросмотр: ${url}`,
|
||
watchFailed: message => `Не удалось отслеживать файл предпросмотра: ${message}`,
|
||
moduleMimeDescription:
|
||
'Модульные скрипты раздаются с неверным MIME-типом. Обычно это значит, что статический файл-сервер раздаёт Vite/React-приложение вместо dev-сервера проекта.',
|
||
loadFailedConsole: (code, message) => `Не удалось загрузить${code ? ` (${code})` : ''}: ${message}`,
|
||
unreachableDescription: 'Страница предпросмотра недоступна.',
|
||
openTarget: url => `Открыть ${url}`,
|
||
fallbackTitle: 'Предпросмотр'
|
||
}
|
||
},
|
||
zones: {
|
||
showTabStrip: 'Показать вкладки',
|
||
hideTabStrip: 'Скрыть вкладки',
|
||
showStripTab: title => `Показать ${title}`,
|
||
hideStripTab: title => `Скрыть ${title}`,
|
||
lastTabKeptTitle: 'Последняя вкладка остаётся',
|
||
lastTabKeptBody:
|
||
'В этой зоне нужна хотя бы одна видимая вкладка. Сначала покажите другую вкладку или сверните всю боковую панель.',
|
||
toggleStripTab: title => `Переключить вкладку ${title}`,
|
||
minimize: 'Свернуть',
|
||
restore: 'Восстановить',
|
||
closeRunningTitle: 'Закрыть работающую вкладку?',
|
||
closeRunningBody:
|
||
'Этот чат ещё работает (или ждёт вашего ввода). Закрытие вкладки скроет его — сеанс сохранит прогресс и можно будет открыть снова из боковой панели.',
|
||
closeRunningConfirm: 'Закрыть вкладку',
|
||
reload: 'Перезагрузить',
|
||
closeOthers: 'Закрыть другие',
|
||
closeToRight: 'Закрыть справа',
|
||
closeAll: 'Закрыть все',
|
||
newSessionTab: 'Вкладка нового сеанса',
|
||
pluginDisabled: pluginId => `Плагин «${pluginId}» отключён`,
|
||
pluginDisabledBody: 'Включите его снова в Возможности → Плагины, чтобы вернуть панель.',
|
||
missingPane: paneId => `нет панели: ${paneId}`,
|
||
editTitle: 'Раскладки',
|
||
editHint: 'Выберите раскладку или перетащите панели между зонами.',
|
||
reset: 'Сбросить',
|
||
templates: 'Шаблоны',
|
||
custom: 'Свои',
|
||
newGridLayout: 'Новая сеточная раскладка',
|
||
saveCurrentAs: 'Сохранить текущую расстановку как шаблон',
|
||
nameLayoutPlaceholder: 'Название этой раскладки…',
|
||
deletePreset: name => `Удалить ${name}`,
|
||
zoneEditorTitle: 'Редактор зон',
|
||
editorHintPre: 'клик — разделить · ',
|
||
editorHintPost:
|
||
' переворачивает линию · перетаскивание между зонами — слить · перетаскивание общих граней — изменить размер',
|
||
templateColumns: 'Колонки',
|
||
templateRows: 'Строки',
|
||
templateGrid: 'Сетка',
|
||
templatePriority: 'Приоритет',
|
||
zoneTag: index => `зона ${index}`,
|
||
mergeZones: count => `Слить ${count} ${RU_NOUN(count, 'зона', 'зоны', 'зон')}`,
|
||
customZoneName: count => `Своя ${count}-зонная`,
|
||
layoutNamePlaceholder: fallback => `Название раскладки (${fallback})`,
|
||
saveApply: 'Сохранить и применить',
|
||
notExpressible: 'эта расстановка зацеплена (pinwheel) — пока не выразима как вложенные разделения',
|
||
zoneCount: count => `${count} ${RU_NOUN(count, 'зона', 'зоны', 'зон')}`,
|
||
tabCount: count => `${count} ${RU_NOUN(count, 'вкладка', 'вкладки', 'вкладок')}`
|
||
},
|
||
contextMenu: {
|
||
link: {
|
||
openInApp: 'Открыть во встроенном браузере',
|
||
openExternal: 'Открыть во внешнем браузере',
|
||
copyUrl: 'Копировать URL',
|
||
copyResolvedUrl: 'Копировать разрешённый URL'
|
||
},
|
||
image: {
|
||
copyImage: 'Копировать изображение',
|
||
copyImageAddress: 'Копировать адрес изображения',
|
||
saveImageAs: 'Сохранить изображение как…'
|
||
},
|
||
edit: {
|
||
cut: 'Вырезать',
|
||
paste: 'Вставить',
|
||
selectAll: 'Выделить всё',
|
||
addToDictionary: 'Добавить в словарь'
|
||
},
|
||
page: {
|
||
copyPageUrl: 'Копировать URL страницы',
|
||
inspectElement: 'Исследовать элемент'
|
||
}
|
||
},
|
||
assistant: {
|
||
thread: {
|
||
loadingSession: 'Загрузка сеанса',
|
||
showEarlier: 'Показать ранние сообщения',
|
||
loadingResponse: 'Hermes загружает ответ',
|
||
resumeWhenBackgroundDone: count =>
|
||
count === 1
|
||
? 'Продолжится, когда фоновая задача завершится'
|
||
: `Продолжится, когда ${count} ${RU_NOUN(count, 'фоновая задача', 'фоновые задачи', 'фоновых задач')} завершатся`,
|
||
thinking: 'Думает',
|
||
thought: 'Помыслил',
|
||
thoughtBriefly: 'Кратко подумал',
|
||
thoughtFor: duration => `Думал ${duration}`,
|
||
turnDuration: duration => `Этот ход занял ${duration}`,
|
||
today: time => `Сегодня, ${time}`,
|
||
yesterday: time => `Вчера, ${time}`,
|
||
copy: 'Копировать',
|
||
refresh: 'Обновить',
|
||
moreActions: 'Ещё действия',
|
||
branchNewChat: 'Ветка в новый чат',
|
||
react: 'Реакция',
|
||
dismissError: 'Скрыть ошибку',
|
||
filesChanged: count => `${count} ${RU_PLURAL(count, 'файл изменён', 'файла изменено', 'файлов изменено')}`,
|
||
reviewChanges: 'Проверить',
|
||
readAloudFailed: 'Не удалось зачитать вслух',
|
||
preparingAudio: 'Подготовка аудио...',
|
||
stopReading: 'Остановить чтение',
|
||
readAloud: 'Зачитать вслух',
|
||
editMessage: 'Изменить сообщение',
|
||
expandMessage: 'Развернуть сообщение',
|
||
scrollToBottom: 'Прокрутить вниз',
|
||
stop: 'Стоп',
|
||
restorePrevious: 'Восстановить предыдущий чекпоинт',
|
||
restoreCheckpoint: 'Восстановить чекпоинт',
|
||
restoreFromHere: 'Восстановить чекпоинт — запустить снова с этого промпта',
|
||
restoreTitle: 'Восстановить до этого чекпоинта?',
|
||
restoreBody: 'Всё, что было после этого промпта, будет удалено из разговора, и промпт запустится снова отсюда.',
|
||
restoreConfirm: 'Восстановить и запустить',
|
||
restoreNext: 'Восстановить следующий чекпоинт',
|
||
goForward: 'Двигаться вперёд',
|
||
sendEdited: 'Отправить изменённое сообщение',
|
||
attachingFile: 'Прикрепление…'
|
||
},
|
||
approval: {
|
||
gatewayDisconnected: 'Шлюз Hermes не подключён',
|
||
sendFailed: 'Не удалось отправить ответ на подтверждение',
|
||
run: 'Выполнить',
|
||
command: 'Команда',
|
||
moreOptions: 'Больше опций подтверждения',
|
||
allowSession: 'Разрешить в этом сеансе',
|
||
alwaysAllowMenu: 'Всегда разрешать…',
|
||
jumpToApproval: 'Нужно подтверждение',
|
||
reject: 'Отклонить',
|
||
alwaysTitle: 'Всегда разрешать эту команду?',
|
||
alwaysDescription: pattern =>
|
||
`Это добавит паттерн «${pattern}» в ваш постоянный список разрешений (~/.hermes/config.yaml). Hermes больше не будет спрашивать о подобных командах — ни в этом сеансе, ни в будущем.`,
|
||
alwaysAllow: 'Всегда разрешать'
|
||
},
|
||
clarify: {
|
||
notReady: 'Запрос уточнения ещё не готов',
|
||
gatewayDisconnected: 'Шлюз Hermes не подключён',
|
||
sendFailed: 'Не удалось отправить ответ на уточнение',
|
||
loadingQuestion: 'Загрузка вопроса…',
|
||
other: 'Другое (введите ответ)',
|
||
placeholder: 'Введите ваш ответ…',
|
||
skip: 'Пропустить',
|
||
skipped: 'Пропущено',
|
||
continueLabel: 'Продолжить',
|
||
confirmAndContinueLabel: 'Подтвердить и продолжить',
|
||
answeredBadge: 'Ответ дан',
|
||
questionProgress: (answered, total) => `Ответ дан на ${answered} из ${total}`,
|
||
lateAnswer: (question, choice) => `Re: «${question}» — мой ответ: ${choice}`,
|
||
lateAnswerTip: 'Составить этот ответ как продолжение',
|
||
lateAnswerHint: 'Этот промпт больше не ждёт. Выберите вариант, чтобы составить его как сообщение-продолжение.'
|
||
},
|
||
mcpSetup: {
|
||
installTitle: server => `Добавить MCP-сервер ${server}?`,
|
||
enableTitle: server => `Включить MCP-сервер ${server}?`,
|
||
authorizeTitle: server => `Авторизовать MCP-сервер ${server}?`,
|
||
installAction: 'Установить',
|
||
enableAction: 'Включить',
|
||
authorizeAction: 'Авторизовать',
|
||
decline: 'Не сейчас',
|
||
declined: 'Отклонено',
|
||
installed: server => `${server} установлен`,
|
||
enabled: server => `${server} включён`,
|
||
authorized: server => `${server} авторизован`,
|
||
failed: server => `Настройка не удалась для ${server}`,
|
||
unanswered: 'Нет ответа',
|
||
toolCount: count => `${count} ${RU_NOUN(count, 'инструмент', 'инструмента', 'инструментов')}`,
|
||
notInCatalog: server => `«${server}» нет в MCP-каталоге`,
|
||
catalogSource: 'Из каталога, одобренного Nous',
|
||
envRequired: 'Сначала заполните обязательные учётные данные',
|
||
sendFailed: 'Не удалось отправить ответ на настройку MCP',
|
||
reloadFailed: 'Сервер сохранён, но перезагрузка MCP-инструментов не удалась — они загрузятся в следующем сеансе',
|
||
gatewayDisconnected: 'Шлюз Hermes не подключён'
|
||
},
|
||
tool: {
|
||
copyCode: 'Копировать код',
|
||
renderingImage: 'Рендеринг изображения',
|
||
copyOutput: 'Копировать вывод',
|
||
copyCommand: 'Копировать команду',
|
||
copyContent: 'Копировать содержимое',
|
||
copyUrl: 'Копировать URL',
|
||
copyResults: 'Копировать результаты',
|
||
copyQuery: 'Копировать запрос',
|
||
copyFile: 'Копировать файл',
|
||
copyPath: 'Копировать путь',
|
||
outputAlt: 'Вывод инструмента',
|
||
rawResponse: 'Сырой ответ',
|
||
copyActivity: 'Копировать активность',
|
||
recoveredOne: 'Восстановлено после 1 неудачного шага',
|
||
recoveredMany: count =>
|
||
`Восстановлено после ${count} ${RU_NOUN(count, 'неудачного шага', 'неудачных шагов', 'неудачных шагов')}`,
|
||
failedOne: '1 шаг не удался',
|
||
failedMany: count => `${count} ${RU_NOUN(count, 'шаг не удался', 'шага не удалось', 'шагов не удалось')}`,
|
||
statusRunning: 'Выполняется',
|
||
statusError: 'Ошибка',
|
||
statusRecovered: 'Восстановлено',
|
||
statusDone: 'Готово',
|
||
memoryWriteNoted: 'Запись в память отмечена',
|
||
actions: {
|
||
read: 'Чтение',
|
||
reading: 'Читает',
|
||
opened: 'Открыто',
|
||
opening: 'Открывает',
|
||
failedToOpen: 'Не удалось открыть',
|
||
searched: 'Поиск выполнен',
|
||
searching: 'Ищет',
|
||
ran: 'Выполнено',
|
||
running: 'Выполняется',
|
||
ranCode: 'Код выполнен',
|
||
runningCode: 'Скриптинг'
|
||
},
|
||
prefixes: {
|
||
browser: 'Браузер',
|
||
web: 'Web'
|
||
},
|
||
titleTemplates: {
|
||
actionCommand: (action, command) => `${action} ${command}`,
|
||
actionQuoted: (action, value) => `${action} «${value}»`,
|
||
actionTarget: (action, target) => `${action} ${target}`,
|
||
prefixedDone: (prefix, action) => `${prefix} ${action}`,
|
||
runningPrefixedTool: (prefix, action) => `Выполняется: ${prefix.toLowerCase()} ${action.toLowerCase()}`,
|
||
runningTool: action => `Выполняется: ${action.toLowerCase()}`
|
||
},
|
||
titles: {
|
||
browser_click: {
|
||
done: 'Нажат элемент страницы',
|
||
pending: 'Нажимаю элемент страницы',
|
||
pendingAction: 'Нажимаю'
|
||
},
|
||
browser_fill: { done: 'Заполнено поле формы', pending: 'Заполняю поле формы', pendingAction: 'Заполняю' },
|
||
browser_navigate: { done: 'Открыта страница', pending: 'Открываю страницу', pendingAction: 'Открываю' },
|
||
browser_snapshot: {
|
||
done: 'Снят снимок страницы',
|
||
pending: 'Снимаю страницу',
|
||
pendingAction: 'Снимаю'
|
||
},
|
||
browser_take_screenshot: {
|
||
done: 'Снят скриншот',
|
||
pending: 'Снимаю скриншот',
|
||
pendingAction: 'Снимаю'
|
||
},
|
||
browser_type: { done: 'Введено на странице', pending: 'Ввожу на странице', pendingAction: 'Ввожу' },
|
||
clarify: { done: 'Задан вопрос', pending: 'Задаю вопрос', pendingAction: 'Задаю' },
|
||
cronjob: { done: 'Cron-задача', pending: 'Планирую cron-задачу', pendingAction: 'Планирую' },
|
||
edit_file: { done: 'Файл изменён', pending: 'Изменяю файл', pendingAction: 'Изменяю' },
|
||
execute_code: { done: 'Код выполнен', pending: 'Скриптинг', pendingAction: 'Скриптинг' },
|
||
image_generate: {
|
||
done: 'Изображение сгенерировано',
|
||
pending: 'Генерирую изображение',
|
||
pendingAction: 'Генерирую'
|
||
},
|
||
list_files: { done: 'Файлы перечислены', pending: 'Перечисляю файлы', pendingAction: 'Перечисляю' },
|
||
memory: { done: 'Сохранено в память', pending: 'Сохраняю в память', pendingAction: 'Сохраняю' },
|
||
patch: { done: 'Файл патчен', pending: 'Патчу файл', pendingAction: 'Патчу' },
|
||
read_file: { done: 'Файл прочитан', pending: 'Читаю файл', pendingAction: 'Читаю' },
|
||
search_files: { done: 'Файлы найдены', pending: 'Ищу файлы', pendingAction: 'Ищу' },
|
||
session_search_recall: {
|
||
done: 'История сеансов найдена',
|
||
pending: 'Ищу в истории сеансов',
|
||
pendingAction: 'Ищу'
|
||
},
|
||
terminal: { done: 'Команда выполнена', pending: 'Выполняю команду', pendingAction: 'Выполняю' },
|
||
todo: { done: 'Todo обновлены', pending: 'Обновляю todo', pendingAction: 'Обновляю' },
|
||
vision_analyze: {
|
||
done: 'Изображение проанализировано',
|
||
pending: 'Анализирую изображение',
|
||
pendingAction: 'Анализирую'
|
||
},
|
||
web_extract: { done: 'Веб-страница прочитана', pending: 'Читаю веб-страницу', pendingAction: 'Читаю' },
|
||
web_search: { done: 'Поиск в вебе выполнен', pending: 'Ищу в вебе', pendingAction: 'Ищу' },
|
||
write_file: { done: 'Файл изменён', pending: 'Изменяю файл', pendingAction: 'Изменяю' }
|
||
}
|
||
}
|
||
},
|
||
prompts: {
|
||
gatewayDisconnected: 'Шлюз Hermes не подключён',
|
||
sudoSendFailed: 'Не удалось отправить пароль sudo',
|
||
secretSendFailed: 'Не удалось отправить секрет',
|
||
sudoTitle: 'Пароль администратора',
|
||
sudoDesc:
|
||
'Hermes нужен ваш пароль sudo, чтобы выполнить команду с повышенными правами. Он отправляется только вашему локальному агенту.',
|
||
sudoPlaceholder: 'пароль sudo',
|
||
secretTitle: 'Требуется секрет',
|
||
secretDesc: 'Hermes нужны учётные данные, чтобы продолжить.',
|
||
secretPlaceholder: 'значение секрета'
|
||
},
|
||
desktop: {
|
||
audioReadFailed: 'Не удалось прочитать записанное аудио',
|
||
sessionUnavailable: 'Сеанс недоступен',
|
||
createSessionFailed: 'Не удалось создать новый сеанс',
|
||
promptFailed: 'Промпт не удался',
|
||
providerCredentialRequired: 'Добавьте учётные данные провайдера перед отправкой первого сообщения.',
|
||
emptySlashCommand: 'пустая слэш-команда',
|
||
desktopCommands: 'Команды desktop',
|
||
skillCommandsAvailable: count =>
|
||
`${count} ${RU_NOUN(count, 'команда навыка', 'команды навыка', 'команд навыка')} доступно.`,
|
||
warningLine: message => `предупреждение: ${message}`,
|
||
yoloArmed: 'YOLO включён для этого чата',
|
||
yoloOff: 'YOLO выключен',
|
||
yoloSystem: active => `YOLO ${active ? 'включён' : 'выключен'} для этого сеанса`,
|
||
yoloTitle: 'YOLO',
|
||
yoloToggleFailed: 'Не удалось переключить YOLO',
|
||
profileStatus: current =>
|
||
`Профиль: ${current}. Используйте /profile <name> или выборку «Новый сеанс», чтобы начать чат в другом профиле.`,
|
||
unknownProfile: 'Неизвестный профиль',
|
||
noProfileNamed: (target, available) => `Нет профиля «${target}». Доступны: ${available}`,
|
||
newChatsProfile: name => `Новые чаты будут использовать профиль ${name}.`,
|
||
setProfileFailed: 'Не удалось установить профиль',
|
||
sttDisabled: 'Распознавание речи отключено в настройках.',
|
||
stopFailed: 'Остановка не удалась',
|
||
regenerateFailed: 'Повторная генерация не удалась',
|
||
editFailed: 'Изменение не удалось',
|
||
editTurnUnavailable: 'Этого хода больше нет в истории сервера (возможно, он был сжат).',
|
||
resumeFailed: 'Возобновление не удалось',
|
||
resumeStrandedTitle: 'Не удалось загрузить этот сеанс',
|
||
resumeStrandedBody:
|
||
'Соединение с этим сеансом оборвалось, и автоматические повторные попытки исчерпаны. Проверьте, что шлюз работает, и попробуйте снова.',
|
||
resumeRetry: 'Повторить',
|
||
nothingToBranch: 'Нечего ветвить',
|
||
branchNeedsChat: 'Начните или возобновите чат перед ветвлением.',
|
||
sessionBusy: 'Сеанс занят',
|
||
branchStopCurrent: 'Остановите текущий ход перед ветвлением этого чата.',
|
||
branchNoText: 'В этом сообщении нет текста, от которого можно ответвить.',
|
||
branchTitle: n => `Черновик: Ветка #${n}`,
|
||
branchFailed: 'Ветвление не удалось',
|
||
deleteFailed: 'Удаление не удалось',
|
||
archived: 'В архиве',
|
||
archiveFailed: 'Архивирование не удалось',
|
||
cwdChangeFailed: 'Изменение рабочего каталога не удалось',
|
||
cwdStagedTitle: 'Рабочий каталог поставлен в очередь',
|
||
cwdStagedMessage: 'Перезапустите бэкенд desktop, чтобы применить изменения cwd к этому активному сеансу.',
|
||
modelSwitchFailed: 'Смена модели не удалась',
|
||
sessionExported: 'Сеанс экспортирован',
|
||
sessionExportFailed: 'Не удалось экспортировать сеанс',
|
||
imageSaved: 'Изображение сохранено',
|
||
downloadStarted: 'Загрузка началась',
|
||
restartToUseSaveImage: 'Перезапустите Hermes Desktop, чтобы использовать «Сохранить изображение».',
|
||
restartToSaveImages: 'Перезапустите Hermes Desktop, чтобы сохранять изображения',
|
||
imageDownloadFailed: 'Загрузка изображения не удалась',
|
||
openImage: 'Открыть изображение',
|
||
downloadImage: 'Скачать изображение',
|
||
savingImage: 'Сохранение изображения',
|
||
imagePreviewFailed: 'Предпросмотр изображения не удался',
|
||
imageAttach: 'Прикрепление изображения',
|
||
imageWriteFailed: 'Не удалось записать изображение на диск.',
|
||
imageAttachFailed: 'Прикрепление изображения не удалось',
|
||
attachImages: 'Прикрепить изображения',
|
||
clipboard: 'Буфер обмена',
|
||
noClipboardImage: 'Изображение в буфере обмена не найдено',
|
||
clipboardPasteFailed: 'Вставка из буфера обмена не удалась',
|
||
dropFiles: 'Перетащите файлы',
|
||
handoff: {
|
||
pickPlatform: 'Выберите назначение',
|
||
success: platform => `Передаём в ${platform}. Возобновите здесь в любой момент.`,
|
||
systemNote: platform => `↻ Передано в ${platform} — возобновите здесь в любой момент.`,
|
||
failed: error => `Передача не удалась: ${error}`,
|
||
timedOut: 'Превышено время ожидания шлюза. Выполняется ли `hermes gateway`?'
|
||
}
|
||
},
|
||
errors: {
|
||
genericFailure: 'Что-то пошло не так',
|
||
boundaryTitle: 'Что-то сломалось в интерфейсе',
|
||
boundaryDesc: 'Вид столкнулся с неожиданной ошибкой. Ваши чаты и настройки в безопасности.',
|
||
reloadWindow: 'Перезагрузить окно',
|
||
openLogs: 'Открыть журналы'
|
||
},
|
||
|
||
ui: {
|
||
search: {
|
||
clear: 'Очистить поиск'
|
||
},
|
||
pagination: {
|
||
label: 'пагинация',
|
||
previous: 'Назад',
|
||
previousAria: 'Перейти на предыдущую страницу',
|
||
next: 'Дальше',
|
||
nextAria: 'Перейти на следующую страницу'
|
||
},
|
||
sidebar: {
|
||
title: 'Боковая панель',
|
||
description: 'Показывает мобильную боковую панель.',
|
||
toggle: open => `${open ? 'Показать' : 'Скрыть'} боковую панель`
|
||
}
|
||
}
|
||
})
|