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

+17
View File
@@ -0,0 +1,17 @@
/** Namespace: common (i18n plumbing, generic buttons/status). Owner: i18n infrastructure. */
const common: Record<string, string> = {
'common.ok': 'OK',
'common.cancel': 'Cancel',
'common.close': 'Close',
'common.save': 'Save',
'common.delete': 'Delete',
'common.edit': 'Edit',
'common.add': 'Add',
'common.copy': 'Copy',
'common.paste': 'Paste',
'common.reset': 'Reset to defaults',
'common.language': 'Language',
'common.languageDesc': 'Switches the interface language immediately; saved permanently.'
}
export default common
+19
View File
@@ -0,0 +1,19 @@
import common from './common'
import settings from './settings'
import workspace from './workspace'
import terminal from './terminal'
import ssh from './ssh'
import panels from './panels'
import main from './main'
/** English entries. Namespace files are owned per area — see the ownership map
* in src/shared/i18n/index.ts. */
export default {
...common,
...settings,
...workspace,
...terminal,
...ssh,
...panels,
...main
}
+56
View File
@@ -0,0 +1,56 @@
/** Namespace: main (main-process strings: tray, close prompt, updater). Owner: main process. */
const main: Record<string, string> = {
'main.tray.showWindow': 'Show main window',
'main.tray.closeAction': 'Close button action',
'main.tray.askEveryTime': 'Ask every time',
'main.tray.minimizeToTray': 'Minimize to tray',
'main.tray.exitDirectly': 'Exit directly',
'main.tray.exit': 'Exit',
'main.tray.balloonTitle': 'Minimized to tray',
'main.tray.balloonContent': 'Terminal sessions keep running in the background. Click the tray icon to restore the window.',
'main.tray.closeTitle': 'Close OpenTerminal',
'main.tray.closeMessage': 'Minimize to tray, or exit now?',
'main.tray.closeDetail': 'Minimizing to tray keeps your terminal sessions running.',
'main.tray.rememberChoice': 'Remember my choice, never ask again',
'main.updater.feedFailed': 'Domestic feed: {gitea}; GitHub: {github}',
'main.ssh.connectTimeout': 'Connection timed out ({host}:{port})',
'main.ssh.saveFingerprintFailed': 'Failed to save the host fingerprint: {detail}',
'main.ssh.hostKeyRejected': 'The user rejected the host key',
'main.ssh.connectFailed': 'Connection failed {host}:{port}: {detail}',
'main.ssh.shellOpenFailed': 'Could not open the SSH shell ({host}:{port}): {detail}',
'main.ssh.initFailed': 'SSH connection initialization failed ({host}:{port}): {detail}',
'main.ssh.readKeyFailed': 'Could not read the private key file {path}: {detail}',
'main.sftp.sessionGone': 'The SSH session does not exist or has disconnected',
'main.sftp.deleteFailed': 'Delete failed: {detail}',
'main.sftp.invalidMode': 'Invalid permission value: {mode}',
'main.sftp.invalidUidGid': 'Invalid uid/gid',
'main.sftp.commandExitCode': 'Command exited with code {code}',
'main.sftp.cancelled': 'Cancelled',
'main.zmodem.transferFailed': 'Transfer failed',
'main.zmodem.transferTimeout': 'Transfer timed out',
'main.zmodem.sendFailed': 'Sending failed',
'main.zmodem.uploadFailed': 'Upload failed',
'main.zmodem.receiveFailed': 'Receiving failed',
'main.zmodem.abnormal': 'ZMODEM transfer error',
'main.zmodem.cancelled': 'Cancelled',
'main.zmodem.offerTimedOut': 'No files selected, cancelled',
'main.zmodem.sessionInvalid': 'The session is no longer valid',
'main.zmodem.sessionCreateFailed': 'Could not establish the ZMODEM session',
'main.zmodem.noSaveDir': 'No save directory specified',
'main.zmodem.noFiles': 'No files selected',
'main.ipc.connectionMissing': 'Connection bookmark not found ({id})',
'main.sysinfo.sessionGone': 'SSH session is missing or disconnected',
'main.sysinfo.execFailed': 'SSH exec failed',
'main.sysinfo.parseFailed': 'Parse failed: {message}',
'main.pty.serviceNotReady': 'SSH session service is not initialised yet',
'main.pty.missingConnectionId': 'SSH session is missing its connectionId',
'main.log.tuiOmitted': 'full-screen (TUI) output omitted'
}
export default main
+36
View File
@@ -0,0 +1,36 @@
/** Namespace: panels (command panel, session-log panel, transfer panel). Owner: panels area. */
const panels: Record<string, string> = {
// Command panel
'panels.commands.sectionTitle': 'Commands',
'panels.commands.target': 'Send to',
'panels.commands.targetSsh': 'SSH server',
'panels.commands.targetTerminal': 'Terminal',
'panels.commands.tabHistory': 'History',
'panels.commands.tabLibrary': 'Library',
'panels.commands.historyTitle': 'Command history',
'panels.commands.clearTitle': 'Clear all command history?',
'panels.commands.clear': 'Clear',
'panels.commands.noHistory': 'No command history',
'panels.commands.loading': 'Loading…',
'panels.commands.libraryTitle': 'Command library',
'panels.commands.libraryEmpty': 'The command library is empty',
'panels.commands.add': 'Add command',
'panels.commands.name': 'Name',
'panels.commands.optional': '(optional)',
'panels.commands.command': 'Command',
'panels.commands.commandPlaceholder': 'e.g. ls -la',
'panels.commands.note': 'Note',
'panels.commands.deleteTitle': 'Delete this command?',
'panels.commands.deleteAria': 'Delete command',
// Transfer panel
'panels.transfer.failed': 'Transfer failed',
'panels.transfer.cancelled': 'Cancelled',
'panels.transfer.done': 'Transfer complete',
'panels.transfer.uploading': 'Uploading',
'panels.transfer.downloading': 'Downloading',
'panels.transfer.zmodemUploading': 'ZMODEM uploading',
'panels.transfer.zmodemDownloading': 'ZMODEM downloading'
}
export default panels
+153
View File
@@ -0,0 +1,153 @@
/** Namespace: settings (the settings dialog: font/cursor/render/highlight/theme/system/about). Owner: settings page. */
const settings: Record<string, string> = {
'settings.title': 'Settings',
'settings.tabs.font': 'Font',
'settings.tabs.cursor': 'Cursor & Scrollback',
'settings.tabs.render': 'Rendering & Behavior',
'settings.tabs.highlight': 'Highlighting',
'settings.tabs.theme': 'Themes',
'settings.tabs.system': 'System',
'settings.tabs.about': 'About',
'settings.resizeHandle': 'Drag to resize',
'settings.preview': 'Preview',
'settings.deleteConfirmDesc': 'This cannot be undone. Continue?',
'settings.color.foreground': 'Foreground',
'settings.color.background': 'Background',
'settings.color.cursor': 'Cursor',
'settings.color.selection': 'Selection',
'settings.font.label': 'Font',
'settings.font.desc': 'The built-in default or a system monospace font',
'settings.font.placeholder': 'Select a font',
'settings.font.default': 'Default',
'settings.font.size': 'Font size',
'settings.font.sizeDesc': 'Pixel size of the terminal text',
'settings.font.weight': 'Weight',
'settings.font.weightDesc': '400 is regular, 700 is bold',
'settings.font.boldWeight': 'Bold weight',
'settings.font.boldWeightDesc': 'Weight used for bold text',
'settings.font.letterSpacing': 'Letter spacing',
'settings.font.letterSpacingDesc': 'Horizontal distance between characters',
'settings.font.lineHeight': 'Line height',
'settings.font.lineHeightDesc': 'Vertical distance between adjacent lines',
'settings.cursor.blink': 'Blinking cursor',
'settings.cursor.blinkDesc': 'Whether the cursor blinks periodically',
'settings.cursor.style': 'Cursor style',
'settings.cursor.styleDesc': 'Shape used to draw the cursor',
'settings.cursor.inactiveStyle': 'Inactive cursor style',
'settings.cursor.inactiveStyleDesc': 'Cursor style while the window is unfocused',
'settings.cursor.scrollback': 'Scrollback buffer',
'settings.cursor.scrollbackDesc': 'How many lines you can scroll back',
'settings.cursorStyle.bar': 'Bar',
'settings.cursorStyle.block': 'Block',
'settings.cursorStyle.underline': 'Underline',
'settings.cursorStyle.outline': 'Outline',
'settings.cursorStyle.none': 'None',
'settings.rendererMode.auto': 'Automatic',
'settings.rendererMode.autoHint': 'Prefer WebGL acceleration, falling back to DOM rendering if it fails',
'settings.rendererMode.webgl': 'High-performance WebGL',
'settings.rendererMode.webglHint':
'Force GPU-accelerated rendering; best for high refresh rates and heavy scrolling',
'settings.rendererMode.dom': 'Compatible DOM',
'settings.rendererMode.domHint':
'Pure CPU rendering with the widest compatibility; best without a GPU or over remote desktop',
'settings.render.modeLabel': 'Renderer',
'settings.render.modeHint': 'How terminal cells are accelerated; applies to every terminal',
'settings.render.autoWrap': 'Auto wrap',
'settings.render.autoWrapDesc': 'Wrap lines that exceed the width',
'settings.render.copyOnSelect': 'Copy on select',
'settings.render.copyOnSelectDesc': 'Copy text automatically when you select it with the mouse',
'settings.render.pasteRiskConfirm': 'Confirm risky paste',
'settings.render.pasteRiskConfirmDesc':
'Ask before pasting multi-line text (or a very long single line); single lines paste directly',
'settings.render.suggest': 'Input suggestions',
'settings.render.suggestDesc':
'Show command suggestions while typing; Tab accepts, Enter always runs the command right away',
'settings.render.history': 'Record command history',
'settings.render.historyDesc': 'When off, new commands are no longer recorded; saved history is kept',
'settings.render.historyLimit': 'History limit',
'settings.render.historyLimitDesc': 'Most commands to keep; duplicates are stored only once',
'settings.render.recButton': 'Terminal toolbar · Record',
'settings.render.recButtonDesc': 'Show the "Record session log" button in the top-right corner',
'settings.render.openLogsButton': 'Terminal toolbar · Open log folder',
'settings.render.openLogsButtonDesc': 'Show the "Open log folder" button in the top-right corner',
'settings.render.openCwdButton': 'Terminal toolbar · Open workspace folder',
'settings.render.openCwdButtonDesc':
'Show the "Open current folder" button in the top-right corner (hidden in SSH sessions; the folder follows cd in real time and needs shell integration or the cd command)',
'settings.system.launchAtLogin': 'Launch at startup',
'settings.system.launchAtLoginDesc':
'Start OpenTerminal when the system boots (in development mode the dev build is registered)',
'settings.system.preventSleep': 'Prevent system sleep',
'settings.system.preventSleepDesc':
'While on, OpenTerminal keeps the system from sleeping automatically; when off, the system follows its own power settings',
'settings.system.restoreSession': 'Restore last session on startup',
'settings.system.restoreSessionDesc':
'Restore the split layout on the next launch and return each terminal to its last directory; when off, OpenTerminal always starts with a single terminal',
'settings.system.shellIntegration': 'Shell integration',
'settings.system.shellIntegrationDesc':
'Let the shell report its working directory (OSC 7) for more precise path tracking, including cd inside scripts; it wraps your prompt, so turn it off if the prompt theme looks wrong',
'settings.system.closeAction': 'Close button behavior',
'settings.system.closeActionDesc':
'What happens when you click the window close button; after minimizing to the tray you can quit from the tray icon context menu',
'settings.system.closeActionTray': 'Minimize to tray',
'settings.system.closeActionExit': 'Quit directly',
'settings.system.closeActionAsk': 'Ask every time',
'settings.system.globalShortcut': 'Global show/hide shortcut',
'settings.system.globalShortcutDesc':
'Click the field, then press the key combination; Esc cancels, Backspace clears and disables it',
'settings.system.globalShortcutHint':
'Together with the global key this shows or hides the window from anywhere; if registration fails (a conflict with another app) it simply has no effect and the app reports no error.',
'settings.system.shortcutRecording': 'Press the keys…',
'settings.system.shortcutPlaceholder': 'Click and press a shortcut, leave empty to disable',
'settings.highlight.alert':
'Custom highlighting improves readability at a small performance cost. Rules are applied in priority order. PS: colors are injected as text is written to the terminal, so existing scrollback is unaffected',
'settings.highlight.enabled': 'Enabled',
'settings.highlight.pattern': 'Pattern',
'settings.highlight.patternPlaceholder': 'e.g. \\b(ERROR|FAILED)\\b',
'settings.highlight.invalidRegex': 'Invalid regular expression',
'settings.highlight.priority': 'Priority',
'settings.highlight.priorityHint': 'Lower values apply first',
'settings.highlight.color': 'Color',
'settings.highlight.clearBg': 'Clear',
'settings.highlight.addBg': 'Add',
'settings.highlight.palette': 'Palette',
'settings.highlight.note': 'Note',
'settings.highlight.notePlaceholder': 'Rule description (optional)',
'settings.highlight.actions': 'Actions',
'settings.highlight.addRule': '+ Add rule',
'settings.highlight.empty': 'No highlight rules yet — click "+ Add rule" to create one',
'settings.highlight.deleteTitle': 'Delete highlight rule',
'settings.highlight.resetTitle': 'Restore default highlight rules',
'settings.highlight.resetDesc': 'Replaces every current rule with the built-in presets. This cannot be undone.',
'settings.highlight.resetOk': 'Restore',
'settings.highlight.createTitle': 'New highlight rule',
'settings.highlight.editTitle': 'Edit highlight rule',
'settings.theme.accent': 'Tab accent color',
'settings.theme.accentDesc': 'Accent color for the active tab border, the sidebar indicator, and SSH badges',
'settings.theme.customBadge': 'Custom',
'settings.theme.deleteTitle': 'Delete custom theme',
'settings.theme.create': 'New theme',
'settings.theme.editTitle': 'Edit theme',
'settings.themeEditor.name': 'Name',
'settings.themeEditor.namePlaceholder': 'Theme name',
'settings.themeEditor.copySuffix': ' (copy)',
'settings.about.currentVersion': 'Current version',
'settings.about.statusIdle': 'Click to check for updates',
'settings.about.statusChecking': 'Checking for updates…',
'settings.about.statusAvailable': 'A new version is available',
'settings.about.statusLatest': 'Already up to date',
'settings.about.statusDownloading': 'Downloading…',
'settings.about.statusDownloaded': 'Download complete — restart to install',
'settings.about.statusError': 'Check failed',
'settings.about.statusDev': 'Update checks are unavailable in development mode',
'settings.about.channelStable': 'Stable channel',
'settings.about.autoCheck': 'Check automatically at startup',
'settings.about.download': 'Download update',
'settings.about.downloadGithub': ' (GitHub source)',
'settings.about.install': 'Restart and install',
'settings.about.check': 'Check for updates',
'settings.about.checkingButton': 'Checking',
'settings.about.changelog': 'Changelog',
'settings.about.changelogEmpty': 'No changelog available'
}
export default settings
+150
View File
@@ -0,0 +1,150 @@
/** Namespace: ssh (ssh connections, host key prompt, file panel, zmodem, monitor). Owner: ssh area. */
const ssh: Record<string, string> = {
// Auth method / secret kind
'ssh.auth.password': 'Password',
'ssh.auth.privateKey': 'Private key',
'ssh.auth.agent': 'Agent',
'ssh.secret.passphrase': 'Passphrase',
// Connection dialog: auth fields
'ssh.fields.agentDesc':
'Authenticate with a key already loaded in the local SSH Agent; this app stores nothing for you.',
'ssh.fields.askPasswordLabel': 'Ask for password on connect',
'ssh.fields.askPasswordHint':
'Prompts for the password on every connection instead of using the saved one',
'ssh.fields.passwordPlaceholder': 'Leave empty to keep the saved password',
'ssh.fields.keyPath': 'Private key path (path on the server, optional)',
'ssh.fields.keyContent': 'Private key content',
'ssh.fields.keyContentPlaceholder':
'Paste the private key; leave empty to use the path above (leave empty while editing to keep the saved key)',
'ssh.fields.askPassphraseLabel': 'Ask for passphrase on connect',
'ssh.fields.askPassphraseHint': 'Prompts for the key passphrase on every connection',
'ssh.fields.passphrase': 'Key passphrase',
'ssh.fields.passphrasePlaceholder': 'Leave empty to keep the saved passphrase',
// Connection dialog
'ssh.dialog.titleEdit': 'Edit connection',
'ssh.dialog.titleNew': 'New connection',
'ssh.dialog.saveFailed': 'Save failed. Check your input and try again.',
'ssh.dialog.name': 'Name',
'ssh.dialog.nameRequired': 'Please enter a connection name',
'ssh.dialog.namePlaceholder': 'e.g. Production server',
'ssh.dialog.group': 'Group',
'ssh.dialog.groupPlaceholder': 'Pick or type a new group; leave empty for “Default”',
'ssh.dialog.host': 'Host',
'ssh.dialog.hostRequired': 'Please enter a host address',
'ssh.dialog.hostPlaceholder': '192.168.1.10 or example.com',
'ssh.dialog.port': 'Port',
'ssh.dialog.portRange': 'Port must be between 1 and 65535',
'ssh.dialog.username': 'Username',
'ssh.dialog.usernameRequired': 'Please enter a username',
'ssh.dialog.authMethod': 'Authentication',
'ssh.dialog.savedSecret': 'A {kind} is saved; leave empty to keep it',
'ssh.dialog.keepalive': 'Keepalive interval (seconds)',
'ssh.dialog.keepaliveTooltip': '0 disables keepalive',
'ssh.dialog.keepaliveMin': 'Cannot be negative',
// Connection sidebar
'ssh.sidebar.defaultGroup': 'Default',
'ssh.sidebar.timeJustNow': 'just now',
'ssh.sidebar.timeMinutesAgo': '{n} min ago',
'ssh.sidebar.timeHoursAgo': '{n} h ago',
'ssh.sidebar.timeDaysAgo': '{n} d ago',
'ssh.sidebar.modeTerminal': 'Terminal workspace',
'ssh.sidebar.modeSsh': 'SSH workspace',
'ssh.sidebar.title': 'Connections',
'ssh.sidebar.newConnection': 'New connection',
'ssh.sidebar.sectionTerminals': 'Terminals',
'ssh.sidebar.noLocalTerminals': 'No local terminal open',
'ssh.sidebar.local': 'Local',
'ssh.sidebar.sectionServers': 'SSH servers',
'ssh.sidebar.empty': 'No connections yet — click + to create one',
'ssh.sidebar.loading': 'Loading…',
'ssh.sidebar.recent': 'Recent sessions',
'ssh.sidebar.dblClickConnect': 'Double-click to connect to {host}',
'ssh.sidebar.deleteTitle': 'Delete this connection?',
'ssh.sidebar.deleteDesc':
'A deleted connection cannot be restored. Its saved key material is removed as well.',
// Host key verification
'ssh.hostKey.changedTitle': 'Host fingerprint changed!',
'ssh.hostKey.unknownHost': 'Unknown host',
'ssh.hostKey.accept': 'Accept and connect',
'ssh.hostKey.reject': 'Reject',
'ssh.hostKey.mitmTitle': 'Possible man-in-the-middle attack',
'ssh.hostKey.mitmDesc':
'The remote host key fingerprint differs from the one recorded earlier. Unless you changed the server key yourself, someone may be impersonating this host.',
'ssh.hostKey.firstConnect':
'First connection to this host; its fingerprint has not been recorded yet.',
'ssh.hostKey.target': 'Host: {target}',
'ssh.hostKey.fingerprint': 'Fingerprint: {fingerprint}',
// SSH workspace: file panel container, host badge
'ssh.bottomPanel.resize': 'Resize the file panel',
'ssh.hostBadge.aria': 'SSH host {label}',
// ZMODEM
'ssh.zmodem.done': 'ZMODEM transfer complete',
'ssh.zmodem.failed': 'ZMODEM transfer failed: {message}',
'ssh.zmodem.unknownError': 'unknown error',
'ssh.zmodem.titleReceive': 'Download to local',
'ssh.zmodem.titleSend': 'Upload to server',
'ssh.zmodem.pickDir': 'Choose save folder',
'ssh.zmodem.pickFiles': 'Choose files',
'ssh.zmodem.receiveDesc':
'An sz download request was detected (the remote side is sending files). Choose the local folder to save them in.',
'ssh.zmodem.sendDesc':
'An rz upload request was detected (the remote side is receiving files). Choose the files to upload.',
// File panel (SFTP)
'ssh.file.up': 'Parent folder',
'ssh.file.refresh': 'Refresh',
'ssh.file.uploadFile': 'Upload files',
'ssh.file.downloadSelected': 'Download selection',
'ssh.file.permOwner': 'Permissions / owner',
'ssh.file.open': 'Open',
'ssh.file.download': 'Download',
'ssh.file.upload': 'Upload…',
'ssh.file.rename': 'Rename',
'ssh.file.new': 'New',
'ssh.file.newFolder': 'New folder',
'ssh.file.copyPath': 'Copy path',
'ssh.file.copyPathFailed': 'Failed to copy the path',
'ssh.file.pathCopied': 'Path copied',
'ssh.file.permission': 'Permissions…',
'ssh.file.deleteTitle': 'Delete?',
'ssh.file.loading': 'Loading…',
'ssh.file.empty': 'Empty folder',
'ssh.file.modeUnavailable': 'Permissions unavailable',
'ssh.file.folderName': 'Folder name',
'ssh.file.create': 'Create',
'ssh.file.renameTitle': 'Rename {name}',
'ssh.file.permTitle': 'Permissions · {name}',
'ssh.file.permApplied': 'Permissions applied',
'ssh.file.octal': 'Octal',
'ssh.file.octalPlaceholder': 'e.g. 755',
'ssh.file.keepEmpty': 'Leave empty to keep',
'ssh.file.ownerHint': 'Leave UID/GID empty to keep the current owner',
'ssh.file.permRowOwner': 'Owner',
'ssh.file.permRowGroup': 'Group',
'ssh.file.permRowOther': 'Other',
'ssh.file.permColRead': 'Read',
'ssh.file.permColWrite': 'Write',
'ssh.file.permColExec': 'Execute',
// System monitor
'ssh.monitor.collecting': 'Collecting…',
'ssh.monitor.interrupted': 'Sampling stopped: {error}',
'ssh.monitor.mem': 'Memory',
'ssh.monitor.disks': 'Disks',
'ssh.monitor.net': 'Network',
'ssh.monitor.cores': '{n} cores',
'ssh.monitor.loadavg': 'Load {value}',
'ssh.monitor.uptime': 'Uptime',
'ssh.monitor.uptimeSeconds': '{n}s',
'ssh.monitor.uptimeMinutes': '{n} min',
'ssh.monitor.uptimeHours': '{h} h {m} min',
'ssh.monitor.uptimeDays': '{n} d'
}
export default ssh
+27
View File
@@ -0,0 +1,27 @@
/** Namespace: terminal (terminal view: context menu, search, paste confirm, toolbar, hints). Owner: workspace/terminal. */
const terminal: Record<string, string> = {
'terminal.menu.find': 'Find',
'terminal.menu.selectAll': 'Select all',
'terminal.menu.clear': 'Clear',
'terminal.search.placeholder': 'Search',
'terminal.search.prev': 'Previous',
'terminal.search.next': 'Next',
'terminal.search.found': 'Found',
'terminal.search.notFound': 'Not found',
'terminal.suggest.hint': '↑/↓ select · Tab accept · Esc close',
'terminal.rec.start': 'Start recording',
'terminal.rec.stop': 'Stop recording',
'terminal.rec.startLog': 'Start session log',
'terminal.rec.stopLog': 'Stop session log',
'terminal.rec.openLogs': 'Open logs folder',
'terminal.rec.openCwd': 'Open working directory',
'terminal.paste.title': 'Confirm paste',
'terminal.paste.message': 'Multi-line or potentially risky input detected. Paste it into the terminal?',
'terminal.paste.noPrompt': "Don't ask again this session",
'terminal.paste.disableDetection': 'Disable paste detection from now on',
'terminal.paste.hint':
'You can turn it back on or change the detection policy in the general terminal settings.',
'terminal.dead.message': 'Process exited (code {code})'
}
export default terminal
+61
View File
@@ -0,0 +1,61 @@
/** Namespace: workspace (workspace shell: sidebar, tabs, layout menu, split, empty states). Owner: workspace. */
const workspace: Record<string, string> = {
'workspace.tab.terminalTitle': 'Terminal {n}',
'workspace.tab.localTerminal': 'Local terminal',
'workspace.tab.closeOthers': 'Close others',
'workspace.tab.closeRight': 'Close to the right',
'workspace.tab.broadcastTarget': 'Broadcast target',
'workspace.tab.broadcastBadge': 'B',
'workspace.tab.addInSplit': 'New terminal in this split',
'workspace.newTerminal': 'New terminal',
'workspace.empty.terminalTitle': 'No terminals',
'workspace.empty.sshTitle': 'No SSH sessions',
'workspace.empty.sshHint': 'Connect from the server list on the left',
'workspace.rail.hideSidebar': 'Collapse sidebar',
'workspace.rail.showSidebar': 'Expand sidebar',
'workspace.rail.layout': 'Layout',
'workspace.rail.settings': 'Settings',
'workspace.rail.connecting': 'Connecting…',
'workspace.rail.terminalWorkspace': 'Terminal workspace',
'workspace.rail.sshWorkspace': 'SSH workspace',
'workspace.panel.hideSidebar': 'Collapse sidebar',
'workspace.panel.showSidebar': 'Expand sidebar',
'workspace.layout.splitRight': 'Split horizontally',
'workspace.layout.splitBelow': 'Split vertically',
'workspace.layout.saveTemplate': 'Save as template',
'workspace.layout.applyTemplate': 'Apply template',
'workspace.template.saveTitle': 'Save layout template',
'workspace.template.namePlaceholder': 'Template name',
'workspace.template.applyTitle': 'Apply layout template',
'workspace.template.empty': 'No saved templates',
'workspace.template.apply': 'Apply',
'workspace.template.deleteConfirm': 'Delete this template?',
'workspace.broadcast.toggle': 'Broadcast input',
'workspace.broadcast.activeTitle': 'Broadcasting ({count} targets)',
'workspace.broadcast.popoverTerminal': 'Broadcast input (Terminal)',
'workspace.broadcast.popoverSsh': 'Broadcast input (SSH)',
'workspace.broadcast.switch': 'Broadcast switch',
'workspace.broadcast.enabled': 'Enabled ({count})',
'workspace.broadcast.needTwo': 'Select at least 2 targets',
'workspace.broadcast.disabled': 'Disabled',
'workspace.broadcast.emptySsh': 'No SSH server sessions',
'workspace.broadcast.emptyTerminal': 'No terminals',
'workspace.broadcast.hint':
'Broadcasting turns on automatically once 2 or more terminals are picked, and turns off once fewer than 2 remain. Only sessions in the current mode can be picked.',
'workspace.hint.sshFromList': 'Connect SSH sessions from the server list',
'workspace.hint.connectSshFirst': 'Connect to an SSH server first',
'workspace.hint.noActiveTerminal': 'No active terminal — open at least one local terminal or SSH session',
'workspace.hint.noSessionInPanel': 'The active pane has no session available',
'workspace.connect.failed': 'SSH connection failed',
'workspace.connect.passwordTitle': 'Enter connection password',
'workspace.connect.passwordPlaceholder': 'Password',
'workspace.connect.passphraseTitle': 'Enter private key passphrase',
'workspace.connect.passphrasePlaceholder': 'Passphrase',
'workspace.connect.connecting': 'Connecting…',
'workspace.connect.connectingNamed': 'Connecting to {name}',
'workspace.connect.action': 'Connect',
'workspace.error.title': 'The interface hit an error',
'workspace.error.reload': 'Reload'
}
export default workspace
+17
View File
@@ -0,0 +1,17 @@
/** 名前空間: common(i18n 基盤、汎用ボタン・状態)。担当: i18n 基盤。 */
const common: Record<string, string> = {
'common.ok': 'OK',
'common.cancel': 'キャンセル',
'common.close': '閉じる',
'common.save': '保存',
'common.delete': '削除',
'common.edit': '編集',
'common.add': '追加',
'common.copy': 'コピー',
'common.paste': '貼り付け',
'common.reset': '既定値に戻す',
'common.language': '表示言語',
'common.languageDesc': '切り替えるとすぐに表示言語が反映され、保存後は永続化されます。'
}
export default common
+19
View File
@@ -0,0 +1,19 @@
import common from './common'
import settings from './settings'
import workspace from './workspace'
import terminal from './terminal'
import ssh from './ssh'
import panels from './panels'
import main from './main'
/** 日本語の文言。名前空間ファイルは領域ごとに分担して保守します。詳細は
* src/shared/i18n/index.ts の担当表を参照。 */
export default {
...common,
...settings,
...workspace,
...terminal,
...ssh,
...panels,
...main
}
+56
View File
@@ -0,0 +1,56 @@
/** 名前空間: main(メインプロセスの文言: トレイ、終了確認、アップデータ)。担当: メインプロセス。 */
const main: Record<string, string> = {
'main.tray.showWindow': 'メインウィンドウを表示',
'main.tray.closeAction': '閉じるボタンの動作',
'main.tray.askEveryTime': '毎回確認する',
'main.tray.minimizeToTray': 'トレイに最小化',
'main.tray.exitDirectly': '直接終了',
'main.tray.exit': '終了',
'main.tray.balloonTitle': 'トレイに最小化しました',
'main.tray.balloonContent': 'ターミナルセッションはバックグラウンドで実行中です。トレイアイコンをクリックするとウィンドウを復元できます。',
'main.tray.closeTitle': 'OpenTerminal を終了',
'main.tray.closeMessage': 'トレイに最小化しますか、それとも終了しますか?',
'main.tray.closeDetail': 'トレイに最小化すると、ターミナルセッションは実行を続けます。',
'main.tray.rememberChoice': '選択を記憶して今後確認しない',
'main.updater.feedFailed': '国内フィード: {gitea};GitHub: {github}',
'main.ssh.connectTimeout': '接続がタイムアウトしました ({host}:{port})',
'main.ssh.saveFingerprintFailed': 'ホスト鍵のフィンガープリントを保存できませんでした: {detail}',
'main.ssh.hostKeyRejected': 'ユーザーがホスト鍵を拒否しました',
'main.ssh.connectFailed': '接続に失敗しました {host}:{port}: {detail}',
'main.ssh.shellOpenFailed': 'SSH シェルを開けません ({host}:{port}): {detail}',
'main.ssh.initFailed': 'SSH 接続の初期化に失敗しました ({host}:{port}): {detail}',
'main.ssh.readKeyFailed': '秘密鍵ファイルを読み取れません {path}: {detail}',
'main.sftp.sessionGone': 'SSH セッションが存在しないか、切断されています',
'main.sftp.deleteFailed': '削除に失敗しました: {detail}',
'main.sftp.invalidMode': '不正なパーミッション値: {mode}',
'main.sftp.invalidUidGid': '不正な uid/gid',
'main.sftp.commandExitCode': 'コマンドの終了コード {code}',
'main.sftp.cancelled': 'キャンセルしました',
'main.zmodem.transferFailed': '転送に失敗しました',
'main.zmodem.transferTimeout': '転送がタイムアウトしました',
'main.zmodem.sendFailed': '送信に失敗しました',
'main.zmodem.uploadFailed': 'アップロードに失敗しました',
'main.zmodem.receiveFailed': '受信に失敗しました',
'main.zmodem.abnormal': 'ZMODEM 転送エラー',
'main.zmodem.cancelled': 'キャンセルしました',
'main.zmodem.offerTimedOut': 'ファイルが選択されなかったためキャンセルしました',
'main.zmodem.sessionInvalid': 'セッションが無効になりました',
'main.zmodem.sessionCreateFailed': 'ZMODEM セッションを確立できません',
'main.zmodem.noSaveDir': '保存先ディレクトリが指定されていません',
'main.zmodem.noFiles': 'ファイルが選択されていません',
'main.ipc.connectionMissing': '接続ブックマークが見つかりません ({id})',
'main.sysinfo.sessionGone': 'SSH セッションが存在しないか切断されています',
'main.sysinfo.execFailed': 'SSH exec に失敗しました',
'main.sysinfo.parseFailed': '解析に失敗しました: {message}',
'main.pty.serviceNotReady': 'SSH セッションサービスが未初期化です',
'main.pty.missingConnectionId': 'SSH セッションに connectionId がありません',
'main.log.tuiOmitted': '全画面 (TUI) 出力を省略しました'
}
export default main
+36
View File
@@ -0,0 +1,36 @@
/** 名前空間: panels(コマンドパネル、セッションログパネル、転送パネル)。担当: パネル。 */
const panels: Record<string, string> = {
// コマンドパネル
'panels.commands.sectionTitle': 'コマンド',
'panels.commands.target': '送信先',
'panels.commands.targetSsh': 'SSH サーバー',
'panels.commands.targetTerminal': 'ターミナル',
'panels.commands.tabHistory': '履歴',
'panels.commands.tabLibrary': 'コマンドライブラリ',
'panels.commands.historyTitle': '履歴コマンド',
'panels.commands.clearTitle': 'すべてのコマンド履歴を消去しますか?',
'panels.commands.clear': '消去',
'panels.commands.noHistory': 'コマンド履歴はありません',
'panels.commands.loading': '読み込み中…',
'panels.commands.libraryTitle': 'コマンドライブラリ',
'panels.commands.libraryEmpty': 'コマンドライブラリは空です',
'panels.commands.add': 'コマンドを追加',
'panels.commands.name': '名前',
'panels.commands.optional': '(任意)',
'panels.commands.command': 'コマンド',
'panels.commands.commandPlaceholder': '例:ls -la',
'panels.commands.note': 'メモ',
'panels.commands.deleteTitle': 'このコマンドを削除しますか?',
'panels.commands.deleteAria': 'コマンドを削除',
// 転送パネル
'panels.transfer.failed': '転送に失敗しました',
'panels.transfer.cancelled': 'キャンセル済み',
'panels.transfer.done': '転送が完了しました',
'panels.transfer.uploading': 'アップロード中',
'panels.transfer.downloading': 'ダウンロード中',
'panels.transfer.zmodemUploading': 'ZMODEM アップロード中',
'panels.transfer.zmodemDownloading': 'ZMODEM ダウンロード中'
}
export default panels
+150
View File
@@ -0,0 +1,150 @@
/** 名前空間: settings(設定ダイアログ: フォント/カーソル/描画/ハイライト/テーマ/システム/情報)。担当: 設定画面。 */
const settings: Record<string, string> = {
'settings.title': '設定',
'settings.tabs.font': 'フォント',
'settings.tabs.cursor': 'カーソルとスクロール',
'settings.tabs.render': '描画と動作',
'settings.tabs.highlight': 'ハイライト',
'settings.tabs.theme': 'テーマ',
'settings.tabs.system': 'システム',
'settings.tabs.about': 'このアプリについて',
'settings.resizeHandle': 'ドラッグしてサイズ変更',
'settings.preview': 'プレビュー',
'settings.deleteConfirmDesc': '削除すると元に戻せません。続けますか?',
'settings.color.foreground': '前景',
'settings.color.background': '背景',
'settings.color.cursor': 'カーソル',
'settings.color.selection': '選択範囲',
'settings.font.label': 'フォント',
'settings.font.desc': '組み込みの既定フォント、またはシステムの等幅フォント',
'settings.font.placeholder': 'フォントを選択',
'settings.font.default': 'デフォルト',
'settings.font.size': '文字サイズ',
'settings.font.sizeDesc': 'ターミナル文字のピクセルサイズ',
'settings.font.weight': '文字の太さ',
'settings.font.weightDesc': '400 が標準、700 が太字',
'settings.font.boldWeight': '太字の太さ',
'settings.font.boldWeightDesc': '太字テキストに使う太さ',
'settings.font.letterSpacing': '文字間隔',
'settings.font.letterSpacingDesc': '文字どうしの水平方向の間隔',
'settings.font.lineHeight': '行の高さ',
'settings.font.lineHeightDesc': '隣り合う行の垂直方向の距離',
'settings.cursor.blink': 'カーソルの点滅',
'settings.cursor.blinkDesc': 'カーソルを定期的に点滅させるかどうか',
'settings.cursor.style': 'カーソルの形状',
'settings.cursor.styleDesc': 'カーソルの表示形状',
'settings.cursor.inactiveStyle': '非アクティブ時のカーソル形状',
'settings.cursor.inactiveStyleDesc': 'ウィンドウがフォーカスを失ったときのカーソル形状',
'settings.cursor.scrollback': 'スクロールバック',
'settings.cursor.scrollbackDesc': 'さかのぼって表示できる行数',
'settings.cursorStyle.bar': '縦線 (bar)',
'settings.cursorStyle.block': 'ブロック (block)',
'settings.cursorStyle.underline': '下線 (underline)',
'settings.cursorStyle.outline': '輪郭 (outline)',
'settings.cursorStyle.none': 'なし (none)',
'settings.rendererMode.auto': '自動',
'settings.rendererMode.autoHint': 'WebGL による高速化を優先し、失敗したら DOM 描画に自動で切り替えます',
'settings.rendererMode.webgl': '高性能 WebGL',
'settings.rendererMode.webglHint': 'GPU 描画を強制します。高リフレッシュレートや大量行のスクロールに適します',
'settings.rendererMode.dom': '互換 DOM',
'settings.rendererMode.domHint': 'CPU のみで描画し、互換性を最優先します。GPU がない環境やリモートデスクトップに適します',
'settings.render.modeLabel': '描画モード',
'settings.render.modeHint': 'ターミナルセルの描画を高速化する方式。変更はすべてのターミナルに適用されます',
'settings.render.autoWrap': '自動折り返し',
'settings.render.autoWrapDesc': '幅を超えた行を自動で折り返します',
'settings.render.copyOnSelect': '選択時にコピー',
'settings.render.copyOnSelectDesc': 'マウスで文字を選択すると自動でコピーします',
'settings.render.pasteRiskConfirm': '貼り付け前の確認',
'settings.render.pasteRiskConfirmDesc':
'複数行(または極端に長い 1 行)を貼り付ける前に確認します。1 行はそのまま貼り付けます',
'settings.render.suggest': '入力候補',
'settings.render.suggestDesc':
'入力中にコマンド候補を表示します。Tab で確定、Enter は常にそのまま実行します',
'settings.render.history': 'コマンド履歴を記録',
'settings.render.historyDesc': 'オフにすると新しいコマンドを記録しません。保存済みの履歴は残ります',
'settings.render.historyLimit': '履歴の上限件数',
'settings.render.historyLimitDesc': 'コマンド履歴の最大件数。重複したコマンドは 1 件として記録します',
'settings.render.recButton': 'ターミナルツールバー · 記録',
'settings.render.recButtonDesc': '右上に「セッションログを記録」ボタンを表示します',
'settings.render.openLogsButton': 'ターミナルツールバー · ログフォルダーを開く',
'settings.render.openLogsButtonDesc': '右上に「ログフォルダーを開く」ボタンを表示します',
'settings.render.openCwdButton': 'ターミナルツールバー · ワークスペースフォルダーを開く',
'settings.render.openCwdButtonDesc':
'右上に「現在のフォルダーを開く」ボタンを表示します(SSH セッションでは非表示。フォルダーは cd に追従するため、shell 統合を有効にするか cd コマンドを使ってください)',
'settings.system.launchAtLogin': 'スタートアップ時に起動',
'settings.system.launchAtLoginDesc': 'OS の起動時に自動で起動します(開発モードでは開発版が登録されます)',
'settings.system.preventSleep': 'スリープを防止',
'settings.system.preventSleepDesc':
'オンにすると OpenTerminal がシステムの自動スリープを防ぎます。オフにすると OS の設定どおりにスリープします',
'settings.system.restoreSession': '起動時に前回のセッションを復元',
'settings.system.restoreSessionDesc':
'次回の起動で分割レイアウトを復元し、各ターミナルを前回のディレクトリに戻します。オフにすると毎回 1 つのターミナルで起動します',
'settings.system.shellIntegration': 'Shell 統合',
'settings.system.shellIntegrationDesc':
'shell に作業ディレクトリを報告させ(OSC 7)、パスの記憶をより正確にします(スクリプト内の cd も含みます)。プロンプトをラップするため、プロンプトの表示が崩れる場合はオフにしてください',
'settings.system.closeAction': '閉じるボタンの動作',
'settings.system.closeActionDesc':
'ウィンドウの閉じるボタンを押したときの動作。タスクトレイに最小化した後は、トレイアイコンの右クリックメニューから終了できます',
'settings.system.closeActionTray': 'タスクトレイに最小化',
'settings.system.closeActionExit': 'そのまま終了',
'settings.system.closeActionAsk': '毎回確認する',
'settings.system.globalShortcut': 'グローバル呼び出しショートカット',
'settings.system.globalShortcutDesc':
'入力欄をクリックしてからキーの組み合わせを押します。Esc で取り消し、Backspace でクリアして無効化します',
'settings.system.globalShortcutHint':
'グローバルキーと組み合わせると、どの画面からでもウィンドウを呼び出し/非表示にできます。登録に失敗した場合(他のソフトとの競合)は効果がなく、アプリにエラーは表示されません。',
'settings.system.shortcutRecording': 'キーを押してください…',
'settings.system.shortcutPlaceholder': 'クリックしてショートカットを押す。空欄で無効',
'settings.highlight.alert':
'独自のハイライトは見やすさを高めますが、わずかに性能を消費します。ルールは優先順に適用されます。PS: ハイライトはターミナルへの書き込み時に色を注入するため、既存のスクロールバックには反映されません',
'settings.highlight.enabled': '有効',
'settings.highlight.pattern': '正規表現',
'settings.highlight.patternPlaceholder': '例: \\b(ERROR|FAILED)\\b',
'settings.highlight.invalidRegex': '正規表現が無効です',
'settings.highlight.priority': '優先度',
'settings.highlight.priorityHint': '値が小さいほど先に適用されます',
'settings.highlight.color': '色',
'settings.highlight.clearBg': 'クリア',
'settings.highlight.addBg': '追加',
'settings.highlight.palette': 'パレット',
'settings.highlight.note': 'メモ',
'settings.highlight.notePlaceholder': 'ルールの説明(任意)',
'settings.highlight.actions': '操作',
'settings.highlight.addRule': '+ ルールを追加',
'settings.highlight.empty': 'ハイライトルールがありません。「+ ルールを追加」から作成できます',
'settings.highlight.deleteTitle': 'ハイライトルールを削除',
'settings.highlight.resetTitle': '既定のハイライトルールに戻す',
'settings.highlight.resetDesc': '現在のすべてのルールを組み込みのプリセットに置き換えます。元に戻せません。',
'settings.highlight.resetOk': '元に戻す',
'settings.highlight.createTitle': 'ハイライトルールを作成',
'settings.highlight.editTitle': 'ハイライトルールを編集',
'settings.theme.accent': 'タブのアクセントカラー',
'settings.theme.accentDesc': 'アクティブなタブの枠線、サイドバーのインジケーター、SSH バッジのアクセントカラー',
'settings.theme.customBadge': 'カスタム',
'settings.theme.deleteTitle': 'カスタムテーマを削除',
'settings.theme.create': '新しいテーマ',
'settings.theme.editTitle': 'テーマを編集',
'settings.themeEditor.name': '名前',
'settings.themeEditor.namePlaceholder': 'テーマ名',
'settings.themeEditor.copySuffix': '(コピー)',
'settings.about.currentVersion': '現在のバージョン',
'settings.about.statusIdle': 'クリックして更新を確認',
'settings.about.statusChecking': '更新を確認しています…',
'settings.about.statusAvailable': '新しいバージョンがあります',
'settings.about.statusLatest': '最新バージョンです',
'settings.about.statusDownloading': 'ダウンロードしています…',
'settings.about.statusDownloaded': 'ダウンロード完了。再起動してインストールできます',
'settings.about.statusError': '確認に失敗しました',
'settings.about.statusDev': '開発モードでは更新を確認できません',
'settings.about.channelStable': '安定版チャンネル',
'settings.about.autoCheck': '起動時に自動で確認',
'settings.about.download': '更新をダウンロード',
'settings.about.downloadGithub': '(GitHub ソース)',
'settings.about.install': '再起動してインストール',
'settings.about.check': '更新を確認',
'settings.about.checkingButton': '確認中',
'settings.about.changelog': '更新履歴',
'settings.about.changelogEmpty': '更新履歴はありません'
}
export default settings
+152
View File
@@ -0,0 +1,152 @@
/** 名前空間: 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': '8 進数',
'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
+26
View File
@@ -0,0 +1,26 @@
/** 名前空間: terminal(ターミナル表示:コンテキストメニュー、検索、貼り付け確認、ツールバー、ヒント)。担当: ワークスペース/ターミナル。 */
const terminal: Record<string, string> = {
'terminal.menu.find': '検索',
'terminal.menu.selectAll': 'すべて選択',
'terminal.menu.clear': '画面クリア',
'terminal.search.placeholder': '検索',
'terminal.search.prev': '前へ',
'terminal.search.next': '次へ',
'terminal.search.found': '見つかりました',
'terminal.search.notFound': '見つかりません',
'terminal.suggest.hint': '↑/↓ 選択 · Tab で確定 · Esc で閉じる',
'terminal.rec.start': '記録開始',
'terminal.rec.stop': '記録停止',
'terminal.rec.startLog': 'セッションログの記録を開始',
'terminal.rec.stopLog': 'セッションログの記録を停止',
'terminal.rec.openLogs': 'ログフォルダーを開く',
'terminal.rec.openCwd': 'ワークスペースフォルダーを開く',
'terminal.paste.title': '貼り付けの確認',
'terminal.paste.message': '複数行または危険な可能性のあるコマンドを検出しました。ターミナルに貼り付けますか?',
'terminal.paste.noPrompt': 'このセッションでは表示しない',
'terminal.paste.disableDetection': '今後の貼り付けチェックを無効にする',
'terminal.paste.hint': '一般のターミナル設定で再度有効にするか、検出ポリシーを変更できます。',
'terminal.dead.message': 'プロセスが終了しました (コード {code})'
}
export default terminal
+62
View File
@@ -0,0 +1,62 @@
/** 名前空間: workspace(ワークスペース外装:サイドバー、タブ、レイアウトメニュー、分割、空状態)。担当: ワークスペース。 */
const workspace: Record<string, string> = {
'workspace.tab.terminalTitle': 'ターミナル {n}',
'workspace.tab.localTerminal': 'ローカルターミナル',
'workspace.tab.closeOthers': 'ほかを閉じる',
'workspace.tab.closeRight': '右側を閉じる',
'workspace.tab.broadcastTarget': 'ブロードキャスト対象',
'workspace.tab.broadcastBadge': '配',
'workspace.tab.addInSplit': 'この分割に新しいターミナル',
'workspace.newTerminal': '新規ターミナル',
'workspace.empty.terminalTitle': 'ターミナルがありません',
'workspace.empty.sshTitle': 'SSH セッションがありません',
'workspace.empty.sshHint': '左側のサーバー一覧から接続してください',
'workspace.rail.hideSidebar': 'サイドバーを折りたたむ',
'workspace.rail.showSidebar': 'サイドバーを展開',
'workspace.rail.layout': 'レイアウト',
'workspace.rail.settings': '設定',
'workspace.rail.connecting': '接続中…',
'workspace.rail.terminalWorkspace': 'ターミナルワークスペース',
'workspace.rail.sshWorkspace': 'SSH ワークスペース',
'workspace.panel.hideSidebar': 'サイドバーを折りたたむ',
'workspace.panel.showSidebar': 'サイドバーを展開',
'workspace.layout.splitRight': '水平分割',
'workspace.layout.splitBelow': '垂直分割',
'workspace.layout.saveTemplate': 'テンプレートとして保存',
'workspace.layout.applyTemplate': 'テンプレートを適用',
'workspace.template.saveTitle': 'レイアウトテンプレートを保存',
'workspace.template.namePlaceholder': 'テンプレート名',
'workspace.template.applyTitle': 'レイアウトテンプレートを適用',
'workspace.template.empty': '保存済みのテンプレートはありません',
'workspace.template.apply': '適用',
'workspace.template.deleteConfirm': 'このテンプレートを削除しますか?',
'workspace.broadcast.toggle': 'ブロードキャスト入力',
'workspace.broadcast.activeTitle': 'ブロードキャスト中({count} 件の対象)',
'workspace.broadcast.popoverTerminal': 'ブロードキャスト入力(ターミナル)',
'workspace.broadcast.popoverSsh': 'ブロードキャスト入力(SSH)',
'workspace.broadcast.switch': 'ブロードキャストスイッチ',
'workspace.broadcast.enabled': '有効({count})',
'workspace.broadcast.needTwo': '対象を 2 つ以上選択してください',
'workspace.broadcast.disabled': '無効',
'workspace.broadcast.emptySsh': 'SSH サーバーセッションがありません',
'workspace.broadcast.emptyTerminal': 'ターミナルがありません',
'workspace.broadcast.hint':
'ターミナルを 2 つ以上選ぶとブロードキャストが自動的に有効になり、対象が 2 つ未満になると自動的に解除されます。選択できるのは現在のモードのセッションだけです。',
'workspace.hint.sshFromList': 'SSH セッションはサーバー一覧から接続してください',
'workspace.hint.connectSshFirst': '先に SSH サーバーへ接続してください',
'workspace.hint.noActiveTerminal':
'有効なターミナルがありません。ローカルターミナルまたは SSH セッションを 1 つ以上開いてください',
'workspace.hint.noSessionInPanel': '現在アクティブなパネルに利用できるセッションがありません',
'workspace.connect.failed': 'SSH 接続に失敗しました',
'workspace.connect.passwordTitle': '接続パスワードを入力',
'workspace.connect.passwordPlaceholder': 'パスワード',
'workspace.connect.passphraseTitle': '秘密鍵のパスフレーズを入力',
'workspace.connect.passphrasePlaceholder': 'パスフレーズ',
'workspace.connect.connecting': '接続中…',
'workspace.connect.connectingNamed': '{name} に接続しています',
'workspace.connect.action': '接続',
'workspace.error.title': '画面でエラーが発生しました',
'workspace.error.reload': '再読み込み'
}
export default workspace
+17
View File
@@ -0,0 +1,17 @@
/** 命名空间:通用(i18n 基础设施、通用按钮与状态)。归属:i18n 基础设施维护者。 */
const common: Record<string, string> = {
'common.ok': '确定',
'common.cancel': '取消',
'common.close': '关闭',
'common.save': '保存',
'common.delete': '删除',
'common.edit': '编辑',
'common.add': '新增',
'common.copy': '复制',
'common.paste': '粘贴',
'common.reset': '恢复默认',
'common.language': '界面语言',
'common.languageDesc': '切换后立即预览界面语言,保存后永久生效。'
}
export default common
+18
View File
@@ -0,0 +1,18 @@
import common from './common'
import settings from './settings'
import workspace from './workspace'
import terminal from './terminal'
import ssh from './ssh'
import panels from './panels'
import main from './main'
/** 简体中文词条。命名空间文件按区域分工维护,详见 src/shared/i18n/index.ts 的归属表。 */
export default {
...common,
...settings,
...workspace,
...terminal,
...ssh,
...panels,
...main
}
+56
View File
@@ -0,0 +1,56 @@
/** 命名空间:main(主进程文案:托盘、关闭询问、更新器)。归属:主进程维护者。 */
const main: Record<string, string> = {
'main.tray.showWindow': '显示主窗口',
'main.tray.closeAction': '关闭按钮行为',
'main.tray.askEveryTime': '每次询问',
'main.tray.minimizeToTray': '最小化到托盘',
'main.tray.exitDirectly': '直接退出',
'main.tray.exit': '退出',
'main.tray.balloonTitle': '已最小化到托盘',
'main.tray.balloonContent': '终端会话仍在后台运行,点击托盘图标可恢复窗口。',
'main.tray.closeTitle': '关闭 OpenTerminal',
'main.tray.closeMessage': '最小化到托盘,还是直接退出?',
'main.tray.closeDetail': '最小化到托盘时终端会话保持运行。',
'main.tray.rememberChoice': '记住我的选择,不再询问',
'main.updater.feedFailed': '国内源: {gitea};GitHub: {github}',
'main.ssh.connectTimeout': '连接超时 ({host}:{port})',
'main.ssh.saveFingerprintFailed': '保存主机指纹失败: {detail}',
'main.ssh.hostKeyRejected': '用户拒绝了主机指纹',
'main.ssh.connectFailed': '连接失败 {host}:{port}: {detail}',
'main.ssh.shellOpenFailed': '无法打开 SSH shell ({host}:{port}): {detail}',
'main.ssh.initFailed': 'SSH 连接初始化失败 ({host}:{port}): {detail}',
'main.ssh.readKeyFailed': '无法读取私钥文件 {path}: {detail}',
'main.sftp.sessionGone': 'SSH 会话不存在或已断开',
'main.sftp.deleteFailed': '删除失败: {detail}',
'main.sftp.invalidMode': '非法权限值: {mode}',
'main.sftp.invalidUidGid': '非法 uid/gid',
'main.sftp.commandExitCode': '命令退出码 {code}',
'main.sftp.cancelled': '已取消',
'main.zmodem.transferFailed': '传输失败',
'main.zmodem.transferTimeout': '传输超时',
'main.zmodem.sendFailed': '发送失败',
'main.zmodem.uploadFailed': '上传失败',
'main.zmodem.receiveFailed': '接收失败',
'main.zmodem.abnormal': 'ZMODEM 传输异常',
'main.zmodem.cancelled': '已取消',
'main.zmodem.offerTimedOut': '未选择文件,已取消',
'main.zmodem.sessionInvalid': '会话已失效',
'main.zmodem.sessionCreateFailed': '无法建立 ZMODEM 会话',
'main.zmodem.noSaveDir': '未指定保存目录',
'main.zmodem.noFiles': '未选择文件',
'main.ipc.connectionMissing': '连接书签不存在 ({id})',
'main.sysinfo.sessionGone': 'SSH 会话不存在或已断开',
'main.sysinfo.execFailed': 'SSH exec 失败',
'main.sysinfo.parseFailed': '解析失败: {message}',
'main.pty.serviceNotReady': 'SSH 会话服务尚未初始化',
'main.pty.missingConnectionId': 'SSH 会话缺少 connectionId',
'main.log.tuiOmitted': '全屏界面(TUI)输出已省略'
}
export default main
+36
View File
@@ -0,0 +1,36 @@
/** 命名空间:panels(命令面板、会话日志面板、传输面板)。归属:SSH/面板维护者。 */
const panels: Record<string, string> = {
// 命令面板
'panels.commands.sectionTitle': '命令',
'panels.commands.target': '发送目标',
'panels.commands.targetSsh': 'SSH 服务器',
'panels.commands.targetTerminal': '终端',
'panels.commands.tabHistory': '历史',
'panels.commands.tabLibrary': '命令库',
'panels.commands.historyTitle': '历史命令',
'panels.commands.clearTitle': '清空全部命令历史?',
'panels.commands.clear': '清空',
'panels.commands.noHistory': '暂无历史命令',
'panels.commands.loading': '加载中…',
'panels.commands.libraryTitle': '命令库',
'panels.commands.libraryEmpty': '命令库为空',
'panels.commands.add': '新增命令',
'panels.commands.name': '名称',
'panels.commands.optional': '(可选)',
'panels.commands.command': '命令',
'panels.commands.commandPlaceholder': '如 ls -la',
'panels.commands.note': '备注',
'panels.commands.deleteTitle': '删除该命令?',
'panels.commands.deleteAria': '删除命令',
// 传输面板
'panels.transfer.failed': '传输失败',
'panels.transfer.cancelled': '已取消',
'panels.transfer.done': '传输完成',
'panels.transfer.uploading': '上传中',
'panels.transfer.downloading': '下载中',
'panels.transfer.zmodemUploading': 'ZMODEM 上传中',
'panels.transfer.zmodemDownloading': 'ZMODEM 下载中'
}
export default panels
+147
View File
@@ -0,0 +1,147 @@
/** 命名空间:settings(设置弹窗:字体/光标/渲染/高亮/主题/系统/关于)。归属:设置页维护者。 */
const settings: Record<string, string> = {
'settings.title': '设置',
'settings.tabs.font': '字体',
'settings.tabs.cursor': '光标与滚动',
'settings.tabs.render': '渲染与行为',
'settings.tabs.highlight': '高亮',
'settings.tabs.theme': '主题',
'settings.tabs.system': '系统',
'settings.tabs.about': '关于',
'settings.resizeHandle': '拖拽调整大小',
'settings.preview': '预览',
'settings.deleteConfirmDesc': '删除后无法恢复,确定继续?',
'settings.color.foreground': '前景',
'settings.color.background': '背景',
'settings.color.cursor': '光标',
'settings.color.selection': '选区',
'settings.font.label': '字体',
'settings.font.desc': '内置默认字体或系统等宽字体',
'settings.font.placeholder': '选择字体',
'settings.font.default': '默认',
'settings.font.size': '字号',
'settings.font.sizeDesc': '终端文字的像素大小',
'settings.font.weight': '字重',
'settings.font.weightDesc': '400 为常规,700 为粗体',
'settings.font.boldWeight': '粗体字重',
'settings.font.boldWeightDesc': '粗体文字所用的字重',
'settings.font.letterSpacing': '字间距',
'settings.font.letterSpacingDesc': '字符之间的水平间距',
'settings.font.lineHeight': '行高',
'settings.font.lineHeightDesc': '相邻两行之间的垂直距离',
'settings.cursor.blink': '光标闪烁',
'settings.cursor.blinkDesc': '光标是否周期性闪烁',
'settings.cursor.style': '光标样式',
'settings.cursor.styleDesc': '光标的显示形状',
'settings.cursor.inactiveStyle': '非活动光标样式',
'settings.cursor.inactiveStyleDesc': '窗口失焦时光标样式',
'settings.cursor.scrollback': '滚动缓冲区',
'settings.cursor.scrollbackDesc': '屏幕上可回滚的行数',
'settings.cursorStyle.bar': '竖线 (bar)',
'settings.cursorStyle.block': '方块 (block)',
'settings.cursorStyle.underline': '下划线 (underline)',
'settings.cursorStyle.outline': '轮廓 (outline)',
'settings.cursorStyle.none': '无 (none)',
'settings.rendererMode.auto': '自动',
'settings.rendererMode.autoHint': '优先使用 WebGL 加速,失败时自动回退到 DOM 渲染',
'settings.rendererMode.webgl': '高性能 WebGL',
'settings.rendererMode.webglHint': '强制使用 GPU 加速渲染,适合高刷新率与大行数滚动',
'settings.rendererMode.dom': '兼容 DOM',
'settings.rendererMode.domHint': '纯 CPU 渲染,兼容性最好,适合无 GPU 或远程桌面环境',
'settings.render.modeLabel': '渲染模式',
'settings.render.modeHint': '终端单元渲染加速方式,改动将应用到所有终端',
'settings.render.autoWrap': '自动换行',
'settings.render.autoWrapDesc': '超出宽度时自动折行',
'settings.render.copyOnSelect': '选中即复制',
'settings.render.copyOnSelectDesc': '鼠标选中文字时自动复制',
'settings.render.pasteRiskConfirm': '粘贴风险确认',
'settings.render.pasteRiskConfirmDesc': '多行文本(或超长单行)粘贴前弹出确认;单行直接粘贴',
'settings.render.suggest': '输入建议',
'settings.render.suggestDesc': '输入时弹出命令建议;Tab 接受,回车始终直接执行',
'settings.render.history': '记录命令历史',
'settings.render.historyDesc': '关闭后不再记录新命令;已保存的历史仍然保留',
'settings.render.historyLimit': '历史条数上限',
'settings.render.historyLimitDesc': '命令历史最多保留多少条,重复命令只记一次',
'settings.render.recButton': '终端工具栏 · 录制',
'settings.render.recButtonDesc': '右上角显示「记录会话日志」按钮',
'settings.render.openLogsButton': '终端工具栏 · 打开日志目录',
'settings.render.openLogsButtonDesc': '右上角显示「打开日志目录」按钮',
'settings.render.openCwdButton': '终端工具栏 · 打开工作区目录',
'settings.render.openCwdButtonDesc':
'右上角显示「打开当前目录」按钮(SSH 会话不显示;目录随 cd 实时跟踪,需开启 shell 集成或使用 cd 命令)',
'settings.system.launchAtLogin': '开机时自启动',
'settings.system.launchAtLoginDesc': '开机时自动启动软件(开发模式下注册的是开发版程序)',
'settings.system.preventSleep': '阻止系统休眠',
'settings.system.preventSleepDesc':
'开启后 OpenTerminal 将阻止系统自动休眠;关闭则允许系统按系统设置休眠',
'settings.system.restoreSession': '启动时恢复上次会话',
'settings.system.restoreSessionDesc':
'下次启动恢复分屏布局,并让每个终端回到它上次所在的目录;关闭则每次都以单个终端启动',
'settings.system.shellIntegration': 'Shell 集成',
'settings.system.shellIntegrationDesc':
'让 shell 主动上报工作目录(OSC 7),路径记忆更精确(含脚本内的 cd);会包装你的命令提示符,遇到提示符主题异常时关掉即可',
'settings.system.closeAction': '关闭按钮行为',
'settings.system.closeActionDesc':
'点击窗口关闭按钮时的动作;最小化到托盘后可在托盘图标右键菜单中退出',
'settings.system.closeActionTray': '最小化到托盘',
'settings.system.closeActionExit': '直接退出',
'settings.system.closeActionAsk': '每次询问',
'settings.system.globalShortcut': '全局唤起快捷键',
'settings.system.globalShortcutDesc': '点击输入框后直接按下组合键;Esc 取消,退格清空禁用',
'settings.system.globalShortcutHint':
'配合全局键可在任何界面唤起/隐藏窗口;若注册失败(与其他软件冲突)则不生效,应用不会报错。',
'settings.system.shortcutRecording': '按下组合键…',
'settings.system.shortcutPlaceholder': '点击后按下快捷键,留空禁用',
'settings.highlight.alert':
'自定义高亮可增强显示效果,但会略微增加性能消耗。规则按优先级顺序应用。PS: 高亮在写入终端时注入颜色,对已有回滚内容不生效',
'settings.highlight.enabled': '启用',
'settings.highlight.pattern': '正则',
'settings.highlight.patternPlaceholder': '例如 \\b(ERROR|FAILED)\\b',
'settings.highlight.invalidRegex': '正则表达式无效',
'settings.highlight.priority': '优先级',
'settings.highlight.priorityHint': '值越小越先应用',
'settings.highlight.color': '颜色',
'settings.highlight.clearBg': '清空',
'settings.highlight.addBg': '添加',
'settings.highlight.palette': '色板',
'settings.highlight.note': '备注',
'settings.highlight.notePlaceholder': '规则说明(可选)',
'settings.highlight.actions': '操作',
'settings.highlight.addRule': '+ 新增规则',
'settings.highlight.empty': '暂无高亮规则,点击「+ 新增规则」创建',
'settings.highlight.deleteTitle': '删除高亮规则',
'settings.highlight.resetTitle': '恢复默认高亮规则',
'settings.highlight.resetDesc': '将替换当前全部规则为内置预设,不可恢复。',
'settings.highlight.resetOk': '恢复',
'settings.highlight.createTitle': '新建高亮规则',
'settings.highlight.editTitle': '编辑高亮规则',
'settings.theme.accent': '标签强调色',
'settings.theme.accentDesc': '活动标签边框、侧栏指示条与 SSH 徽章的强调颜色',
'settings.theme.customBadge': '自定义',
'settings.theme.deleteTitle': '删除自定义主题',
'settings.theme.create': '新建主题',
'settings.theme.editTitle': '编辑主题',
'settings.themeEditor.name': '名称',
'settings.themeEditor.namePlaceholder': '主题名称',
'settings.themeEditor.copySuffix': '(副本)',
'settings.about.currentVersion': '当前版本',
'settings.about.statusIdle': '点击检查更新',
'settings.about.statusChecking': '正在检查更新…',
'settings.about.statusAvailable': '发现新版本',
'settings.about.statusLatest': '已经是最新版本',
'settings.about.statusDownloading': '正在下载…',
'settings.about.statusDownloaded': '下载完成,可重启安装',
'settings.about.statusError': '检查失败',
'settings.about.statusDev': '开发模式不支持更新检查',
'settings.about.channelStable': '稳定更新通道',
'settings.about.autoCheck': '启动时自动检查',
'settings.about.download': '下载更新',
'settings.about.downloadGithub': '(GitHub 源)',
'settings.about.install': '重启安装',
'settings.about.check': '检查更新',
'settings.about.checkingButton': '检查中',
'settings.about.changelog': '更新日志',
'settings.about.changelogEmpty': '暂无更新日志'
}
export default settings
+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
+26
View File
@@ -0,0 +1,26 @@
/** 命名空间:terminal(终端视图:右键菜单、搜索、粘贴确认、工具条、提示)。归属:工作区/终端维护者。 */
const terminal: Record<string, string> = {
'terminal.menu.find': '查找',
'terminal.menu.selectAll': '全选',
'terminal.menu.clear': '清屏',
'terminal.search.placeholder': '搜索',
'terminal.search.prev': '上一个',
'terminal.search.next': '下一个',
'terminal.search.found': '已找到',
'terminal.search.notFound': '未找到',
'terminal.suggest.hint': '↑/↓ 选择 · Tab 接受 · Esc 关闭',
'terminal.rec.start': '开始记录',
'terminal.rec.stop': '停止记录',
'terminal.rec.startLog': '开始记录会话日志',
'terminal.rec.stopLog': '停止记录会话日志',
'terminal.rec.openLogs': '打开日志目录',
'terminal.rec.openCwd': '打开工作区目录',
'terminal.paste.title': '确认粘贴',
'terminal.paste.message': '检测到多行或潜在危险命令,确定要粘贴到终端吗?',
'terminal.paste.noPrompt': '本次会话不再提示',
'terminal.paste.disableDetection': '关闭后续粘贴检测',
'terminal.paste.hint': '可在通用终端设置中重新开启或切换检测策略。',
'terminal.dead.message': '进程已退出 (代码 {code})'
}
export default terminal
+60
View File
@@ -0,0 +1,60 @@
/** 命名空间:workspace(工作区外壳:侧栏、标签、布局菜单、分屏、空状态)。归属:工作区维护者。 */
const workspace: Record<string, string> = {
'workspace.tab.terminalTitle': '终端 {n}',
'workspace.tab.localTerminal': '本地终端',
'workspace.tab.closeOthers': '关闭其他',
'workspace.tab.closeRight': '关闭右侧',
'workspace.tab.broadcastTarget': '广播目标',
'workspace.tab.broadcastBadge': '播',
'workspace.tab.addInSplit': '在此分屏中新建终端',
'workspace.newTerminal': '新建终端',
'workspace.empty.terminalTitle': '暂无终端',
'workspace.empty.sshTitle': '暂无 SSH 会话',
'workspace.empty.sshHint': '请从左侧服务器列表连接',
'workspace.rail.hideSidebar': '收起侧栏',
'workspace.rail.showSidebar': '展开侧栏',
'workspace.rail.layout': '布局',
'workspace.rail.settings': '设置',
'workspace.rail.connecting': '正在连接…',
'workspace.rail.terminalWorkspace': '终端工作区',
'workspace.rail.sshWorkspace': 'SSH 工作区',
'workspace.panel.hideSidebar': '收起侧边栏',
'workspace.panel.showSidebar': '展开侧边栏',
'workspace.layout.splitRight': '水平分屏',
'workspace.layout.splitBelow': '垂直分屏',
'workspace.layout.saveTemplate': '保存为模板',
'workspace.layout.applyTemplate': '应用模板',
'workspace.template.saveTitle': '保存布局模板',
'workspace.template.namePlaceholder': '模板名称',
'workspace.template.applyTitle': '应用布局模板',
'workspace.template.empty': '暂无已保存的模板',
'workspace.template.apply': '应用',
'workspace.template.deleteConfirm': '删除该模板?',
'workspace.broadcast.toggle': '广播输入',
'workspace.broadcast.activeTitle': '广播中 ({count} 个目标)',
'workspace.broadcast.popoverTerminal': '广播输入(终端)',
'workspace.broadcast.popoverSsh': '广播输入(SSH)',
'workspace.broadcast.switch': '广播开关',
'workspace.broadcast.enabled': '已启用 ({count})',
'workspace.broadcast.needTwo': '需至少选择 2 个目标',
'workspace.broadcast.disabled': '未启用',
'workspace.broadcast.emptySsh': '暂无 SSH 服务器会话',
'workspace.broadcast.emptyTerminal': '暂无终端',
'workspace.broadcast.hint': '选择 ≥2 个终端后广播自动开启;关闭任意一个使目标少于 2 个时自动关闭。仅当前模式组的会话可被勾选。',
'workspace.hint.sshFromList': 'SSH 会话请从服务器列表连接',
'workspace.hint.connectSshFirst': '请先连接 SSH 服务器',
'workspace.hint.noActiveTerminal': '没有激活的终端:请至少打开一个本地终端或 SSH 会话',
'workspace.hint.noSessionInPanel': '当前激活面板没有可用的会话',
'workspace.connect.failed': 'SSH 连接失败',
'workspace.connect.passwordTitle': '输入连接密码',
'workspace.connect.passwordPlaceholder': '密码',
'workspace.connect.passphraseTitle': '输入私钥口令',
'workspace.connect.passphrasePlaceholder': '私钥口令',
'workspace.connect.connecting': '连接中…',
'workspace.connect.connectingNamed': '正在连接 {name}',
'workspace.connect.action': '连接',
'workspace.error.title': '界面出现异常',
'workspace.error.reload': '重新加载'
}
export default workspace
+17
View File
@@ -0,0 +1,17 @@
/** 命名空間:通用(i18n 基礎設施、通用按鈕與狀態)。歸屬:i18n 基礎設施維護者。 */
const common: Record<string, string> = {
'common.ok': '確定',
'common.cancel': '取消',
'common.close': '關閉',
'common.save': '儲存',
'common.delete': '刪除',
'common.edit': '編輯',
'common.add': '新增',
'common.copy': '複製',
'common.paste': '貼上',
'common.reset': '恢復預設',
'common.language': '介面語言',
'common.languageDesc': '切換後立即預覽介面語言,儲存後永久生效。'
}
export default common
+18
View File
@@ -0,0 +1,18 @@
import common from './common'
import settings from './settings'
import workspace from './workspace'
import terminal from './terminal'
import ssh from './ssh'
import panels from './panels'
import main from './main'
/** 繁體中文詞條。命名空間檔案依區域分工維護,詳見 src/shared/i18n/index.ts 的歸屬表。 */
export default {
...common,
...settings,
...workspace,
...terminal,
...ssh,
...panels,
...main
}
+56
View File
@@ -0,0 +1,56 @@
/** 命名空間:main(主程序文案:系統匣、關閉詢問、更新器)。歸屬:主程序維護者。 */
const main: Record<string, string> = {
'main.tray.showWindow': '顯示主視窗',
'main.tray.closeAction': '關閉按鈕行為',
'main.tray.askEveryTime': '每次詢問',
'main.tray.minimizeToTray': '最小化到系統匣',
'main.tray.exitDirectly': '直接結束',
'main.tray.exit': '結束',
'main.tray.balloonTitle': '已最小化到系統匣',
'main.tray.balloonContent': '終端機連線仍在背景執行,點擊系統匣圖示即可還原視窗。',
'main.tray.closeTitle': '關閉 OpenTerminal',
'main.tray.closeMessage': '要最小化到系統匣,還是直接結束?',
'main.tray.closeDetail': '最小化到系統匣時,終端機連線會繼續執行。',
'main.tray.rememberChoice': '記住我的選擇,不再詢問',
'main.updater.feedFailed': '國內來源: {gitea};GitHub: {github}',
'main.ssh.connectTimeout': '連線逾時 ({host}:{port})',
'main.ssh.saveFingerprintFailed': '儲存主機指紋失敗: {detail}',
'main.ssh.hostKeyRejected': '使用者拒絕了主機指紋',
'main.ssh.connectFailed': '連線失敗 {host}:{port}: {detail}',
'main.ssh.shellOpenFailed': '無法開啟 SSH shell ({host}:{port}): {detail}',
'main.ssh.initFailed': 'SSH 連線初始化失敗 ({host}:{port}): {detail}',
'main.ssh.readKeyFailed': '無法讀取私密金鑰檔案 {path}: {detail}',
'main.sftp.sessionGone': 'SSH 連線不存在或已中斷',
'main.sftp.deleteFailed': '刪除失敗: {detail}',
'main.sftp.invalidMode': '權限值無效: {mode}',
'main.sftp.invalidUidGid': 'uid/gid 無效',
'main.sftp.commandExitCode': '指令結束碼 {code}',
'main.sftp.cancelled': '已取消',
'main.zmodem.transferFailed': '傳輸失敗',
'main.zmodem.transferTimeout': '傳輸逾時',
'main.zmodem.sendFailed': '傳送失敗',
'main.zmodem.uploadFailed': '上傳失敗',
'main.zmodem.receiveFailed': '接收失敗',
'main.zmodem.abnormal': 'ZMODEM 傳輸異常',
'main.zmodem.cancelled': '已取消',
'main.zmodem.offerTimedOut': '未選擇檔案,已取消',
'main.zmodem.sessionInvalid': '連線已失效',
'main.zmodem.sessionCreateFailed': '無法建立 ZMODEM 連線',
'main.zmodem.noSaveDir': '未指定儲存目錄',
'main.zmodem.noFiles': '未選擇檔案',
'main.ipc.connectionMissing': '連線書籤不存在 ({id})',
'main.sysinfo.sessionGone': 'SSH 工作階段不存在或已中斷',
'main.sysinfo.execFailed': 'SSH exec 失敗',
'main.sysinfo.parseFailed': '解析失敗: {message}',
'main.pty.serviceNotReady': 'SSH 工作階段服務尚未初始化',
'main.pty.missingConnectionId': 'SSH 工作階段缺少 connectionId',
'main.log.tuiOmitted': '全螢幕介面(TUI)輸出已省略'
}
export default main
+36
View File
@@ -0,0 +1,36 @@
/** 命名空間:panels(命令面板、工作階段日誌面板、傳輸面板)。歸屬:SSH/面板維護者。 */
const panels: Record<string, string> = {
// 命令面板
'panels.commands.sectionTitle': '命令',
'panels.commands.target': '傳送目標',
'panels.commands.targetSsh': 'SSH 伺服器',
'panels.commands.targetTerminal': '終端機',
'panels.commands.tabHistory': '歷史',
'panels.commands.tabLibrary': '命令庫',
'panels.commands.historyTitle': '歷史命令',
'panels.commands.clearTitle': '清空全部命令歷史?',
'panels.commands.clear': '清空',
'panels.commands.noHistory': '尚無歷史命令',
'panels.commands.loading': '載入中…',
'panels.commands.libraryTitle': '命令庫',
'panels.commands.libraryEmpty': '命令庫為空',
'panels.commands.add': '新增命令',
'panels.commands.name': '名稱',
'panels.commands.optional': '(選填)',
'panels.commands.command': '命令',
'panels.commands.commandPlaceholder': '如 ls -la',
'panels.commands.note': '備註',
'panels.commands.deleteTitle': '刪除該命令?',
'panels.commands.deleteAria': '刪除命令',
// 傳輸面板
'panels.transfer.failed': '傳輸失敗',
'panels.transfer.cancelled': '已取消',
'panels.transfer.done': '傳輸完成',
'panels.transfer.uploading': '上傳中',
'panels.transfer.downloading': '下載中',
'panels.transfer.zmodemUploading': 'ZMODEM 上傳中',
'panels.transfer.zmodemDownloading': 'ZMODEM 下載中'
}
export default panels
+147
View File
@@ -0,0 +1,147 @@
/** 命名空間:settings(設定對話框:字型/游標/渲染/高亮/主題/系統/關於)。歸屬:設定頁維護者。 */
const settings: Record<string, string> = {
'settings.title': '設定',
'settings.tabs.font': '字型',
'settings.tabs.cursor': '游標與捲動',
'settings.tabs.render': '渲染與行為',
'settings.tabs.highlight': '高亮',
'settings.tabs.theme': '主題',
'settings.tabs.system': '系統',
'settings.tabs.about': '關於',
'settings.resizeHandle': '拖曳調整大小',
'settings.preview': '預覽',
'settings.deleteConfirmDesc': '刪除後無法復原,確定要繼續嗎?',
'settings.color.foreground': '前景',
'settings.color.background': '背景',
'settings.color.cursor': '游標',
'settings.color.selection': '選取區',
'settings.font.label': '字型',
'settings.font.desc': '內建預設字型或系統等寬字型',
'settings.font.placeholder': '選擇字型',
'settings.font.default': '預設',
'settings.font.size': '字型大小',
'settings.font.sizeDesc': '終端文字的像素大小',
'settings.font.weight': '字重',
'settings.font.weightDesc': '400 為一般,700 為粗體',
'settings.font.boldWeight': '粗體字重',
'settings.font.boldWeightDesc': '粗體文字所使用的字重',
'settings.font.letterSpacing': '字元間距',
'settings.font.letterSpacingDesc': '字元之間的水平間距',
'settings.font.lineHeight': '行高',
'settings.font.lineHeightDesc': '相鄰兩行之間的垂直距離',
'settings.cursor.blink': '游標閃爍',
'settings.cursor.blinkDesc': '游標是否週期性閃爍',
'settings.cursor.style': '游標樣式',
'settings.cursor.styleDesc': '游標的顯示形狀',
'settings.cursor.inactiveStyle': '非作用中游標樣式',
'settings.cursor.inactiveStyleDesc': '視窗失焦時的游標樣式',
'settings.cursor.scrollback': '捲動緩衝區',
'settings.cursor.scrollbackDesc': '畫面上可往回捲動的行數',
'settings.cursorStyle.bar': '直線 (bar)',
'settings.cursorStyle.block': '方塊 (block)',
'settings.cursorStyle.underline': '底線 (underline)',
'settings.cursorStyle.outline': '外框 (outline)',
'settings.cursorStyle.none': '無 (none)',
'settings.rendererMode.auto': '自動',
'settings.rendererMode.autoHint': '優先使用 WebGL 加速,失敗時自動退回 DOM 渲染',
'settings.rendererMode.webgl': '高效能 WebGL',
'settings.rendererMode.webglHint': '強制使用 GPU 加速渲染,適合高更新率與大量行數捲動',
'settings.rendererMode.dom': '相容 DOM',
'settings.rendererMode.domHint': '純 CPU 渲染,相容性最佳,適合沒有 GPU 或遠端桌面的環境',
'settings.render.modeLabel': '渲染模式',
'settings.render.modeHint': '終端儲存格的渲染加速方式,變更將套用到所有終端',
'settings.render.autoWrap': '自動換行',
'settings.render.autoWrapDesc': '超出寬度時自動折行',
'settings.render.copyOnSelect': '選取即複製',
'settings.render.copyOnSelectDesc': '以滑鼠選取文字時自動複製',
'settings.render.pasteRiskConfirm': '貼上風險確認',
'settings.render.pasteRiskConfirmDesc': '多行文字(或超長單行)貼上前彈出確認;單行直接貼上',
'settings.render.suggest': '輸入建議',
'settings.render.suggestDesc': '輸入時顯示指令建議;Tab 接受,Enter 一律直接執行',
'settings.render.history': '記錄指令歷史',
'settings.render.historyDesc': '關閉後不再記錄新指令;已儲存的歷史仍會保留',
'settings.render.historyLimit': '歷史筆數上限',
'settings.render.historyLimitDesc': '指令歷史最多保留幾筆,重複的指令只記一次',
'settings.render.recButton': '終端工具列 · 錄製',
'settings.render.recButtonDesc': '右上角顯示「記錄工作階段日誌」按鈕',
'settings.render.openLogsButton': '終端工具列 · 開啟日誌目錄',
'settings.render.openLogsButtonDesc': '右上角顯示「開啟日誌目錄」按鈕',
'settings.render.openCwdButton': '終端工具列 · 開啟工作區目錄',
'settings.render.openCwdButtonDesc':
'右上角顯示「開啟目前目錄」按鈕(SSH 工作階段不顯示;目錄會隨 cd 即時追蹤,需開啟 shell 整合或使用 cd 指令)',
'settings.system.launchAtLogin': '開機時自動啟動',
'settings.system.launchAtLoginDesc': '開機時自動啟動程式(開發模式下註冊的是開發版程式)',
'settings.system.preventSleep': '防止系統休眠',
'settings.system.preventSleepDesc':
'開啟後 OpenTerminal 會防止系統自動休眠;關閉則允許系統依本身的設定休眠',
'settings.system.restoreSession': '啟動時還原上次工作階段',
'settings.system.restoreSessionDesc':
'下次啟動時還原分割版面,並讓每個終端回到上次所在的目錄;關閉則每次都以單一終端啟動',
'settings.system.shellIntegration': 'Shell 整合',
'settings.system.shellIntegrationDesc':
'讓 shell 主動回報工作目錄(OSC 7),路徑記憶更精確(含指令碼內的 cd);會包裝你的命令提示字元,提示字元主題顯示異常時關閉即可',
'settings.system.closeAction': '關閉按鈕行為',
'settings.system.closeActionDesc':
'點擊視窗關閉按鈕時的動作;最小化至系統匣後,可從系統匣圖示的右鍵選單結束',
'settings.system.closeActionTray': '最小化至系統匣',
'settings.system.closeActionExit': '直接結束',
'settings.system.closeActionAsk': '每次詢問',
'settings.system.globalShortcut': '全域喚出快速鍵',
'settings.system.globalShortcutDesc': '點擊輸入框後直接按下組合鍵;Esc 取消,Backspace 清除並停用',
'settings.system.globalShortcutHint':
'搭配全域鍵可在任何畫面喚出/隱藏視窗;若註冊失敗(與其他軟體衝突)則不會生效,應用程式也不會報錯。',
'settings.system.shortcutRecording': '請按下組合鍵…',
'settings.system.shortcutPlaceholder': '點擊後按下快速鍵,留空為停用',
'settings.highlight.alert':
'自訂高亮可強化顯示效果,但會略微增加效能負擔。規則依優先順序套用。PS:高亮是在寫入終端時注入顏色,對既有的回捲內容不生效',
'settings.highlight.enabled': '啟用',
'settings.highlight.pattern': '正規表示式',
'settings.highlight.patternPlaceholder': '例如 \\b(ERROR|FAILED)\\b',
'settings.highlight.invalidRegex': '正規表示式無效',
'settings.highlight.priority': '優先順序',
'settings.highlight.priorityHint': '值越小越先套用',
'settings.highlight.color': '顏色',
'settings.highlight.clearBg': '清除',
'settings.highlight.addBg': '新增',
'settings.highlight.palette': '色盤',
'settings.highlight.note': '備註',
'settings.highlight.notePlaceholder': '規則說明(選填)',
'settings.highlight.actions': '操作',
'settings.highlight.addRule': '+ 新增規則',
'settings.highlight.empty': '尚無高亮規則,點擊「+ 新增規則」建立',
'settings.highlight.deleteTitle': '刪除高亮規則',
'settings.highlight.resetTitle': '還原預設高亮規則',
'settings.highlight.resetDesc': '會將目前所有規則取代為內建預設,無法復原。',
'settings.highlight.resetOk': '還原',
'settings.highlight.createTitle': '新增高亮規則',
'settings.highlight.editTitle': '編輯高亮規則',
'settings.theme.accent': '標籤強調色',
'settings.theme.accentDesc': '作用中標籤的邊框、側邊欄指示條與 SSH 徽章的強調顏色',
'settings.theme.customBadge': '自訂',
'settings.theme.deleteTitle': '刪除自訂主題',
'settings.theme.create': '新增主題',
'settings.theme.editTitle': '編輯主題',
'settings.themeEditor.name': '名稱',
'settings.themeEditor.namePlaceholder': '主題名稱',
'settings.themeEditor.copySuffix': '(副本)',
'settings.about.currentVersion': '目前版本',
'settings.about.statusIdle': '點擊檢查更新',
'settings.about.statusChecking': '正在檢查更新…',
'settings.about.statusAvailable': '發現新版本',
'settings.about.statusLatest': '目前已是最新版本',
'settings.about.statusDownloading': '正在下載…',
'settings.about.statusDownloaded': '下載完成,可重新啟動安裝',
'settings.about.statusError': '檢查失敗',
'settings.about.statusDev': '開發模式不支援檢查更新',
'settings.about.channelStable': '穩定更新通道',
'settings.about.autoCheck': '啟動時自動檢查',
'settings.about.download': '下載更新',
'settings.about.downloadGithub': '(GitHub 來源)',
'settings.about.install': '重新啟動安裝',
'settings.about.check': '檢查更新',
'settings.about.checkingButton': '檢查中',
'settings.about.changelog': '更新日誌',
'settings.about.changelogEmpty': '暫無更新日誌'
}
export default settings
+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
+26
View File
@@ -0,0 +1,26 @@
/** 命名空間:terminal(終端機檢視:右鍵選單、搜尋、貼上確認、工具列、提示)。歸屬:工作區/終端機維護者。 */
const terminal: Record<string, string> = {
'terminal.menu.find': '尋找',
'terminal.menu.selectAll': '全選',
'terminal.menu.clear': '清除畫面',
'terminal.search.placeholder': '搜尋',
'terminal.search.prev': '上一個',
'terminal.search.next': '下一個',
'terminal.search.found': '已找到',
'terminal.search.notFound': '未找到',
'terminal.suggest.hint': '↑/↓ 選擇 · Tab 接受 · Esc 關閉',
'terminal.rec.start': '開始錄製',
'terminal.rec.stop': '停止錄製',
'terminal.rec.startLog': '開始錄製工作階段日誌',
'terminal.rec.stopLog': '停止錄製工作階段日誌',
'terminal.rec.openLogs': '開啟日誌目錄',
'terminal.rec.openCwd': '開啟工作區目錄',
'terminal.paste.title': '確認貼上',
'terminal.paste.message': '偵測到多行或潛在危險命令,確定要貼到終端機嗎?',
'terminal.paste.noPrompt': '本次工作階段不再提示',
'terminal.paste.disableDetection': '關閉後續貼上偵測',
'terminal.paste.hint': '可在一般終端機設定中重新開啟或切換偵測策略。',
'terminal.dead.message': '處理程序已結束 (代碼 {code})'
}
export default terminal
+60
View File
@@ -0,0 +1,60 @@
/** 命名空間:workspace(工作區外殼:側邊欄、分頁、版面配置選單、分割、空狀態)。歸屬:工作區維護者。 */
const workspace: Record<string, string> = {
'workspace.tab.terminalTitle': '終端機 {n}',
'workspace.tab.localTerminal': '本機終端機',
'workspace.tab.closeOthers': '關閉其他',
'workspace.tab.closeRight': '關閉右側',
'workspace.tab.broadcastTarget': '廣播目標',
'workspace.tab.broadcastBadge': '播',
'workspace.tab.addInSplit': '在此分割中新增終端機',
'workspace.newTerminal': '新增終端機',
'workspace.empty.terminalTitle': '尚無終端機',
'workspace.empty.sshTitle': '尚無 SSH 工作階段',
'workspace.empty.sshHint': '請從左側伺服器清單連線',
'workspace.rail.hideSidebar': '收合側邊欄',
'workspace.rail.showSidebar': '展開側邊欄',
'workspace.rail.layout': '版面配置',
'workspace.rail.settings': '設定',
'workspace.rail.connecting': '連線中…',
'workspace.rail.terminalWorkspace': '終端機工作區',
'workspace.rail.sshWorkspace': 'SSH 工作區',
'workspace.panel.hideSidebar': '收合側邊欄',
'workspace.panel.showSidebar': '展開側邊欄',
'workspace.layout.splitRight': '水平分割',
'workspace.layout.splitBelow': '垂直分割',
'workspace.layout.saveTemplate': '儲存為範本',
'workspace.layout.applyTemplate': '套用範本',
'workspace.template.saveTitle': '儲存版面配置範本',
'workspace.template.namePlaceholder': '範本名稱',
'workspace.template.applyTitle': '套用版面配置範本',
'workspace.template.empty': '尚無已儲存的範本',
'workspace.template.apply': '套用',
'workspace.template.deleteConfirm': '刪除這個範本?',
'workspace.broadcast.toggle': '廣播輸入',
'workspace.broadcast.activeTitle': '廣播中({count} 個目標)',
'workspace.broadcast.popoverTerminal': '廣播輸入(終端機)',
'workspace.broadcast.popoverSsh': '廣播輸入(SSH)',
'workspace.broadcast.switch': '廣播開關',
'workspace.broadcast.enabled': '已啟用({count})',
'workspace.broadcast.needTwo': '需至少選擇 2 個目標',
'workspace.broadcast.disabled': '未啟用',
'workspace.broadcast.emptySsh': '尚無 SSH 伺服器工作階段',
'workspace.broadcast.emptyTerminal': '尚無終端機',
'workspace.broadcast.hint': '選擇 ≥2 個終端機後會自動開啟廣播;關閉任一個使目標少於 2 個時會自動關閉。僅目前模式群組的工作階段可被勾選。',
'workspace.hint.sshFromList': 'SSH 工作階段請從伺服器清單連線',
'workspace.hint.connectSshFirst': '請先連線 SSH 伺服器',
'workspace.hint.noActiveTerminal': '沒有作用中的終端機:請至少開啟一個本機終端機或 SSH 工作階段',
'workspace.hint.noSessionInPanel': '目前作用中的面板沒有可用的工作階段',
'workspace.connect.failed': 'SSH 連線失敗',
'workspace.connect.passwordTitle': '輸入連線密碼',
'workspace.connect.passwordPlaceholder': '密碼',
'workspace.connect.passphraseTitle': '輸入私密金鑰密語',
'workspace.connect.passphrasePlaceholder': '私密金鑰密語',
'workspace.connect.connecting': '連線中…',
'workspace.connect.connectingNamed': '正在連線 {name}',
'workspace.connect.action': '連線',
'workspace.error.title': '介面發生異常',
'workspace.error.reload': '重新載入'
}
export default workspace
+83
View File
@@ -0,0 +1,83 @@
/**
* Tiny dependency-free i18n core, shared by the renderer and the main process.
*
* Dictionaries are flat `key -> text` maps split by namespace, one file per
* language per namespace (`dicts/<lang>/<namespace>.ts`). Ownership map — each
* namespace is translated by whoever owns that area, so parallel work never
* edits the same file:
*
* common — i18n plumbing: language names, generic buttons/status
* settings — the settings dialog (font/cursor/render/highlight/theme/system/about)
* workspace — workspace shell: sidebar, tabs, layout menu, split, empty state
* terminal — terminal view internals: context menu, search, paste confirm, toolbar
* ssh — ssh connections, host key prompt, file panel, zmodem, monitor
* panels — command panel, session-log panel, transfer panel
* main — main-process strings: tray, close prompt, updater
*
* Missing keys fall back to zh-CN, then to the key itself (so a missing
* translation is visible, never blank).
*/
import zhCN from './dicts/zh-CN'
import zhTW from './dicts/zh-TW'
import en from './dicts/en'
import ja from './dicts/ja'
export type Language = 'zh-CN' | 'zh-TW' | 'en' | 'ja'
export interface LanguageOption {
value: Language
/** Language names are shown in their own script, so this is not translated. */
label: string
}
export const LANGUAGES: LanguageOption[] = [
{ value: 'zh-CN', label: '简体中文' },
{ value: 'zh-TW', label: '繁體中文' },
{ value: 'en', label: 'English' },
{ value: 'ja', label: '日本語' }
]
export const DEFAULT_LANGUAGE: Language = 'zh-CN'
export function isLanguage(value: unknown): value is Language {
return typeof value === 'string' && LANGUAGES.some((l) => l.value === value)
}
export type Dict = Record<string, string>
const DICTS: Record<Language, Dict> = {
'zh-CN': zhCN,
'zh-TW': zhTW,
en,
ja
}
let current: Language = DEFAULT_LANGUAGE
const listeners = new Set<(lang: Language) => void>()
/** Switch the active language and notify subscribers (renderer re-render,
* main-process tray rebuild). Both processes call this on settings load/save. */
export function setLanguage(lang: Language): void {
if (current === lang) return
current = lang
for (const listener of listeners) listener(lang)
}
export function getLanguage(): Language {
return current
}
export function onLanguageChange(cb: (lang: Language) => void): () => void {
listeners.add(cb)
return () => listeners.delete(cb)
}
/** Translate `key`; `{name}` placeholders are filled from `vars`. */
export function t(key: string, vars?: Record<string, string | number>): string {
const raw = DICTS[current][key] ?? DICTS[DEFAULT_LANGUAGE][key] ?? key
if (!vars) return raw
return raw.replace(/\{(\w+)\}/g, (match, name: string) =>
vars[name] === undefined ? match : String(vars[name])
)
}
+4 -1
View File
@@ -1,4 +1,5 @@
import type { TerminalTheme } from './theme'
import type { Language } from './i18n'
/** One terminal keyword-highlight rule (regex → ANSI color injection). */
export interface HighlightRule {
@@ -72,6 +73,8 @@ export interface SystemSettings {
* to parsing typed `cd` commands.
*/
shellIntegration?: boolean
/** interface language (see @shared/i18n); missing = 简体中文 */
language?: Language
}
export interface AppSettings {
@@ -133,5 +136,5 @@ export const DEFAULT_SETTINGS: AppSettings = {
},
customThemes: [],
highlightRules: DEFAULT_HIGHLIGHT_RULES,
system: { launchAtLogin: false, preventSleep: false, globalShowHide: '', closeAction: 'tray', autoCheckUpdate: true, restoreSession: true, shellIntegration: false }
system: { launchAtLogin: false, preventSleep: false, globalShowHide: '', closeAction: 'tray', autoCheckUpdate: true, restoreSession: true, shellIntegration: false, language: 'zh-CN' }
}