* feat: auto-poll Docker capabilities while Docker tab is active
When the Docker tab is visible and hasDocker is not yet true,
poll refreshCapabilities() at the process refresh interval.
Stop polling once hasDocker becomes true, or when switching
to a different tab.
* fix: use resolvedTab instead of activeTab for Docker auto-poll condition
The auto-poll useEffect condition used activeTab, which stays stale
when Docker becomes unavailable. Changed to resolvedTab which reflects
the actual displayed tab. Also updated the dep array.
* fix: replace setInterval with setTimeout recursion in Docker tab probe
Replace setInterval-based polling with setTimeout recursion in the Docker
tab capability probe effect. This ensures the next probe only starts after
the previous one finishes, avoiding overlapping probes when SSH timeout
exceeds the polling interval.
- Add dockerPollTimerRef to track the timeout handle
- Use async pollOnce() that awaits refreshCapabilities() before scheduling next
- Use cancelled flag in cleanup to prevent scheduling after unmount
- Keep same dependency array for correctness
* fix: stabilize docker poll timer by using useRef for refreshCapabilities
refreshCapabilities() can return a new reference on every render, causing
the useEffect to re-run on every render — cleanup cancels the polling timer,
then the effect immediately calls pollOnce(), effectively bypassing the
configured timeout interval.
Fix: store refreshCapabilities in a useRef (refreshRef), use
refreshRef.current() inside pollOnce(), and replace refreshCapabilities
with refreshRef in the useEffect dependency array.
Closes #PR1456 Codex P2 review item.
* fix: delay auto-poll first probe by one interval to avoid overlap with tab-switch probe
When switching to the Docker tab, two mechanisms were triggering probes:
1. tab-switch effect (line 67-76): immediate probe via refreshCapabilities()
2. auto-poll effect: pollOnce() executing immediately on mount
This caused duplicate probes that waste SSH channel resources.
Fix: pollOnce() no longer fires on mount. Instead, the effect schedules the
first probe with setTimeout(pollOnce, capabilitiesTtlMs), so the first probe
happens after one full interval. Subsequent probes continue at interval pace
via the setTimeout recursion in pollOnce itself.
The tab-switch effect still fires the immediate probe (the correct one),
so responsiveness on tab switch is preserved.
* fix: reset cancelledRef in effect body to prevent permanent stalling of Docker polling
The cancelledRef was set to true in the cleanup function when dependencies
changed, but never reset when the effect re-ran. This caused pollOnce to
always early-return on subsequent timer ticks, permanently halting
Docker capability probing after the first dependency change.
* fix(system-manager): replace cancelledRef with closure variables for per-effect cancellation
Each effect generation now has its own and closure
variables instead of shared / . This
prevents stale probes from surviving cleanup when the panel hides and
re-shows (Codex P2 review).
* fix: wrap refreshCapabilities in try/catch to keep polling on exception
If refreshCapabilities throws (instead of returning {success: false}),
the await would exit pollOnce without scheduling the next setTimeout,
silently killing Docker auto-detection polling.
* fix: add in-flight probe guard to prevent tab-switch and auto-poll concurrent probes
Add probingRef to track whether a capabilities probe is already in-flight.
- Tab-switch effect for Docker branch checks probingRef before starting a new probe
- Auto-poll pollOnce checks probingRef at entry and sets/clears it around the actual probe
- Tmux branch left unchanged as it has no auto-poll overlap risk
* fix: re-schedule next poll timer when probe is in-flight
When probingRef.current is true (tab-switch probe still running),
pollOnce was returning early without scheduling the next timer,
causing auto-poll to stop permanently afterward.
Now it schedules the next poll within the interval and returns,
so the polling loop keeps running until a slot where no probe is
active.
* fix: convert comments to ASCII-only English
- Line 105: translate Chinese comment to 'probe is in-flight, reschedule for next cycle'
- Line 113: replace em dash (U+2014) with ASCII dash
* feat: session inline rename, closeSession shortcut, pane zoom
* fix: sidebar inline rename with local state
* fix: add sessionDisplayName to terminalPropsAreEqual comparator
The Terminal component is wrapped with React.memo(…, terminalPropsAreEqual),
but the comparator was missing a check for sessionDisplayName. After renaming
a session, the pane title bar would show the old name until some other prop
changed and triggered a re-render.
Add prev.sessionDisplayName === next.sessionDisplayName to the comparator
so that display name changes cause the Terminal to re-render immediately.
* fix: add onStartSessionRename to TerminalLayerWorkspaceSection ctx destructuring and TerminalPanesHost props
* fix: add toggleWorkspaceViewMode to executeHotkeyActionImpl destructuring
The togglePaneZoom handler calls toggleWorkspaceViewMode() but it
wasn't destructured from getCtx(), causing a ReferenceError at runtime.
* fix: restore truncated ctx object in TerminalView render call
The TerminalView ctx object literal on line 1265 was truncated to
'showSele...' due to an editing tool truncation bug, causing
Parsing error: ',' expected on npm run lint / tsc --noEmit.
Restored the missing fields from the base commit:
showSelectionAIAction, snippets, status, statusDotTone, sudoHintRef,
sudoHintText: t("terminal.sudoHint.pressEnter"), t, termRef,
terminalBackend, terminalContextActions, terminalCwdTracker,
terminalPreviewVars, terminalSettings, timeLeft, toast, zmodem
Kept the PR's new additions (isVisible, onRename, sessionDisplayName)
intact.
* fix: add toggleWorkspaceViewMode to executeHotkeyAction context and add terminal.menu.rename translations
- Add toggleWorkspaceViewMode to the context getter in executeHotkeyAction (App.tsx)
- Add terminal.menu.rename translation for en (Rename), zh-CN (重命名), ru (Переименовать)
* fix: validate focusedSessionId before closing in closeSession hotkey
When closeSession hotkey fires, workspace.focusedSessionId may reference
a session that was already closed by another trigger (e.g., mouse click
on tab close button). Collect alive session IDs from the workspace root
and fall back to the first living pane if the stored focusedSessionId
is stale.
* fix(auto-poll): check useSessionCapabilities probing state in pollOnce
When auto-poll timer fires before the initial probe (from
useSessionCapabilities) completes, probingRef.current is still false
because the initial probe doesn't set it — causing a second overlapping
probe.
Add check so that any in-flight probe from any path
(initial/auto-poll/tab-switch) prevents auto-poll overlap.
PR #1459
* fix: address remaining Codex review issues
Co-authored-by: Cursor <cursoragent@cursor.com>
* feat: add detach session from workspace with toolbar button and context menu
Co-authored-by: Cursor <cursoragent@cursor.com>
* fix: use customName in pane header display name for renamed sessions
Co-authored-by: Cursor <cursoragent@cursor.com>
* fix: refine workspace terminal detach interactions
* fix: preserve workspace detach tab ordering
---------
Co-authored-by: Cursor <cursoragent@cursor.com>
727 lines
58 KiB
TypeScript
727 lines
58 KiB
TypeScript
import type { Messages } from '../types';
|
||
|
||
export const ruTerminalMessages: Messages = {
|
||
'terminal.sudoHint.pressEnter': 'Нажмите Enter, чтобы вставить пароль sudo',
|
||
// Connection logs
|
||
'logs.table.date': 'Дата',
|
||
'logs.table.user': 'Пользователь',
|
||
'logs.table.host': 'Хост',
|
||
'logs.table.saved': 'Сохранено',
|
||
'logs.empty.title': 'Нет журналов подключений',
|
||
'logs.empty.desc':
|
||
'История ваших подключений будет отображаться здесь, когда вы подключаетесь к хостам или открываете локальные терминалы.',
|
||
'logs.loadMore': 'Загрузить ещё {count} журналов',
|
||
'logs.ongoing': 'в процессе',
|
||
'logs.localTerminal': 'Локальный терминал',
|
||
'logs.action.save': 'Сохранить',
|
||
'logs.action.unsave': 'Убрать из сохранённых',
|
||
'logs.action.delete': 'Удалить',
|
||
|
||
// Log view
|
||
'logView.customizeAppearance': 'Настроить внешний вид',
|
||
'logView.appearance': 'Внешний вид',
|
||
'logView.readOnly': 'Только чтение',
|
||
'logView.export': 'Экспорт',
|
||
|
||
// Terminal toolbar / search / context menu / auth
|
||
'terminal.toolbar.openSftp': 'Открыть SFTP',
|
||
'terminal.toolbar.availableAfterConnect': 'Доступно после подключения',
|
||
'terminal.toolbar.sendYmodem': 'Отправить через YMODEM',
|
||
'terminal.toolbar.receiveYmodem': 'Получить через YMODEM',
|
||
'terminal.toolbar.sftp': 'SFTP',
|
||
'terminal.toolbar.more': 'Другие действия',
|
||
'terminal.toolbar.scripts': 'Скрипты',
|
||
'terminal.toolbar.history': 'История команд',
|
||
'history.scope.label': 'Область истории',
|
||
'history.tab.host': 'Хост',
|
||
'history.tab.global': 'Глобальная',
|
||
'history.searchPlaceholder': 'Поиск по истории...',
|
||
'history.loading': 'Загрузка удалённой истории...',
|
||
'history.meta.count': '{count} команд',
|
||
'history.empty.noSession': 'Откройте удалённую сессию, чтобы просмотреть историю команд.',
|
||
'history.empty.unsupportedProtocol': 'История команд доступна только для сессий SSH/Mosh/ET.',
|
||
'history.empty.noHistory': 'История команд на этом хосте не найдена.',
|
||
'history.empty.noGlobalHistory': 'Глобальной истории команд пока нет. Выполненные команды появятся здесь.',
|
||
'history.action.refresh': 'Обновить',
|
||
'history.action.retry': 'Повторить',
|
||
'history.action.paste': 'Вставить в терминал',
|
||
'history.action.run': 'Выполнить в терминале',
|
||
'history.action.saveAsSnippet': 'Сохранить как сниппет',
|
||
'terminal.toolbar.library': 'Библиотека',
|
||
'terminal.toolbar.noSnippets': 'Нет доступных сниппетов',
|
||
'terminal.toolbar.terminalSettings': 'Настройки терминала',
|
||
'terminal.toolbar.searchTerminal': 'Поиск по терминалу',
|
||
'terminal.toolbar.search': 'Поиск',
|
||
'terminal.toolbar.timestampsEnable': 'Показать время',
|
||
'terminal.toolbar.timestampsDisable': 'Скрыть время',
|
||
'terminal.toolbar.broadcast': 'Трансляция',
|
||
'terminal.toolbar.broadcastEnable': 'Включить режим трансляции',
|
||
'terminal.toolbar.broadcastDisable': 'Отключить режим трансляции',
|
||
'terminal.toolbar.composeBar': 'Строка ввода',
|
||
'terminal.composeBar.placeholder': 'Введите команду здесь и нажмите Enter для отправки...',
|
||
'terminal.composeBar.send': 'Отправить',
|
||
'terminal.composeBar.close': 'Закрыть строку ввода',
|
||
'terminal.composeBar.broadcasting': 'Трансляция во все сессии',
|
||
'terminal.composeBar.resize': 'Изменить высоту строки ввода',
|
||
'terminal.composeBar.manageSnippets': 'Управление быстрыми сниппетами',
|
||
'terminal.composeBar.searchSnippets': 'Поиск сниппетов...',
|
||
'terminal.composeBar.noPinnedSnippets': 'Закрепите сниппеты через + для быстрого доступа',
|
||
'terminal.composeBar.noMatchingSnippets': 'Сниппеты не найдены',
|
||
'terminal.composeBar.pinnedCount': 'Закреплено: {count}',
|
||
'terminal.composeBar.unpinSnippet': 'Убрать {label} из панели',
|
||
'terminal.composeBar.snippetClickHint': 'Клик — вставить · Shift+клик — отправить',
|
||
'terminal.toolbar.focus': 'Фокус',
|
||
'terminal.toolbar.focusMode': 'Режим фокуса',
|
||
'terminal.toolbar.detach': 'Открепить в отдельную вкладку',
|
||
'terminal.toolbar.encoding': 'Кодировка терминала',
|
||
'terminal.toolbar.encoding.utf8': 'UTF-8',
|
||
'terminal.toolbar.encoding.gb18030': 'GB18030',
|
||
'terminal.toolbar.closeSession': 'Закрыть сессию',
|
||
'terminal.toolbar.hostHighlight.title': 'Подсветка ключевых слов хоста',
|
||
'terminal.toolbar.hostHighlight.noRules': 'Для этого хоста не задано пользовательских правил подсветки',
|
||
'terminal.toolbar.hostHighlight.addRule': 'Добавить новое правило',
|
||
'terminal.toolbar.hostHighlight.labelPlaceholder': 'Метка (например, Error)',
|
||
'terminal.toolbar.hostHighlight.patternPlaceholder': 'Regex-шаблон (например, \\bfailed\\b)',
|
||
'terminal.toolbar.hostHighlight.invalidPattern': 'Некорректный regex-шаблон',
|
||
'terminal.toolbar.hostHighlight.clearAll': 'Очистить все',
|
||
'terminal.toolbar.hostHighlight.changeColor': 'Изменить цвет подсветки для',
|
||
'terminal.toolbar.hostHighlight.selectColor': 'Выбрать цвет для нового правила',
|
||
'terminal.statusbar.copyHostname.label': 'Копировать адрес хоста',
|
||
'terminal.statusbar.copyHostname.tooltip': 'Копировать адрес хоста ({hostname})',
|
||
'terminal.statusbar.copyHostname.toast': 'Адрес хоста скопирован: {hostname}',
|
||
'terminal.statusbar.copyHostname.error': 'Не удалось скопировать адрес хоста в буфер обмена',
|
||
'terminal.serverStats.cpu': 'Использование CPU',
|
||
'terminal.serverStats.cpuCores': 'Использование ядер CPU',
|
||
'terminal.serverStats.memory': 'Использование памяти',
|
||
'terminal.serverStats.memoryDetails': 'Сведения о памяти',
|
||
'terminal.serverStats.memUsed': 'Использовано',
|
||
'terminal.serverStats.memBuffers': 'Буферы',
|
||
'terminal.serverStats.memCached': 'Кэш',
|
||
'terminal.serverStats.memFree': 'Свободно',
|
||
'terminal.serverStats.swap': 'Swap',
|
||
'terminal.serverStats.swapUsed': 'Использовано swap',
|
||
'terminal.serverStats.swapFree': 'Свободный swap',
|
||
'terminal.serverStats.swapTotal': 'Всего',
|
||
'terminal.serverStats.topProcesses': 'Топ процессов по памяти',
|
||
'terminal.serverStats.disk': 'Использование диска (корень)',
|
||
'terminal.serverStats.diskDetails': 'Смонтированные диски',
|
||
'terminal.serverStats.network': 'Скорость сети',
|
||
'terminal.serverStats.networkDetails': 'Сетевые интерфейсы',
|
||
'terminal.serverStats.noData': 'Данные недоступны',
|
||
'terminal.dragDrop.localTitle': 'Перетащите для вставки путей',
|
||
'terminal.dragDrop.localMessage': 'Пути к файлам будут вставлены в терминал',
|
||
'terminal.dragDrop.remoteTitle': 'Перетащите для загрузки файлов',
|
||
'terminal.dragDrop.remoteZmodemMessage': 'Файлы будут загружены через ZMODEM (PTY)',
|
||
'terminal.dragDrop.remoteSftpMessage': 'Файлы будут загружены через SFTP',
|
||
'terminal.dragDrop.noFiles': 'Нет файлов для загрузки',
|
||
'terminal.dragDrop.notConnected': 'Нельзя перетащить файлы — терминал не подключён',
|
||
'terminal.dragDrop.errorTitle': 'Ошибка перетаскивания',
|
||
'terminal.dragDrop.errorMessage': 'Не удалось обработать перетащенные файлы',
|
||
'terminal.search.placeholder': 'Поиск...',
|
||
'terminal.search.noResults': 'Ничего не найдено',
|
||
'terminal.search.prevMatch': 'Предыдущее совпадение (Shift+Enter)',
|
||
'terminal.search.nextMatch': 'Следующее совпадение (Enter)',
|
||
'terminal.menu.copy': 'Копировать',
|
||
'terminal.menu.paste': 'Вставить',
|
||
'terminal.menu.addSelectionToAI': 'Добавить в чат',
|
||
'terminal.menu.pasteSelection': 'Вставить выделенное',
|
||
'terminal.menu.selectAll': 'Выбрать всё',
|
||
'terminal.menu.reconnect': 'Переподключиться',
|
||
'terminal.menu.sendYmodem': 'Отправить через YMODEM',
|
||
'terminal.menu.receiveYmodem': 'Получить через YMODEM',
|
||
'terminal.menu.splitHorizontal': 'Разделить по горизонтали',
|
||
'terminal.menu.splitVertical': 'Разделить по вертикали',
|
||
'terminal.menu.clearBuffer': 'Очистить буфер',
|
||
'terminal.menu.closeTerminal': 'Закрыть терминал',
|
||
'terminal.menu.rename': 'Переименовать',
|
||
'terminal.menu.detach': 'Открепить из рабочей области',
|
||
'terminal.menu.detachSession': 'Открепить {name}',
|
||
'terminal.ymodem.selectFile': 'Выберите файл для отправки',
|
||
'terminal.ymodem.allFiles': 'Все файлы',
|
||
'terminal.ymodem.started': 'YMODEM отправляет {fileName}',
|
||
'terminal.ymodem.complete': 'YMODEM отправил {fileName}',
|
||
'terminal.ymodem.failed': 'Не удалось отправить через YMODEM',
|
||
'terminal.ymodem.selectReceiveDirectory': 'Выберите папку для полученных файлов',
|
||
'terminal.ymodem.receiveStarted': 'YMODEM получает...',
|
||
'terminal.ymodem.receiveComplete': 'YMODEM получил {fileName}',
|
||
'terminal.ymodem.receiveCompleteMultiple': 'YMODEM получил файлов: {count}',
|
||
'terminal.ymodem.receiveEmpty': 'Файлы YMODEM не получены',
|
||
'terminal.ymodem.receiveFailed': 'Не удалось получить через YMODEM',
|
||
'terminal.ymodem.unavailable': 'YMODEM недоступен',
|
||
'terminal.selection.addToAI': 'Добавить в чат',
|
||
'terminal.selection.addToAIDesc': 'Прикрепить выбранный вывод терминала к черновику AI',
|
||
'terminal.auth.password': 'Пароль',
|
||
'terminal.auth.sshKey': 'SSH-ключ',
|
||
'terminal.auth.username': 'Имя пользователя',
|
||
'terminal.auth.username.placeholder': 'root',
|
||
'terminal.auth.passwordLabel': 'Пароль',
|
||
'terminal.auth.password.placeholder': 'Введите пароль',
|
||
'terminal.auth.passphrase': 'Парольная фраза',
|
||
'terminal.auth.passphrase.placeholder': 'Необязательная парольная фраза для выбранного приватного ключа',
|
||
'terminal.auth.certificate': 'Сертификат',
|
||
'terminal.auth.selectKey': 'Выбрать ключ',
|
||
'terminal.auth.noKeysHint': 'Нет доступных ключей. Добавьте ключи в связке ключей.',
|
||
'terminal.auth.continueSave': 'Продолжить и сохранить',
|
||
'terminal.auth.credentialsUnavailable': 'Сохранённые учётные данные не могут быть расшифрованы на этом устройстве. Пожалуйста, введите и сохраните их заново.',
|
||
'terminal.auth.jumpCredentialsUnavailable': 'У jump-хоста сохранены учётные данные, которые нельзя расшифровать на этом устройстве. Откройте настройки хоста и введите их заново.',
|
||
'terminal.auth.proxyCredentialsUnavailable': 'Учётные данные прокси не могут быть расшифрованы на этом устройстве. Откройте настройки хоста и заново введите пароль прокси.',
|
||
'terminal.auth.keyUnavailableFallbackPassword': 'Сохранённый SSH-ключ недоступен на этом устройстве. Выполняется переход на аутентификацию по паролю.',
|
||
'terminal.progress.timeoutIn': 'Тайм-аут через {seconds}с',
|
||
'terminal.progress.disconnected': 'Отключено',
|
||
'terminal.progress.cancelling': 'Отмена...',
|
||
'terminal.progress.startOver': 'Начать заново',
|
||
'terminal.connection.dismissDisconnectedDialog': 'Закрыть уведомление об отключении',
|
||
'terminal.connection.chainOf': 'Цепочка {current} из {total}',
|
||
'terminal.connection.showLogs': 'Показать журналы',
|
||
'terminal.connection.hideLogs': 'Скрыть журналы',
|
||
'terminal.connection.protocol.ssh': 'SSH',
|
||
'terminal.connection.protocol.telnet': 'Telnet',
|
||
'terminal.connection.protocol.mosh': 'Mosh',
|
||
'terminal.connection.protocol.serial': 'Serial',
|
||
'terminal.connection.protocol.local': 'Локальная оболочка',
|
||
'terminal.hostKey.unknownTitle': 'Подтвердите этот ключ хоста',
|
||
'terminal.hostKey.changedTitle': 'Ключ хоста изменился',
|
||
'terminal.hostKey.unknownDescription': 'Подлинность {host} пока не может быть установлена.',
|
||
'terminal.hostKey.changedDescription': 'Сохранённый ключ для {host} больше не совпадает с этим сервером.',
|
||
'terminal.hostKey.fingerprintLabel': 'Отпечаток {keyType} — SHA256:',
|
||
'terminal.hostKey.savedFingerprintLabel': 'Сохранённый отпечаток',
|
||
'terminal.hostKey.unknownHint': 'Запомните его, если этот отпечаток принадлежит серверу, к которому вы ожидали подключиться.',
|
||
'terminal.hostKey.changedHint': 'Продолжайте только если вы ожидали, что этот хост изменится.',
|
||
'terminal.hostKey.addAndContinue': 'Добавить и продолжить',
|
||
'terminal.hostKey.updateAndContinue': 'Обновить и продолжить',
|
||
'terminal.themeModal.title': 'Внешний вид терминала',
|
||
'terminal.themeModal.tab.theme': 'Тема',
|
||
'terminal.themeModal.tab.font': 'Шрифт',
|
||
'terminal.themeModal.tab.custom': 'Пользовательское',
|
||
'terminal.themeModal.globalTheme': 'Глобальная тема',
|
||
'terminal.themeModal.globalFont': 'Глобальный шрифт',
|
||
'terminal.themeModal.fontSize': 'Размер шрифта',
|
||
'terminal.themeModal.fontWeight': 'Толщина шрифта',
|
||
'terminal.themeModal.livePreview': 'Предпросмотр в реальном времени',
|
||
'terminal.themeModal.themeType': 'Тема {type}',
|
||
'terminal.hiddenTheme.title': 'Текущая скрытая тема',
|
||
'terminal.hiddenTheme.desc': 'Эта тема скрыта из ручного выбора и будет заменена, когда вы выберете другую тему.',
|
||
'topTabs.toggleTheme.systemExitTitle': 'Активна системная тема',
|
||
'topTabs.toggleTheme.systemExitMessage': 'Откройте настройки, чтобы выбрать фиксированную светлую или тёмную тему.',
|
||
'topTabs.toggleTheme.openSettings': 'Открыть настройки',
|
||
|
||
// Custom Themes
|
||
'terminal.customTheme.section': 'Пользовательские темы',
|
||
'terminal.customTheme.yourThemes': 'Ваши темы',
|
||
'terminal.customTheme.new': 'Новая тема',
|
||
'terminal.customTheme.newDesc': 'Клонировать текущую тему и настроить её',
|
||
'terminal.customTheme.newTitle': 'Новая пользовательская тема',
|
||
'terminal.customTheme.editTitle': 'Редактировать тему',
|
||
'terminal.customTheme.import': 'Импорт .itermcolors',
|
||
'terminal.customTheme.importDesc': 'Импорт из файла цветовой схемы iTerm2',
|
||
'terminal.customTheme.importError': 'Не удалось разобрать выбранный файл. Убедитесь, что это корректный XML-файл .itermcolors.',
|
||
'terminal.customTheme.delete': 'Удалить тему',
|
||
'terminal.customTheme.confirmDelete': 'Подтвердить удаление',
|
||
'terminal.customTheme.name': 'Название',
|
||
'terminal.customTheme.namePlaceholder': 'Моя пользовательская тема',
|
||
'terminal.customTheme.type': 'Тип',
|
||
'terminal.customTheme.group.general': 'Общие',
|
||
'terminal.customTheme.group.normal': 'Обычные цвета',
|
||
'terminal.customTheme.group.bright': 'Яркие цвета',
|
||
'terminal.customTheme.color.background': 'Фон',
|
||
'terminal.customTheme.color.foreground': 'Текст',
|
||
'terminal.customTheme.color.cursor': 'Курсор',
|
||
'terminal.customTheme.color.selection': 'Выделение',
|
||
'terminal.customTheme.color.black': 'Чёрный',
|
||
'terminal.customTheme.color.red': 'Красный',
|
||
'terminal.customTheme.color.green': 'Зелёный',
|
||
'terminal.customTheme.color.yellow': 'Жёлтый',
|
||
'terminal.customTheme.color.blue': 'Синий',
|
||
'terminal.customTheme.color.magenta': 'Пурпурный',
|
||
'terminal.customTheme.color.cyan': 'Голубой',
|
||
'terminal.customTheme.color.white': 'Белый',
|
||
'terminal.customTheme.color.brightBlack': 'Яркий чёрный',
|
||
'terminal.customTheme.color.brightRed': 'Яркий красный',
|
||
'terminal.customTheme.color.brightGreen': 'Яркий зелёный',
|
||
'terminal.customTheme.color.brightYellow': 'Яркий жёлтый',
|
||
'terminal.customTheme.color.brightBlue': 'Яркий синий',
|
||
'terminal.customTheme.color.brightMagenta': 'Яркий пурпурный',
|
||
'terminal.customTheme.color.brightCyan': 'Яркий голубой',
|
||
'terminal.customTheme.color.brightWhite': 'Яркий белый',
|
||
|
||
// Cloud Sync Settings
|
||
'cloudSync.gate.title': 'Синхронизация с end-to-end шифрованием',
|
||
'cloudSync.gate.desc':
|
||
'Ваши данные шифруются локально перед синхронизацией. Облачные провайдеры никогда не видят ваши данные в открытом виде. Задайте мастер-ключ, чтобы включить безопасную синхронизацию.',
|
||
'cloudSync.gate.masterKey': 'Мастер-ключ',
|
||
'cloudSync.gate.confirmMasterKey': 'Подтвердите мастер-ключ',
|
||
'cloudSync.gate.placeholder': 'Введите надёжный пароль',
|
||
'cloudSync.gate.confirmPlaceholder': 'Подтвердите пароль',
|
||
'cloudSync.gate.mismatch': 'Пароли не совпадают',
|
||
'cloudSync.gate.warning':
|
||
'Я понимаю, что если забуду мастер-ключ, мои данные нельзя будет восстановить. Сброс пароля невозможен.',
|
||
'cloudSync.gate.enableVault': 'Включить зашифрованное хранилище',
|
||
'cloudSync.gate.enabledToast': 'Зашифрованное хранилище включено',
|
||
'cloudSync.gate.setupFailed': 'Не удалось настроить мастер-ключ',
|
||
'cloudSync.passwordStrength.tooShort': 'Слишком короткий',
|
||
'cloudSync.passwordStrength.weak': 'Слабый',
|
||
'cloudSync.passwordStrength.moderate': 'Средний',
|
||
'cloudSync.passwordStrength.strong': 'Сильный',
|
||
'cloudSync.passwordStrength.veryStrong': 'Очень сильный',
|
||
'cloudSync.provider.notConnected': 'Не подключено',
|
||
'cloudSync.provider.sync': 'Синхронизация',
|
||
'cloudSync.provider.connect': 'Подключить',
|
||
'cloudSync.provider.connecting': 'Подключение...',
|
||
'cloudSync.provider.webdav': 'WebDAV',
|
||
'cloudSync.provider.webdav.desc': 'Подключение к самостоятельно размещённому WebDAV endpoint',
|
||
'cloudSync.provider.s3': 'Совместимое с S3',
|
||
'cloudSync.provider.s3.desc': 'Подключение к объектному хранилищу, совместимому с S3',
|
||
'cloudSync.provider.comingSoon': 'Скоро',
|
||
'cloudSync.webdav.title': 'Настройки WebDAV',
|
||
'cloudSync.webdav.desc': 'Настройка WebDAV endpoint для зашифрованной синхронизации.',
|
||
'cloudSync.webdav.endpoint': 'URL endpoint',
|
||
'cloudSync.webdav.authType': 'Тип аутентификации',
|
||
'cloudSync.webdav.auth.basic': 'Basic',
|
||
'cloudSync.webdav.auth.digest': 'Digest',
|
||
'cloudSync.webdav.auth.token': 'Токен',
|
||
'cloudSync.webdav.username': 'Имя пользователя',
|
||
'cloudSync.webdav.password': 'Пароль',
|
||
'cloudSync.webdav.token': 'Токен',
|
||
'cloudSync.webdav.showSecret': 'Показать секрет',
|
||
'cloudSync.webdav.allowInsecure': 'Разрешить небезопасное соединение (игнорировать ошибки сертификата)',
|
||
'cloudSync.webdav.validation.endpoint': 'Введите корректный WebDAV endpoint.',
|
||
'cloudSync.webdav.validation.credentials': 'Имя пользователя и пароль обязательны.',
|
||
'cloudSync.webdav.validation.token': 'Токен обязателен.',
|
||
'cloudSync.s3.title': 'Настройки S3',
|
||
'cloudSync.s3.desc': 'Подключение к объектному хранилищу, совместимому с S3, для зашифрованной синхронизации.',
|
||
'cloudSync.s3.endpoint': 'URL endpoint',
|
||
'cloudSync.s3.region': 'Регион',
|
||
'cloudSync.s3.bucket': 'Бакет',
|
||
'cloudSync.s3.accessKeyId': 'ID ключа доступа',
|
||
'cloudSync.s3.secretAccessKey': 'Секретный ключ доступа',
|
||
'cloudSync.s3.sessionToken': 'Токен сессии (необязательно)',
|
||
'cloudSync.s3.prefix': 'Префикс ключа (необязательно)',
|
||
'cloudSync.s3.forcePathStyle': 'Принудительно использовать path-style URL (для MinIO/R2 и т. д.)',
|
||
'cloudSync.s3.showSecret': 'Показать секреты',
|
||
'cloudSync.s3.validation.required': 'Endpoint, регион, бакет, access key и secret обязательны.',
|
||
'cloudSync.smb.title': 'Настройки SMB',
|
||
'cloudSync.smb.desc': 'Подключение к файловой SMB/CIFS-шаре для зашифрованной синхронизации.',
|
||
'cloudSync.smb.share': 'Путь к шаре',
|
||
'cloudSync.smb.username': 'Имя пользователя',
|
||
'cloudSync.smb.password': 'Пароль',
|
||
'cloudSync.smb.domain': 'Домен (необязательно)',
|
||
'cloudSync.smb.domainPlaceholder': 'например, WORKGROUP',
|
||
'cloudSync.smb.port': 'Порт (необязательно)',
|
||
'cloudSync.smb.showSecret': 'Показать пароль',
|
||
'cloudSync.smb.validation.share': 'Путь к шаре обязателен.',
|
||
'cloudSync.smb.validation.port': 'Порт должен быть числом от 1 до 65535.',
|
||
'cloudSync.connect.smb.success': 'SMB успешно подключён',
|
||
'cloudSync.connect.smb.failedTitle': 'Ошибка подключения SMB',
|
||
'cloudSync.provider.smb': 'SMB-шара',
|
||
'cloudSync.connect.webdav.success': 'WebDAV успешно подключён',
|
||
'cloudSync.connect.webdav.failedTitle': 'Ошибка подключения WebDAV',
|
||
'cloudSync.connect.s3.success': 'S3 успешно подключён',
|
||
'cloudSync.connect.s3.failedTitle': 'Ошибка подключения S3',
|
||
'cloudSync.lastSync.never': 'Никогда',
|
||
'cloudSync.lastSync.justNow': 'Только что',
|
||
'cloudSync.lastSync.minutesAgo': '{minutes} мин назад',
|
||
'cloudSync.changeKey': 'Изменить ключ',
|
||
'cloudSync.providers.title': 'Облачные провайдеры',
|
||
'cloudSync.syncAll': 'Синхронизировать всех подключённых провайдеров',
|
||
'cloudSync.autoSync.title': 'Автосинхронизация',
|
||
'cloudSync.autoSync.desc': 'Автоматически синхронизировать при внесении изменений',
|
||
'cloudSync.strategy.title': 'Стратегия синхронизации',
|
||
'cloudSync.strategy.desc': 'Выберите, что делать, когда изменились и локальные, и облачные данные.',
|
||
'cloudSync.strategy.smartMerge': 'Умное объединение (рекомендуется)',
|
||
'cloudSync.strategy.smartMergeDesc': 'По возможности объединять изменения с обеих сторон; если Netcatty не сможет безопасно выбрать, он попросит вас решить вручную.',
|
||
'cloudSync.strategy.preferCloud': 'Приоритет облака',
|
||
'cloudSync.strategy.preferCloudDesc': 'Когда изменились обе стороны, скачать облачную версию и заменить локальные изменения.',
|
||
'cloudSync.strategy.preferLocal': 'Приоритет локальных данных',
|
||
'cloudSync.strategy.preferLocalDesc': 'Когда изменились обе стороны, загрузить локальную версию и заменить облачные изменения.',
|
||
'cloudSync.status.title': 'Статус синхронизации',
|
||
'cloudSync.status.localVersion': 'Локальная версия',
|
||
'cloudSync.status.remoteVersion': 'Удалённая версия',
|
||
'cloudSync.history.title': 'История синхронизации',
|
||
'cloudSync.history.upload': 'Загрузка',
|
||
'cloudSync.history.download': 'Скачивание',
|
||
'cloudSync.history.resolved': 'Разрешено',
|
||
'cloudSync.history.error': 'Ошибка',
|
||
'cloudSync.localBackups.title': 'История локальных резервных копий',
|
||
'cloudSync.localBackups.desc': 'Netcatty сохраняет локальные точки восстановления перед сменой версии приложения и перед восстановлением хранилища.',
|
||
'cloudSync.localBackups.retentionTitle': 'Хранение резервных копий',
|
||
'cloudSync.localBackups.retentionDesc': 'Выберите, сколько локальных резервных копий должен хранить Netcatty.',
|
||
'cloudSync.localBackups.maxCount': 'Макс. число копий',
|
||
'cloudSync.localBackups.maxSaved': 'Хранение резервных копий: {count}',
|
||
'cloudSync.localBackups.maxInvalid': 'Введите число от 1 до 100.',
|
||
'cloudSync.localBackups.empty': 'Локальных резервных копий пока нет.',
|
||
'cloudSync.localBackups.reason.appVersionChange': 'Перед сменой версии приложения',
|
||
'cloudSync.localBackups.reason.beforeRestore': 'Перед восстановлением',
|
||
'cloudSync.localBackups.versionChange': '{from} -> {to}',
|
||
'cloudSync.localBackups.counts': '{hosts} хостов, {keys} ключей, {snippets} сниппетов',
|
||
'cloudSync.localBackups.restore': 'Восстановить',
|
||
'cloudSync.localBackups.restoreSuccess': 'Локальная резервная копия восстановлена.',
|
||
'cloudSync.localBackups.restoreFailedTitle': 'Ошибка восстановления',
|
||
'cloudSync.localBackups.restoreMissing': 'Резервная копия не найдена.',
|
||
'cloudSync.localBackups.protectiveBackupFailed': 'Не удалось создать защитную резервную копию, поэтому восстановление было прервано для защиты ваших текущих данных. Устраните основную проблему (например, доступ к keychain) и попробуйте снова. Подробности: {message}',
|
||
'cloudSync.localBackups.restoreConfirmTitle': 'Восстановить эту резервную копию?',
|
||
'cloudSync.localBackups.restoreConfirmDesc': 'Ваши текущие хосты, ключи, сниппеты и настройки будут заменены содержимым этой резервной копии. Перед этим автоматически создаётся защитный снимок текущих данных.',
|
||
'cloudSync.localBackups.restoreConfirmButton': 'Восстановить',
|
||
'cloudSync.localBackups.restoreConfirmCancel': 'Отмена',
|
||
'cloudSync.localBackups.unavailableTitle': 'Локальные резервные копии недоступны',
|
||
'cloudSync.localBackups.unavailableDesc': 'Эта платформа не предоставляет Netcatty безопасное хранилище ключей, поэтому локальные резервные копии нельзя записывать безопасно. Установите Netcatty в систему с поддерживаемым keychain, чтобы включить историю локальных резервных копий.',
|
||
'cloudSync.localBackups.lockedTitle': 'Требуется мастер-ключ',
|
||
'cloudSync.localBackups.lockedDesc': 'Настройте или разблокируйте мастер-ключ перед восстановлением резервной копии, чтобы восстановленные учётные данные оставались зашифрованными.',
|
||
'cloudSync.revisionHistory.viewButton': 'История',
|
||
'cloudSync.revisionHistory.title': 'История версий хранилища',
|
||
'cloudSync.revisionHistory.description': 'Просматривайте и восстанавливайте предыдущие версии вашего хранилища из истории ревизий Gist.',
|
||
'cloudSync.revisionHistory.empty': 'Ревизии не найдены.',
|
||
'cloudSync.revisionHistory.current': 'Текущая',
|
||
'cloudSync.revisionHistory.revision': 'Ревизия',
|
||
'cloudSync.revisionHistory.revisionPreview': 'Содержимое ревизии',
|
||
'cloudSync.revisionHistory.device': 'Устройство',
|
||
'cloudSync.revisionHistory.hosts': 'Хосты',
|
||
'cloudSync.revisionHistory.keys': 'Ключи',
|
||
'cloudSync.revisionHistory.snippets': 'Сниппеты',
|
||
'cloudSync.revisionHistory.identities': 'Идентификаторы',
|
||
'cloudSync.revisionHistory.restoreButton': 'Восстановить эту версию',
|
||
'cloudSync.revisionHistory.restored': 'Хранилище восстановлено из выбранной ревизии.',
|
||
'cloudSync.revisionHistory.revisionNotFound': 'Ревизия не найдена или не содержит данных хранилища.',
|
||
'cloudSync.revisionHistory.decryptFailed': 'Не удалось расшифровать эту ревизию. Возможно, она была зашифрована другим мастер-паролем.',
|
||
'cloudSync.changeKey.title': 'Изменить мастер-ключ',
|
||
'cloudSync.changeKey.current': 'Текущий мастер-ключ',
|
||
'cloudSync.changeKey.new': 'Новый мастер-ключ',
|
||
'cloudSync.changeKey.confirmNew': 'Подтвердите новый мастер-ключ',
|
||
'cloudSync.changeKey.currentPlaceholder': 'Введите текущий мастер-ключ',
|
||
'cloudSync.changeKey.newPlaceholder': 'Введите новый мастер-ключ',
|
||
'cloudSync.changeKey.confirmPlaceholder': 'Подтвердите новый мастер-ключ',
|
||
'cloudSync.changeKey.fillAll': 'Пожалуйста, заполните все поля',
|
||
'cloudSync.changeKey.minLength': 'Новый мастер-ключ должен содержать не менее 8 символов',
|
||
'cloudSync.changeKey.notMatch': 'Новые мастер-ключи не совпадают',
|
||
'cloudSync.changeKey.incorrectCurrent': 'Неверный текущий мастер-ключ',
|
||
'cloudSync.changeKey.failed': 'Не удалось изменить мастер-ключ',
|
||
'cloudSync.changeKey.desc': 'Это заново зашифрует ваше хранилище. Убедитесь, что вы помните новый ключ.',
|
||
'cloudSync.changeKey.showKeys': 'Показать ключи',
|
||
'cloudSync.changeKey.updatedToast': 'Мастер-ключ обновлён',
|
||
'cloudSync.changeKey.updateButton': 'Обновить ключ',
|
||
'cloudSync.unlock.title': 'Введите мастер-ключ',
|
||
'cloudSync.unlock.masterKey': 'Мастер-ключ',
|
||
'cloudSync.unlock.desc':
|
||
'Введите мастер-ключ один раз, чтобы включить зашифрованную синхронизацию. Он будет безопасно сохранён в системном keychain.',
|
||
'cloudSync.unlock.placeholder': 'Введите мастер-ключ',
|
||
'cloudSync.unlock.empty': 'Пожалуйста, введите мастер-ключ',
|
||
'cloudSync.unlock.incorrect': 'Неверный мастер-ключ',
|
||
'cloudSync.unlock.failed': 'Не удалось разблокировать хранилище',
|
||
'cloudSync.unlock.showKey': 'Показать ключ',
|
||
'cloudSync.unlock.notNow': 'Не сейчас',
|
||
'cloudSync.unlock.readyToast': 'Хранилище готово',
|
||
'cloudSync.unlock.unlockButton': 'Разблокировать',
|
||
'cloudSync.header.vaultReady': 'Хранилище готово',
|
||
'cloudSync.header.preparingVault': 'Подготовка хранилища...',
|
||
'cloudSync.header.providersConnected': 'Подключено провайдеров: {count}',
|
||
'cloudSync.githubFlow.title': 'Подключить GitHub',
|
||
'cloudSync.githubFlow.desc': 'Скопируйте код ниже и введите его на GitHub, чтобы авторизовать Netcatty.',
|
||
'cloudSync.githubFlow.copyCode': 'Скопировать код',
|
||
'cloudSync.githubFlow.copied': 'Скопировано!',
|
||
'cloudSync.githubFlow.openGitHub': 'Открыть GitHub',
|
||
'cloudSync.githubFlow.waiting': 'Ожидание авторизации...',
|
||
'cloudSync.conflict.title': 'Обнаружен конфликт версий',
|
||
'cloudSync.conflict.desc': 'Выберите, какую версию сохранить',
|
||
'cloudSync.conflict.local': 'ЛОКАЛЬНАЯ',
|
||
'cloudSync.conflict.cloud': 'ОБЛАЧНАЯ',
|
||
'cloudSync.conflict.detailsTitle': 'Изменённые данные',
|
||
'cloudSync.conflict.detailsCounts': 'Локально {local} · Облако {cloud} · Конфликты {conflicts}',
|
||
'cloudSync.conflict.entity.hosts': 'Хосты',
|
||
'cloudSync.conflict.entity.keys': 'Ключи',
|
||
'cloudSync.conflict.entity.identities': 'Идентификаторы',
|
||
'cloudSync.conflict.entity.proxyProfiles': 'Профили прокси',
|
||
'cloudSync.conflict.entity.snippets': 'Сниппеты',
|
||
'cloudSync.conflict.entity.customGroups': 'Группы',
|
||
'cloudSync.conflict.entity.snippetPackages': 'Пакеты сниппетов',
|
||
'cloudSync.conflict.entity.portForwardingRules': 'Проброс портов',
|
||
'cloudSync.conflict.entity.groupConfigs': 'Настройки групп',
|
||
'cloudSync.conflict.entity.settings': 'Настройки',
|
||
'cloudSync.conflict.keepLocal': 'Перезаписать облако (сохранить локальную)',
|
||
'cloudSync.conflict.useCloud': 'Скачать из облака (перезаписать локальную)',
|
||
'cloudSync.connect.browserContinue': 'Завершите авторизацию в браузере',
|
||
'cloudSync.connect.browserCancelled': 'Предыдущая авторизация в браузере была отменена',
|
||
'cloudSync.connect.github.success': 'GitHub успешно подключён',
|
||
'cloudSync.connect.github.failedTitle': 'Ошибка подключения GitHub',
|
||
'cloudSync.connect.github.timeout': 'Время подключения к GitHub истекло. Проверьте сеть или настройки прокси.',
|
||
'cloudSync.connect.github.networkError': 'Не удалось связаться с GitHub. Проверьте сеть или настройки прокси.',
|
||
'cloudSync.connect.google.failedTitle': 'Ошибка подключения Google',
|
||
'cloudSync.connect.onedrive.failedTitle': 'Ошибка подключения OneDrive',
|
||
'cloudSync.sync.success': 'Синхронизировано с {provider}',
|
||
'cloudSync.sync.failed': 'Синхронизация не удалась',
|
||
'cloudSync.sync.failedTitle': 'Синхронизация не удалась',
|
||
'cloudSync.sync.errorTitle': 'Ошибка синхронизации',
|
||
'cloudSync.resolve.downloaded': 'Скачаны данные из облака',
|
||
'cloudSync.resolve.uploaded': 'Загружены локальные данные',
|
||
'cloudSync.resolve.failedTitle': 'Не удалось разрешить конфликт',
|
||
'cloudSync.clearLocal.title': 'Очистить локальные данные',
|
||
'cloudSync.clearLocal.desc': 'Сбросить локальную версию и историю синхронизации. При следующей синхронизации данные будут скачаны из облака.',
|
||
'cloudSync.clearLocal.button': 'Очистить',
|
||
'cloudSync.clearLocal.dialog.title': 'Очистить локальные данные хранилища?',
|
||
'cloudSync.clearLocal.dialog.desc': 'Локальная версия будет сброшена до 0, а история синхронизации очищена. При следующей синхронизации данные будут скачаны из облака и заменят локальные.',
|
||
'cloudSync.clearLocal.dialog.cancel': 'Отмена',
|
||
'cloudSync.clearLocal.dialog.confirm': 'Очистить локальные данные',
|
||
'cloudSync.clearLocal.toast.title': 'Локальные данные очищены',
|
||
'cloudSync.clearLocal.toast.desc': 'Локальная версия сброшена до 0. Выполните синхронизацию для загрузки из облака.',
|
||
|
||
// Keychain
|
||
'keychain.filter.key': 'Ключ',
|
||
'keychain.filter.certificate': 'Сертификат',
|
||
'keychain.action.generateKey': 'Создать ключ',
|
||
'keychain.action.importKey': 'Импорт. ключ',
|
||
'keychain.action.newIdentity': 'Новый ид-катор',
|
||
'keychain.action.importCertificate': 'Импорт. сертификат',
|
||
'keychain.view.grid': 'Сетка',
|
||
'keychain.view.list': 'Список',
|
||
'keychain.section.keys': 'Ключи',
|
||
'keychain.section.identities': 'Идентификаторы',
|
||
'keychain.count.items': '{count} запис(ей)',
|
||
'keychain.empty.title': 'Настройте свои ключи',
|
||
'keychain.empty.desc': 'Импортируйте или создайте SSH-ключи для безопасной аутентификации.',
|
||
'keychain.panel.generateKey': 'Сгенерировать ключ',
|
||
'keychain.panel.newKey': 'Новый ключ',
|
||
'keychain.panel.keyDetails': 'Сведения о ключе',
|
||
'keychain.panel.editKey': 'Редактировать ключ',
|
||
'keychain.panel.editIdentity': 'Редактировать идентификатор',
|
||
'keychain.panel.newIdentity': 'Новый идентификатор',
|
||
'keychain.panel.keyExport': 'Экспорт ключа',
|
||
'keychain.validation.labelRequired': 'Пожалуйста, введите метку для ключа',
|
||
'keychain.validation.labelAndPrivateKeyRequired': 'Метка и приватный ключ обязательны',
|
||
'keychain.validation.labelAndUsernameRequired': 'Метка и имя пользователя обязательны',
|
||
'keychain.error.generationUnavailable': 'Генератор ключей не работает - пожалуйста, убедитесь, что приложение работает в Electron',
|
||
'keychain.error.generateKeyPairFailed': 'Не удалось сгенерировать пару ключей',
|
||
'keychain.error.generateKeyFailed': 'Не удалось сгенерировать ключ',
|
||
'keychain.error.keyGenerationTitle': 'Генерация ключа',
|
||
'keychain.export.exportTo': 'Экспортировать в *',
|
||
'keychain.export.selectHost': 'Выберите хост',
|
||
'keychain.export.location': 'Расположение ~ $1 *',
|
||
'keychain.export.filename': 'Имя файла ~ $2 *',
|
||
'keychain.export.note': 'Экспорт ключей сейчас поддерживается только в системах {unix}. Используйте раздел {advanced} для настройки скрипта экспорта.',
|
||
'keychain.export.script': 'Скрипт *',
|
||
'keychain.export.scriptPlaceholder': 'Скрипт экспорта...',
|
||
'keychain.export.missingCredentials': 'У хоста нет сохранённого пароля или ключа. Сначала добавьте в хост учётные данные с паролем.',
|
||
'keychain.export.successTitle': 'Экспорт выполнен успешно',
|
||
'keychain.export.successMessage': 'Публичный ключ экспортирован и привязан к {host}',
|
||
'keychain.export.failedTitle': 'Ошибка экспорта',
|
||
'keychain.export.failedMessage': 'Не удалось экспортировать ключ: {error}',
|
||
'keychain.export.failedPrefix': 'Ошибка экспорта: {error}',
|
||
'keychain.export.exitCode': 'Команда завершилась с кодом {code}',
|
||
'keychain.export.exporting': 'Экспорт...',
|
||
'keychain.export.exportAndAttach': 'Экспортировать и привязать',
|
||
'keychain.export.title': 'Экспорт ключа',
|
||
'keychain.export.exportToRequired': 'Экспортировать в *',
|
||
'keychain.export.selectHostPlaceholder': 'Выберите хост...',
|
||
'keychain.export.locationLabel': 'Расположение ~ $1 *',
|
||
'keychain.export.filenameLabel': 'Имя файла ~ $2 *',
|
||
'keychain.export.advanced': 'Дополнительно',
|
||
'keychain.export.note.supportsOnly': 'Экспорт ключей сейчас поддерживается только в',
|
||
'keychain.export.note.systems': 'системах.',
|
||
'keychain.export.note.use': 'Используйте',
|
||
'keychain.export.note.customize': 'раздел для настройки скрипта экспорта.',
|
||
'keychain.export.scriptRequired': 'Скрипт *',
|
||
'keychain.export.exportToHost': 'Экспортировать на хост',
|
||
'keychain.export.failedGeneric': 'Ошибка экспорта: {message}',
|
||
'keychain.field.label': 'Метка',
|
||
'keychain.field.labelRequired': 'Метка *',
|
||
'keychain.field.labelPlaceholder': 'Метка ключа',
|
||
'keychain.field.privateKeyRequired': 'Приватный ключ *',
|
||
'keychain.field.publicKey': 'Публичный ключ',
|
||
'keychain.field.certificatePlaceholder': 'Содержимое сертификата (необязательно)',
|
||
'keychain.generate.keyType': 'Тип ключа',
|
||
'keychain.generate.keySize': 'Размер ключа',
|
||
'keychain.generate.labelPlaceholder': 'Метка ключа',
|
||
'keychain.generate.passphrasePlaceholder': 'Парольная фраза (необязательно)',
|
||
'keychain.generate.savePassphrase': 'Сохранить парольную фразу',
|
||
'keychain.generate.generate': 'Сгенерировать',
|
||
'keychain.generate.generateSave': 'Сгенерировать и сохранить',
|
||
'keychain.import.dropHint': 'Перетащите сюда файл ключа',
|
||
'keychain.import.importFromFile': 'Импортировать из файла',
|
||
'keychain.import.saveKey': 'Сохранить ключ',
|
||
'keychain.import.importedKeyLabel': 'Импортированный ключ',
|
||
'keychain.identity.usernameRequired': 'Имя пользователя *',
|
||
'keychain.identity.method.passwordOnly': 'Пароль',
|
||
'keychain.identity.summary.password': 'Пароль аутентификации',
|
||
'keychain.identity.summary.key': 'Ключ аутентификации',
|
||
'keychain.identity.summary.certificate': 'Сертификат аутентификации',
|
||
'keychain.identity.summary.passwordAndKey': 'Пароль и ключ аутентификации',
|
||
'keychain.identity.summary.passwordAndCertificate': 'Пароль и сертификат аутентификации',
|
||
'keychain.identity.summary.none': 'Нет учётных данных',
|
||
'keychain.identity.selectCredential': 'Выберите {kind}',
|
||
'keychain.identity.save': 'Сохранить',
|
||
'keychain.identity.update': 'Обновить',
|
||
'keychain.keyDialog.newTitle': 'Новый ключ',
|
||
'keychain.keyDialog.newDesc': 'Добавить новый SSH-ключ',
|
||
'keychain.keyDialog.editTitle': 'Редактировать ключ',
|
||
'keychain.keyDialog.editDesc': 'Обновить этот SSH-ключ',
|
||
'keychain.keyDialog.updateKey': 'Обновить ключ',
|
||
|
||
// Tabs
|
||
'tabs.closeSessionAria': 'Закрыть сессию',
|
||
'tabs.closeLogViewAria': 'Закрыть просмотр журнала',
|
||
'tabs.logPrefix': 'Журнал:',
|
||
'tabs.logLocal': 'Локальный',
|
||
'tabs.copyTab': 'Копировать вкладку',
|
||
'tabs.copyTabToNewWindow': 'Копировать вкладку в новое окно',
|
||
'tabs.copyTabToNewWindowFailed': 'Не удалось открыть вкладку в новом окне',
|
||
'tabs.closeOthers': 'Закрыть остальные',
|
||
'tabs.closeToRight': 'Закрыть вкладки справа',
|
||
'tabs.closeAll': 'Закрыть все',
|
||
'keychain.edit.labelRequired': 'Метка *',
|
||
'keychain.edit.keyLabelPlaceholder': 'Метка ключа',
|
||
'keychain.edit.privateKeyRequired': 'Приватный ключ *',
|
||
'keychain.edit.publicKey': 'Публичный ключ',
|
||
'keychain.edit.certificate': 'Сертификат',
|
||
'keychain.edit.certificatePlaceholder': 'Содержимое сертификата (необязательно)',
|
||
'keychain.edit.filePath': 'Путь к файлу',
|
||
'keychain.edit.keyExport': 'Экспорт ключа',
|
||
'keychain.edit.exportToHost': 'Экспортировать на хост',
|
||
|
||
// Snippets
|
||
'snippets.searchPlaceholder': 'Поиск сниппетов...',
|
||
'snippets.action.newSnippet': 'Новый сниппет',
|
||
'snippets.action.newPackage': 'Новый пакет',
|
||
'snippets.panel.newTitle': 'Новый сниппет',
|
||
'snippets.panel.editTitle': 'Редактировать сниппет',
|
||
'snippets.field.description': 'Описание действия',
|
||
'snippets.field.descriptionPlaceholder': 'Например: проверить сетевую нагрузку',
|
||
'snippets.field.package': 'Добавить пакет',
|
||
'snippets.field.packagePlaceholder': 'Выберите или создайте пакет',
|
||
'snippets.field.createPackage': 'Создать пакет',
|
||
'snippets.field.scriptRequired': 'Скрипт *',
|
||
'snippets.scriptEditor.expand': 'Открыть в окне',
|
||
'snippets.scriptEditor.resize': 'Изменить высоту редактора',
|
||
'snippets.scriptEditor.modalTitle': 'Редактировать скрипт',
|
||
'snippets.variables.dialogTitle': 'Переменные сниппета',
|
||
'snippets.variables.dialogDesc': 'Заполните значения для "{label}" перед запуском.',
|
||
'snippets.variables.hint': 'Значения вставляются в скрипт как есть (без shell-экранирования).',
|
||
'snippets.variables.preview': 'Предпросмотр',
|
||
'snippets.variables.placeholder': 'Введите значение',
|
||
'snippets.variables.placeholderDefault': 'По умолчанию: {value}',
|
||
'snippets.variables.required': 'Эта переменная обязательна',
|
||
'snippets.variables.run': 'Запустить',
|
||
'snippets.field.variablesHelp': 'Используйте {{name}} или {{name:default}} для плейсхолдеров в скрипте.',
|
||
'snippets.field.variablesDetected': 'Переменные',
|
||
'snippets.field.variableDefault': 'по умолчанию {value}',
|
||
'snippets.targets.title': 'Цели',
|
||
'snippets.targets.add': 'Добавить цели',
|
||
'snippets.history.title': 'История оболочки',
|
||
'snippets.history.subtitle': '{count} команд',
|
||
'snippets.history.emptyTitle': 'История оболочки пока пуста',
|
||
'snippets.history.emptyDesc': 'Здесь будут появляться выполненные вами команды',
|
||
'snippets.history.loadMore': 'Загрузить ещё',
|
||
'snippets.history.separator': '•',
|
||
'snippets.history.labelPlaceholder': 'Задайте метку для этого сниппета',
|
||
'snippets.history.saveAsSnippet': 'Сохранить как сниппет',
|
||
'snippets.history.time.justNow': 'только что',
|
||
'snippets.history.time.minutesAgo': '{count}м назад',
|
||
'snippets.history.time.hoursAgo': '{count}ч назад',
|
||
'snippets.history.time.daysAgo': '{count}д назад',
|
||
'snippets.breadcrumb.allPackages': 'Все пакеты',
|
||
'snippets.breadcrumb.separator': '›',
|
||
'snippets.empty.title': 'Создать сниппет',
|
||
'snippets.empty.desc': 'Сохраняйте самые используемые команды как сниппеты, чтобы повторно использовать их в один клик.',
|
||
'snippets.search.noResults.title': 'Нет совпадений',
|
||
'snippets.search.noResults.desc': 'Ни один сниппет или пакет не соответствует запросу "{query}". Попробуйте другой поисковый запрос или очистите поиск для просмотра.',
|
||
'snippets.section.packages': 'Пакеты',
|
||
'snippets.section.snippets': 'Сниппеты',
|
||
'snippets.package.count': '{count} сниппет(ов)',
|
||
'snippets.commandFallback': 'Команда',
|
||
'snippets.view.grid': 'Сетка',
|
||
'snippets.view.list': 'Список',
|
||
'snippets.packageDialog.title': 'Новый пакет',
|
||
'snippets.packageDialog.parent': 'Родитель: {parent}',
|
||
'snippets.packageDialog.root': 'Корень',
|
||
'snippets.packageDialog.placeholder': 'например, ops/maintenance',
|
||
'snippets.packageDialog.hint': 'Используйте "/" для создания вложенных пакетов.',
|
||
|
||
// Snippets Rename Dialog
|
||
'snippets.renameDialog.title': 'Переименовать пакет',
|
||
'snippets.renameDialog.currentPath': 'Текущий путь: {path}',
|
||
'snippets.renameDialog.placeholder': 'Введите новое имя',
|
||
'snippets.renameDialog.error.empty': 'Имя пакета не может быть пустым',
|
||
'snippets.renameDialog.error.duplicate': 'Пакет с таким именем уже существует',
|
||
'snippets.renameDialog.error.invalidChars': 'Имя пакета может содержать только буквы, цифры, дефисы и подчёркивания',
|
||
|
||
'snippets.field.noAutoRun': 'Только вставить (не выполнять автоматически)',
|
||
// Snippet Shortkey
|
||
'snippets.field.shortkey': 'Сочетание клавиш',
|
||
'snippets.shortkey.placeholder': 'Нажмите, чтобы задать сочетание',
|
||
'snippets.shortkey.recording': 'Нажмите сочетание клавиш...',
|
||
'snippets.shortkey.hint': 'Нажмите это сочетание в терминале, чтобы быстро отправить команду.',
|
||
'snippets.shortkey.clear': 'Очистить сочетание',
|
||
'snippets.shortkey.error.systemConflict': 'Это сочетание конфликтует с системным сочетанием',
|
||
'snippets.shortkey.error.snippetConflict': 'Это сочетание уже используется сниппетом: {name}',
|
||
|
||
// Serial Port
|
||
'serial.button': 'Серийный',
|
||
'serial.modal.title': 'Подключение к последовательному порту',
|
||
'serial.modal.desc': 'Настройте параметры подключения к последовательному порту',
|
||
'serial.field.port': 'Последовательный порт',
|
||
'serial.field.selectPort': 'Выберите порт...',
|
||
'serial.field.baudRate': 'Скорость передачи',
|
||
'serial.field.dataBits': 'Биты данных',
|
||
'serial.field.stopBits': 'Стоп-биты',
|
||
'serial.field.stopBits15Warning': '1.5 stop bits may not be supported on all Windows devices',
|
||
'serial.field.parity': 'Чётность',
|
||
'serial.field.flowControl': 'Управление потоком',
|
||
'serial.noPorts': 'Последовательные порты не обнаружены. Подключите устройство и обновите список.',
|
||
'serial.field.customPort': 'Путь к пользовательскому порту',
|
||
'serial.field.customPortPlaceholder': 'например, /dev/ttys001 или COM1',
|
||
'serial.type.hardware': 'Аппаратный',
|
||
'serial.type.pseudo': 'Псевдотерминал',
|
||
'serial.type.custom': 'Пользовательский',
|
||
'serial.parity.none': 'Нет',
|
||
'serial.parity.even': 'Чётная',
|
||
'serial.parity.odd': 'Нечётная',
|
||
'serial.parity.mark': 'Mark',
|
||
'serial.parity.space': 'Space',
|
||
'serial.flowControl.none': 'Нет',
|
||
'serial.flowControl.xon/xoff': 'XON/XOFF (программный)',
|
||
'serial.flowControl.rts/cts': 'RTS/CTS (аппаратный)',
|
||
'serial.field.localEcho': 'Принудительное локальное эхо',
|
||
'serial.field.localEchoDesc': 'Локально отображать вводимые символы (для устройств без удалённого эха)',
|
||
'serial.field.lineMode': 'Построчный режим',
|
||
'serial.field.lineModeDesc': 'Буферизовать ввод и отправлять по Enter (вместо посимвольной отправки)',
|
||
'serial.field.charset': 'Кодировка',
|
||
'serial.connectionError': 'Не удалось подключиться к последовательному порту',
|
||
'serial.field.baudRatePlaceholder': 'Выберите или введите скорость...',
|
||
'serial.field.baudRateEmpty': 'Введите пользовательскую скорость передачи',
|
||
'serial.field.customBaudRate': 'Используется пользовательская скорость передачи',
|
||
'serial.field.saveConfig': 'Сохранить конфигурацию',
|
||
'serial.field.saveConfigDesc': 'Сохраните эту последовательную конфигурацию в хостах для быстрого доступа',
|
||
'serial.field.configLabel': 'Имя конфигурации',
|
||
'serial.field.configLabelPlaceholder': 'например, Arduino Uno',
|
||
'serial.connectAndSave': 'Подключить и сохранить',
|
||
'serial.edit.title': 'Настройки последовательного порта',
|
||
|
||
// Keyboard Interactive Authentication (2FA/MFA)
|
||
'keyboard.interactive.title': 'Требуется аутентификация',
|
||
'keyboard.interactive.desc': 'Сервер требует дополнительную аутентификацию.',
|
||
'keyboard.interactive.descWithHost': 'Сервер {hostname} требует дополнительную аутентификацию.',
|
||
'keyboard.interactive.response': 'Ответ',
|
||
'keyboard.interactive.enterCode': 'Введите код подтверждения',
|
||
'keyboard.interactive.enterResponse': 'Введите ответ',
|
||
'keyboard.interactive.submit': 'Отправить',
|
||
'keyboard.interactive.verifying': 'Проверка...',
|
||
'keyboard.interactive.savePassword': 'Сохранить пароль',
|
||
|
||
// Passphrase Modal for encrypted SSH keys
|
||
'passphrase.title': 'Парольная фраза SSH-ключа',
|
||
'passphrase.desc': 'Введите парольную фразу для {keyName}',
|
||
'passphrase.descWithHost': 'Введите парольную фразу для {keyName}, чтобы подключиться к {hostname}',
|
||
'passphrase.label': 'Парольная фраза',
|
||
'passphrase.keyPath': 'Ключ',
|
||
'passphrase.unlock': 'Разблокировать',
|
||
'passphrase.unlocking': 'Разблокировка...',
|
||
'passphrase.skip': 'Пропустить',
|
||
'passphrase.remember': 'Запомнить эту парольную фразу',
|
||
|
||
// Text Editor
|
||
'sftp.editor.wordWrap': 'Перенос строк',
|
||
'sftp.editor.maximize': 'Развернуть',
|
||
'sftp.editor.unsavedTitle': 'Несохранённые изменения',
|
||
'sftp.editor.unsavedMessage': 'В файле {fileName} есть несохранённые изменения. Сохранить перед закрытием?',
|
||
'sftp.editor.discardChanges': 'Отбросить',
|
||
'sftp.editor.saveAndClose': 'Сохранить и закрыть',
|
||
'sftp.editor.quitBlockedByDirty': 'Есть несохранённые редакторы — перед выходом сохраните изменения или отбросьте их',
|
||
|
||
};
|