feat(i18n): add multi-language support (ja/ko/vi/ru/zh-TW) with system auto-detection

- Extend AppLanguage to 7 locales: zh-CN, zh-TW, en, ja, ko, vi, ru
- Auto-detect system language via navigator.languages; fallback to English
- Add BCP47 locale mapping for date formatting and sorting
- Create 50 translation JSON files (5 languages × 10 namespaces, 1137 keys each)
- Update language selector with native language names
- Extend locale key parity test to cover all 7 languages (70 assertions)
- Add VNC/RDP desktop, serial terminal, AI agent, port forwarding, and SFTP features
- Add credential encryption, host metrics, session backup crypto, and zmodem bridge
- Update Rust backend: desktop services, host metrics, SSH/SFTP enhancements
This commit is contained in:
Logan.Li committed 2026-08-12 00:07:48 +08:00
1 parent fea6d8db04
commit b0d0e3a5f3
301 files changed
+28002 -2705

No files matched your search

+237
View File
@@ -0,0 +1,237 @@
{
"sidebar": {
"quickConnect": "Quick connect",
"quickConnectShort": "Connect",
"newSession": "New session",
"newSessionShort": "New",
"searchPlaceholder": "Search sessions...",
"batchMode": "Batch actions",
"exitBatchMode": "Exit batch mode",
"batchSelected": "{{count}} SSH selected",
"batchExcludedDesktop": " · RDP/VNC excluded",
"selectAllVisible": "Select all in view",
"deselectAllVisible": "Clear selection in view",
"batchExec": "Batch exec",
"settings": "Settings",
"resizeHint": "Drag to resize; double-click to collapse"
},
"tree": {
"selectSession": "Select session",
"noMatchTitle": "No matching sessions",
"noMatchDesc": "Try a different keyword",
"emptyTitle": "No sessions yet",
"emptyDesc": "Quick connect or create a session; double-click to open a terminal",
"emptyAction": "New session"
},
"contextMenu": {
"blank": {
"newGroup": "New group",
"newSession": "New session"
},
"group": {
"newSessionHere": "New session here",
"newGroup": "New group",
"renameGroup": "Rename group",
"deleteEmptyGroup": "Delete empty group"
},
"session": {
"open": "Open",
"edit": "Edit",
"duplicate": "Duplicate",
"delete": "Delete"
}
},
"groups": {
"default": "Default",
"new": {
"title": "New group",
"message": "Enter a group name",
"placeholder": "e.g. Production",
"confirm": "Create"
},
"rename": {
"title": "Rename group",
"message": "Rename \"{{name}}\" to",
"placeholder": "Group name",
"confirm": "Save"
},
"deleteBlocked": {
"title": "Cannot delete",
"message": "Group \"{{name}}\" still has sessions. Move or delete them first.",
"confirm": "Got it"
},
"newOption": "New group…",
"hint": "Default group is used unless you pick or create another"
},
"deleteSession": {
"title": "Delete session",
"message": "Delete session \"{{name}}\"?",
"confirm": "Delete"
},
"welcome": {
"tagline": "Remote terminal · SFTP · Port forwarding",
"sectionStart": "Get started",
"sectionDesktop": "Remote desktop",
"sectionRecent": "Recent sessions",
"quickConnect": {
"title": "Quick connect",
"desc": "One-off SSH; not saved to the library"
},
"newSession": {
"title": "New session",
"desc": "Save hosts; double-click in the sidebar to connect"
},
"localShell": {
"title": "Local shell",
"selectShell": "Choose shell",
"default": "Default"
},
"rdp": {
"title": "RDP remote desktop",
"desc": "Windows · NLA / CredSSP"
},
"vnc": {
"title": "VNC remote desktop",
"desc": "RFB · cross-platform graphical session"
},
"recentEmpty": {
"title": "No saved sessions",
"desc": "Try quick connect, or create a session to reuse later"
}
},
"launcher": {
"searchPlaceholder": "Search hosts, groups, or tabs"
},
"quickConnect": {
"title": "Quick connect",
"target": "Target",
"targetPlaceholder": "root@192.168.1.10:22",
"targetHint": "Supports host, user@host, user@host:port",
"password": "Password",
"passwordOptional": "Optional · leave empty when using a key",
"connect": "Connect",
"errorInvalidTarget": "Enter a host, e.g. root@192.168.1.10 or opsbase.cn:5555",
"errorConnectFailed": "Connection failed"
},
"dialog": {
"create": "New session",
"edit": "Edit session",
"subtitle": "One-line target · advanced options collapsed",
"saving": "Saving…",
"save": "Save",
"createAndSave": "Create and save",
"basic": "Basic",
"login": "Sign-in",
"advanced": "Advanced",
"advancedCollapsed": "Proxy · jump host · tags",
"collapse": "Collapse",
"protocol": "Protocol",
"displayName": "Display name (optional)",
"displayNamePlaceholder": "Defaults to user@host or vnc:host",
"host": "Host",
"hostPlaceholder": "192.168.1.10",
"hostHint": "IP or hostname; host:port is also accepted",
"port": "Port",
"username": "Username",
"usernamePlaceholderRdp": "Administrator",
"usernamePlaceholderSsh": "root",
"width": "Width",
"height": "Height",
"group": "Group",
"authPassword": "Password",
"authKey": "Key",
"password": "Password",
"domain": "Domain (optional)",
"domainPlaceholder": "Rarely needed unless using a domain account",
"keySource": "Key source",
"keyFile": "File",
"keyText": "Text",
"privateKeyPath": "Private key path",
"privateKeyText": "Private key text",
"privateKeyTextHint": "Pasted keys are encrypted on disk like passwords",
"pickKeyFile": "Browse…",
"pickKeyDialogTitle": "Choose private key file",
"allFilesFilter": "All files",
"passphrase": "Key passphrase (optional)",
"passphrasePlaceholder": "Optional",
"tags": "Tags",
"tagsPlaceholder": "prod, web",
"startupCommand": "Startup command (optional)",
"startupCommandPlaceholder": "Run after connect, e.g. cd /var/log",
"proxy": "Proxy",
"proxyNone": "None",
"proxyHostPlaceholder": "Proxy host",
"proxyPortPlaceholder": "Port",
"proxyUserPlaceholder": "Username (optional)",
"proxyPasswordPlaceholder": "Password (optional)",
"jumpHost": "Jump host (optional)",
"jumpNone": "No jump host",
"jumpNoneAlt": "No jump host",
"jumpHint": "One saved session can be used as a jump host"
},
"batch": {
"title": "Batch exec",
"subtitle": "{{selected}} selected · concurrency {{concurrency}} · results discarded when tab closes",
"dialogTitle": "Batch command",
"dialogDesc": "{{selected}}/{{total}} hosts selected · max concurrency {{concurrency}}",
"targetCount": "{{count}} targets",
"runningProgress": "Running {{completed}}/{{total}}",
"execute": "Run on {{count}} hosts",
"executeAgain": "Run again",
"success": "{{count}} succeeded",
"failed": "{{count}} failed",
"command": "Remote command",
"commandPlaceholder": "e.g. uptime",
"targets": "Target hosts",
"filterPlaceholder": "Name, IP, group, or tag",
"filterAria": "Filter hosts",
"noMatchHosts": "No matching hosts",
"resultMatrix": "Result matrix",
"resultMatrixHint": "Host × status × output",
"emptySelection": "Pick targets on the left, or open from sidebar batch mode with a selection",
"noOutput": "(no output)",
"errorReadConfig": "Could not read session config",
"errorConnectFailed": "Connection failed",
"errorExecFailed": "Command execution failed",
"results": "Results",
"resultsHint": "Output is kept only in this dialog",
"ctrlEnterHint": "Ctrl/⌘ + Enter to run",
"executeTo": "Run on {{count}} hosts",
"selectFromLeft": "Select targets on the left"
},
"importExport": {
"exportTitle": "Export sessions",
"exportDefaultPath": "opsxshell-sessions.bak",
"exportFilterBak": "OpsXShell backup",
"exportFilterJson": "JSON",
"exportSuccess": "Exported {{count}} sessions to:\n{{path}}",
"exportWriteFailed": "Failed to write export file",
"exportFailed": "Session export failed",
"exportFailedDetail": "Session export failed: {{message}}",
"exportPasswordTitle": "Set backup password",
"exportPasswordMessage": "The export file will encrypt host groups, private keys, passwords, and other secrets. Choose a backup password.",
"exportPasswordPlaceholder": "Enter backup password",
"exportPasswordConfirmTitle": "Confirm backup password",
"exportPasswordConfirmMessage": "Enter the backup password again to confirm.",
"exportPasswordConfirmPlaceholder": "Re-enter backup password",
"exportPasswordMismatch": "Passwords do not match",
"exportPasswordRequired": "A backup password is required to export",
"importTitle": "Import sessions",
"importFilterBak": "OpsXShell backup",
"importFilterJson": "JSON",
"importFilterSshConfig": "SSH Config",
"importFilterAll": "All files",
"readFileFailed": "Failed to read file",
"readFileFailedDetail": "Failed to read file: {{message}}",
"importPasswordTitle": "Enter backup password",
"importPasswordMessage": "This file is encrypted. Enter the password set at export to import host groups and credentials.",
"importPasswordPlaceholder": "Enter backup password",
"importPasswordRequired": "A password is required to import an encrypted backup",
"importPasswordInvalid": "Incorrect backup password, or the file is corrupted",
"noSessionsFound": "No importable sessions found",
"noValidSessions": "No valid session entries in the file",
"importSuccess": "Imported {{created}}/{{total}} sessions",
"importFailed": "Session import failed",
"importFailedDetail": "Session import failed: {{message}}"
}
}