feat: multi-language interface (zh-CN/zh-TW/en/ja), multilingual offline changelog, settings robustness

i18n
- shared/i18n: dependency-free t() with flat per-namespace dictionaries
  (common/settings/workspace/terminal/ssh/panels/main), zh-CN fallback
- language picker in Settings -> System; antd ConfigProvider locale follows it
- main process tracks the language too: tray menu, close prompt, ssh/sftp/
  zmodem errors and the log TUI marker are translated; tray rebuilds on change

changelog
- CHANGELOG.md (zh-CN canonical) + .zh-TW/.en/.ja, bundled via ?raw and read
  per interface language with per-version fallback to zh-CN (no network)
- sync-changelog.cjs merges RELEASE_NOTES[.<lang>].md per release; release.cjs
  refuses to publish without a zh-CN entry for the version

settings robustness
- closeAction 'ask' survives the sanitizer (was silently coerced to 'tray',
  which made the 'ask every time' option dead)
- highlight rules are repaired instead of dropped: string priority, 0/1
  enabled, missing fg colour; unknown fields preserved
- load-time warnings are written to settings-warnings.log (deduped, capped)

terminal/UI
- configurable terminal toolbar: open working directory (default on), session
  log recording (off), open logs folder (off)
- global shortcut field records key combos (modifier or F-key required)
- input suggestions + command history default to off, with a one-time reset
  migration for existing installs
- settings dialog scrolling fixed (antd v6 renamed the tabs container), theme
  gallery nested scrollbar removed, joined segmented pickers with readable
  selected-state text

tests: settings-store.mjs (15 checks) added; commands-store.mjs updated for
the new off-by-default history setting
This commit is contained in:
Bill committed 2026-09-20 14:22:29 +08:00
1 parent 34094d607b
commit 4c6a29ef28
82 files changed
+3342 -608

No files matched your search

