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