chore: 保存工作副本——客户端授权新契约(双端点/验签/令牌/周检)与桌面会话可靠性改进

This commit is contained in:
Logan.Li committed 2026-09-14 22:10:22 +08:00
1 parent f71eef0eba
commit ae6093c9b3
163 files changed
+4911 -2494

No files matched your search

+4 -4
View File
@@ -16,10 +16,10 @@
"stop": "Остановить",
"send": "Отправить",
"placeholder": "Задача или уточнение… (Enter — отправить, Shift+Enter — новая строка)",
"hintFollowUp": "Уточнения включают контекст этой ветки",
"hintFollowUp": "Уточнения включают сжатое резюме этой ветки",
"hintSelection": "Будет включено {{lines}} выбранных строк",
"hintSteps": "До {{max}} шагов · ничего не сохраняется",
"footerNote": "Высокий риск требует подтверждения · критический блокируется · сеанс не сохраняется",
"hintSteps": "До {{max}} шагов",
"footerNote": "Высокий риск — сначала подтверждение · разрушительные команды отклоняются · чат не сохраняется",
"summarize": "Сводка",
"summarizeTitle": "AI суммирует видимый вывод терминала (сначала выделение); команды не выполняются",
"summarizeRequest": "Суммируйте текущий вывод терминала"
@@ -77,7 +77,7 @@
"invalidCommand": "Модель не вернула единственную однострочную команду; выполнение отклонено",
"repeatLoop": "Обнаружен повторяющийся цикл команд; остановлено: {{command}}",
"criticalBlocked": "Команда попала под деструктивную жёсткую блокировку; обход невозможен: {{command}}",
"execFailed": "Сбой ssh-exec: {{error}}",
"execFailed": "Сбой удалённого выполнения: {{error}}",
"execUnknown": "Неизвестная ошибка",
"execNoOutput": "Команда завершилась без вывода",
"maxSteps": "Достигнут лимит в {{max}} шагов; сузьте задачу и повторите",
+7 -4
View File
@@ -33,8 +33,10 @@
"error": {
"title": "Что-то пошло не так",
"body": "В приложении возникла непредвиденная проблема",
"bodyPane": "В этой вкладке произошла ошибка. Остальные вкладки работают.",
"recoverable": "Эта ошибка обратима. Попробуйте обновить страницу.",
"refreshPage": "Обновить страницу",
"retryPane": "Повторить вкладку",
"restartApp": "Перезапустить приложение",
"supportHint": "Если проблема сохраняется, проверьте журналы или обратитесь в поддержку"
},
@@ -104,11 +106,12 @@
},
"menu": {
"closeOthers": "Закрыть остальные",
"closeRight": "Закрыть вкладки справа",
"closeLeft": "Закрыть вкладки слева",
"closeRight": "Закрыть справа",
"closeLeft": "Закрыть слева",
"closeAll": "Закрыть все",
"clone": "Дублировать вкладку",
"openSftp": "Открыть SFTP"
"clone": "Клонировать вкладку",
"openSftp": "Открыть SFTP",
"reconnect": "Переподключиться"
},
"renameAria": "Переименовать вкладку {{title}}",
"renameHint": "Двойной клик — переименовать"
+5 -1
View File
@@ -35,13 +35,17 @@
"fullscreenAria": "Развернуть на весь экран",
"exitFullscreen": "Выйти из полного экрана",
"exitFullscreenAria": "Выйти из полного экрана",
"exitFullscreenHint": "Esc / F11 — выход"
"exitFullscreenHint": "Esc / F11 — выход",
"reconnect": "Переподключиться",
"reconnectAria": "Переподключить удалённый рабочий стол"
},
"status": {
"connecting": "Подключение…",
"connected": "Подключено",
"disconnected": "Отключено",
"connectFailed": "Сбой подключения",
"reconnecting": "Автопереподключение ({{attempt}}/{{max}})…",
"reconnectLimit": "Достигнут лимит автопереподключения ({{max}})",
"clipboardSynced": "Удалённый буфер обмена синхронизирован",
"savedToDownloads": "Сохранено в локальную папку Downloads: {{name}}",
"pastedToRemote": "Вставлено на удалённый сервер",
+11 -2
View File
@@ -41,7 +41,10 @@
"refused": "В подключении отказано",
"disconnected": "Отключено",
"keepaliveFailed": "SSH keep-alive несколько раз не удался; соединение закрыто",
"idleKicked": "Удалённая оболочка завершилась по таймауту простоя (TMOUT)"
"idleKicked": "Удалённая оболочка завершилась по таймауту простоя (TMOUT)",
"unexpectedDropped": "Соединение разорвано (сеть или закрытие на сервере)",
"shellExited": "Удалённая оболочка завершилась (exit, Ctrl+D или политика сервера)",
"shellReadFailed": "Не удалось прочитать удалённую оболочку"
},
"auth": {
"failed": "Сбой аутентификации. Проверьте имя пользователя и пароль.",
@@ -160,7 +163,7 @@
"invalidCommand": "Модель не вернула единственную однострочную команду; выполнение отклонено",
"repeatLoop": "Обнаружен повторяющийся цикл команд; остановлено: {{command}}",
"criticalBlocked": "Команда попала под деструктивную жёсткую блокировку; обход невозможен: {{command}}",
"execFailed": "Сбой ssh-exec: {{error}}",
"execFailed": "Сбой удалённого выполнения: {{error}}",
"maxSteps": "Достигнут лимит в {{max}} шагов; сузьте задачу и повторите",
"sshRequired": "Требуется подключённый удалённый SSH-сеанс"
},
@@ -168,6 +171,12 @@
"readFailed": "Сбой чтения: {{name}}",
"writeFailed": "Сбой записи: {{name}}"
},
"native": {
"taskJoin": "Фоновая задача не выполнена. Повторите попытку.",
"invalidBase64": "Данные файла не являются корректным Base64.",
"knownHostsPath": "Не удалось найти ~/.ssh/known_hosts.",
"invalidHostKeyDecision": "Некорректное решение по ключу хоста."
},
"unknown": {
"error": "Произошла неизвестная ошибка"
}
+5 -2
View File
@@ -132,7 +132,8 @@
"collapse": "Свернуть",
"protocol": "Протокол",
"displayName": "Отображаемое имя (необязательно)",
"displayNamePlaceholder": "По умолчанию user@host или vnc:host",
"displayNamePlaceholder": "По умолчанию user@host",
"displayNamePlaceholderVnc": "По умолчанию имя хоста",
"host": "Хост",
"hostPlaceholder": "192.168.1.10",
"hostHint": "IP или имя хоста; также принимается host:port",
@@ -208,7 +209,8 @@
},
"importExport": {
"exportTitle": "Экспорт сеансов",
"exportDefaultPath": "opsxshell-sessions.bak",
"exportDefaultPath": "opsxshell-hosts.oxs",
"exportFilterOxs": "Резервная копия хостов OpsXShell",
"exportFilterBak": "Резервная копия OpsXShell",
"exportFilterJson": "JSON",
"exportSuccess": "Экспортировано сеансов: {{count}} в:\n{{path}}",
@@ -224,6 +226,7 @@
"exportPasswordMismatch": "Пароли не совпадают",
"exportPasswordRequired": "Для экспорта требуется пароль резервной копии",
"importTitle": "Импорт сеансов",
"importFilterOxs": "Резервная копия хостов OpsXShell",
"importFilterBak": "Резервная копия OpsXShell",
"importFilterJson": "JSON",
"importFilterSshConfig": "SSH Config",
+45 -33
View File
@@ -13,7 +13,7 @@
"ai": "AI-модели",
"aiDesc": "AI-провайдеры",
"about": "О приложении",
"aboutDesc": "Версия и данные",
"aboutDesc": "Версия, контакты и диагностика",
"account": "Аккаунт",
"accountDesc": "Email, лицензия и устройство"
},
@@ -88,10 +88,10 @@
},
"ssh": {
"connection": "Подключение",
"keepAlive": "Keep-alive",
"keepAliveDesc": "Отправлять SSH keep-alive в простое; отключать только после нескольких сбоев",
"keepAlive": "Поддержание связи",
"keepAliveDesc": "В простое слать протокол SSH keep-alive (не вводить в оболочку). Защищает от NAT, не обходит удалённый TMOUT",
"autoReconnect": "Авто-переподключение",
"autoReconnectDesc": "Автоматически повторять после неожиданного разрыва",
"autoReconnectDesc": "Пока вкладка открыта, после неожиданного разрыва переподключаться (новая оболочка). Закрытие вкладки, простой и удалённый TMOUT не удерживаются силой",
"timeout": "Тайм-аут подключения",
"timeoutDesc": "Максимальное время ожидания при установке SSH (секунды)",
"maxReconnect": "Попытки переподключения",
@@ -104,7 +104,8 @@
"suspend": "Фоновая приостановка",
"suspendDesc": "Через сколько минут приостанавливать простаивающие фоновые вкладки (активные Shell/SFTP остаются)",
"keepAliveInterval": "Интервал keep-alive (сек)",
"keepAliveIntervalDesc": "Как часто опрашивать сервер (как ClientAliveInterval). При нестабильной сети — ≤15 с"
"keepAliveIntervalDesc": "Как часто опрашивать сервер (как ClientAliveInterval). При нестабильной сети — ≤15 с",
"sessionPolicyHint": "Keep-alive держит TCP-канал, а не политику удалённого сеанса. Bash TMOUT, sshd ClientAlive и простой GPO Windows по-прежнему действуют. Долгие задачи — через tmux/screen на сервере."
},
"security": {
"credentials": "Защита учётных данных",
@@ -122,16 +123,25 @@
},
"about": {
"tagline": "Простой и удобный нативный терминал для эксплуатации",
"appVersion": "Приложение v{{version}}",
"copyVersion": "Копировать сведения о версии",
"runtime": "Среда выполнения",
"system": "Система",
"localData": "Локальные данные",
"appVersion": "v{{version}}",
"copyVersion": "Скопировать версию, систему и пути для GitHub",
"copyDiagnostics": "Копировать диагностику",
"copyPath": "Копировать путь",
"resources": "Ресурсы",
"wechat": "WeChat",
"copyWechat": "Скопировать WeChat ID",
"github": "Обсуждения",
"githubDesc": "https://github.com/L00J/opsxshell/discussions",
"releases": "Релизы",
"releasesDesc": "Установщики и заметки к выпуску",
"licenseLink": "Лицензия",
"licenseLinkDesc": "MIT License",
"diagnostics": "Диагностика",
"sessionsSettings": "Сеансы и настройки",
"masterKeyPath": "Мастер-ключ",
"privacyNote": "Пароли и passphrase шифруются в Rust (AES-256-GCM). Без истории команд и без аудита-бастиона.",
"license": "Лицензия MIT · Rust · XTerm.js",
"logPath": "Журнал приложения"
"license": "MIT License · Rust · XTerm.js",
"logPath": "Журнал приложения",
"reportBug": "Сообщить об ошибке",
"reportBugDesc": "Открывает GitHub issue с текущей версией и платформой"
},
"ai": {
"presets": "Пресеты провайдеров",
@@ -151,13 +161,15 @@
"saved": "Сохранено",
"retest": "Пожалуйста, перепроверьте",
"testFailed": "Сбой проверки подключения",
"available": "OK · {{latency}} мс",
"available": "Готово · {{latency}} мс",
"savedKeepBlank": "Сохранено — оставьте пустым, чтобы сохранить",
"notRequired": "Не требуется",
"otherModels": "Другие модели…",
"customModel": "Своя модель",
"backToList": "Назад к списку",
"apiKeyOptional": "API Key (не требуется)",
"apiKey": "API-ключ",
"apiKeyOptional": "API-ключ (не требуется)",
"endpoint": "Адрес API",
"advanced": "Дополнительно",
"allowHttp": "Разрешить HTTP (localhost/LAN)",
"setActive": "Сделать активным",
@@ -175,26 +187,26 @@
}
},
"account": {
"title": "Account",
"email": "Email",
"emailDesc": "Used for checkout and license claims",
"plan": "Current plan",
"planFree": "Free",
"title": "Аккаунт",
"email": "Почта",
"emailDesc": "Контактная почта для оплаты и получения лицензии",
"plan": "Текущий план",
"planFree": "Бесплатный",
"planYearly": "Pro на год",
"planPerpetual": "Pro бессрочно",
"planTrial": "Pro пробный",
"expires": "Expires {{date}}",
"lifetime": "Lifetime",
"devices": "Seats: up to {{count}} devices",
"deviceId": "This device ID",
"saveEmail": "Save email",
"activate": "Activate license",
"pasteLicense": "Paste LIC- license key",
"clear": "Clear local license",
"deactivate": "Deactivate this device",
"upgrade": "Upgrade",
"saved": "Saved",
"activateOk": "Activated",
"expires": "Действует до {{date}}",
"lifetime": "Бессрочно",
"devices": "Места устройств: до {{count}}",
"deviceId": "ID этого устройства",
"saveEmail": "Сохранить почту",
"activate": "Активировать лицензию",
"pasteLicense": "Вставьте лицензию LIC-",
"clear": "Удалить локальную лицензию",
"deactivate": "Отключить активацию на этом устройстве",
"upgrade": "Перейти на Pro",
"saved": "Сохранено",
"activateOk": "Активировано",
"deviceList": "Привязанные устройства",
"loadingDevices": "Загрузка устройств…",
"noDevices": "Нет привязанных устройств",
+2 -1
View File
@@ -15,7 +15,8 @@
"notConnected": "Нет подключения",
"connecting": "Подключение...",
"resumeHint": "После переподключения вернёмся в {{path}}",
"reconnectingResume": "Переподключение и восстановление {{path}}…"
"reconnectingResume": "Переподключение и восстановление {{path}}…",
"autoReconnecting": "Автопереподключение ({{attempt}}/{{max}})…"
},
"errors": {
"notConnected": "SFTP не подключён",
+3 -1
View File
@@ -34,7 +34,9 @@
"reopenShell": "Открыть оболочку снова",
"reopening": "Открытие…",
"disconnected": "Отключено",
"disconnectedHint": "SSH-сеанс завершился или сеть упала. Один клик ниже — и можно продолжать работу.",
"disconnectedHint": "Сеть оборвалась или сервер закрыл SSH. Пока вкладка открыта, будет автопереподключение; можно нажать кнопку ниже.",
"disconnectedKeepalive": "Сбой keep-alive, отключено",
"disconnectedKeepaliveHint": "SSH keep-alive не ответил — обычно NAT или простой сети. В оболочку клавиши не отправляются. Пока вкладка открыта, будет автопереподключение.",
"reconnect": "Переподключиться",
"suspended": "Подключение приостановлено",
"suspendedHint": "Долгое отсутствие активности; подключение приостановлено для экономии ресурсов",