+144
View File
@@ -0,0 +1,144 @@
/** 命名空间:ssh(SSH 连接管理、主机密钥、文件面板、zmodem、系统监控)。归属:SSH 维护者。 */
const ssh: Record<string, string> = {
// 认证方式 / 密钥种类
'ssh.auth.password': '密码',
'ssh.auth.privateKey': '私钥',
'ssh.auth.agent': 'Agent',
'ssh.secret.passphrase': '口令',
// 连接编辑弹窗:认证相关字段
'ssh.fields.agentDesc': '使用本机 SSH Agent 中已加载的密钥进行认证,无需在本应用内保存任何密钥。',
'ssh.fields.askPasswordLabel': '连接时询问密码',
'ssh.fields.askPasswordHint': '开启后每次连接弹出对话框输入密码,不再使用已保存的密码',
'ssh.fields.passwordPlaceholder': '编辑时留空表示保留已保存的密码',
'ssh.fields.keyPath': '私钥路径(服务器上的本地私钥路径,可留空)',
'ssh.fields.keyContent': '私钥内容',
'ssh.fields.keyContentPlaceholder':
'粘贴私钥内容;留空则使用上面的路径(编辑时留空表示保留已保存的私钥)',
'ssh.fields.askPassphraseLabel': '连接时询问口令',
'ssh.fields.askPassphraseHint': '开启后每次连接提示输入私钥口令',
'ssh.fields.passphrase': '私钥口令',
'ssh.fields.passphrasePlaceholder': '编辑时留空表示保留已保存的口令',
// 连接编辑弹窗
'ssh.dialog.titleEdit': '编辑连接',
'ssh.dialog.titleNew': '新建连接',
'ssh.dialog.saveFailed': '保存失败,请检查输入后重试',
'ssh.dialog.name': '名称',
'ssh.dialog.nameRequired': '请输入连接名称',
'ssh.dialog.namePlaceholder': '例如:生产服务器',
'ssh.dialog.group': '分组',
'ssh.dialog.groupPlaceholder': '选择或输入新分组,留空归入“默认”',
'ssh.dialog.host': '主机',
'ssh.dialog.hostRequired': '请输入主机地址',
'ssh.dialog.hostPlaceholder': '192.168.1.10 或 example.com',
'ssh.dialog.port': '端口',
'ssh.dialog.portRange': '端口需在 1–65535 之间',
'ssh.dialog.username': '用户名',
'ssh.dialog.usernameRequired': '请输入用户名',
'ssh.dialog.authMethod': '认证方式',
'ssh.dialog.savedSecret': '已保存{kind},留空将保留原值',
'ssh.dialog.keepalive': 'Keepalive 间隔(秒)',
'ssh.dialog.keepaliveTooltip': '0 表示关闭 keepalive',
'ssh.dialog.keepaliveMin': '不能为负数',
// 连接侧栏
'ssh.sidebar.defaultGroup': '默认',
'ssh.sidebar.timeJustNow': '刚刚',
'ssh.sidebar.timeMinutesAgo': '{n} 分钟前',
'ssh.sidebar.timeHoursAgo': '{n} 小时前',
'ssh.sidebar.timeDaysAgo': '{n} 天前',
'ssh.sidebar.modeTerminal': '终端工作区',
'ssh.sidebar.modeSsh': 'SSH 工作区',
'ssh.sidebar.title': '连接',
'ssh.sidebar.newConnection': '新建连接',
'ssh.sidebar.sectionTerminals': '终端',
'ssh.sidebar.noLocalTerminals': '无打开的本地终端',
'ssh.sidebar.local': '本地',
'ssh.sidebar.sectionServers': 'SSH 服务器',
'ssh.sidebar.empty': '暂无连接,点击+新建',
'ssh.sidebar.loading': '加载中…',
'ssh.sidebar.recent': '最近会话',
'ssh.sidebar.dblClickConnect': '双击连接 {host}',
'ssh.sidebar.deleteTitle': '删除该连接?',
'ssh.sidebar.deleteDesc': '连接配置删除后不可恢复。已保存的密钥数据会同步删除。',
// 主机密钥确认
'ssh.hostKey.changedTitle': '主机指纹已变更!',
'ssh.hostKey.unknownHost': '未知主机',
'ssh.hostKey.accept': '接受并连接',
'ssh.hostKey.reject': '拒绝',
'ssh.hostKey.mitmTitle': '可能遭受中间人攻击',
'ssh.hostKey.mitmDesc':
'远程主机的密钥指纹与之前记录的不一致。如果这不是你本人更换了服务器密钥,可能有人正在冒充该主机。',
'ssh.hostKey.firstConnect': '首次连接该主机,尚未记录其指纹。',
'ssh.hostKey.target': '主机:{target}',
'ssh.hostKey.fingerprint': '指纹:{fingerprint}',
// SSH 工作区:文件面板容器、主机徽标
'ssh.bottomPanel.resize': '调整文件面板高度',
'ssh.hostBadge.aria': 'SSH 主机 {label}',
// ZMODEM
'ssh.zmodem.done': 'ZMODEM 传输完成',
'ssh.zmodem.failed': 'ZMODEM 传输失败:{message}',
'ssh.zmodem.unknownError': '未知错误',
'ssh.zmodem.titleReceive': '下载到本地',
'ssh.zmodem.titleSend': '上传到服务器',
'ssh.zmodem.pickDir': '选择保存目录',
'ssh.zmodem.pickFiles': '选择文件',
'ssh.zmodem.receiveDesc': '检测到 sz 下载请求(远端正在发送文件),请选择保存在本地的目录。',
'ssh.zmodem.sendDesc': '检测到 rz 上传请求(远端正在接收文件),请选择要上传的文件。',
// 文件面板(SFTP)
'ssh.file.up': '上一级',
'ssh.file.refresh': '刷新',
'ssh.file.uploadFile': '上传文件',
'ssh.file.downloadSelected': '下载选中项',
'ssh.file.permOwner': '权限 / 属主',
'ssh.file.open': '打开',
'ssh.file.download': '下载',
'ssh.file.upload': '上传…',
'ssh.file.rename': '重命名',
'ssh.file.new': '新建',
'ssh.file.newFolder': '新建文件夹',
'ssh.file.copyPath': '复制路径',
'ssh.file.copyPathFailed': '复制路径失败',
'ssh.file.pathCopied': '已复制路径',
'ssh.file.permission': '文件权限…',
'ssh.file.deleteTitle': '确认删除?',
'ssh.file.loading': '加载中…',
'ssh.file.empty': '空目录',
'ssh.file.modeUnavailable': '权限不可用',
'ssh.file.folderName': '文件夹名称',
'ssh.file.create': '创建',
'ssh.file.renameTitle': '重命名 {name}',
'ssh.file.permTitle': '权限 · {name}',
'ssh.file.permApplied': '已应用权限',
'ssh.file.octal': '八进制',
'ssh.file.octalPlaceholder': '如 755',
'ssh.file.keepEmpty': '不改则留空',
'ssh.file.ownerHint': 'UID/GID 留空表示不修改属主',
'ssh.file.permRowOwner': '所有者',
'ssh.file.permRowGroup': '组',
'ssh.file.permRowOther': '其他',
'ssh.file.permColRead': '读',
'ssh.file.permColWrite': '写',
'ssh.file.permColExec': '执行',
// 系统监控
'ssh.monitor.collecting': '采集中…',
'ssh.monitor.interrupted': '采集中断:{error}',
'ssh.monitor.mem': '内存',
'ssh.monitor.disks': '磁盘',
'ssh.monitor.net': '网络',
'ssh.monitor.cores': '{n} 核',
'ssh.monitor.loadavg': '负载 {value}',
'ssh.monitor.uptime': '运行时间',
'ssh.monitor.uptimeSeconds': '{n}秒',
'ssh.monitor.uptimeMinutes': '{n}分钟',
'ssh.monitor.uptimeHours': '{h}小时{m}分',
'ssh.monitor.uptimeDays': '{n}天'
}
export default ssh