Files
Netcatty/application/i18n/locales/en.ts
陈大猫 24df4b6548 fix: support CSV password import and save password in keyboard-interactive auth (#629)
* fix: support CSV password import and save password in keyboard-interactive auth (#627)

- Add Password column support to CSV import/export/template
- Add isAPasswordPrompt detection (prompt contains "password" + echo=false)
- Auto-fill saved password in keyboard-interactive modal
- Add "Save password" checkbox for password prompts in keyboard-interactive modal
- Wire save callback through sessionId → host to persist password

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix: address review feedback for keyboard-interactive and CSV changes

- Merge password field in dedupeHosts to avoid losing passwords from duplicate CSV rows
- Extract isAPasswordPrompt to module-level pure function
- Only render save-password checkbox at the first password prompt index
- Clean up orphaned i18n keys (useSaved, useSavedPassword, fill, fillSaved)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix: preserve whitespace in CSV imported passwords

Passwords may intentionally contain leading/trailing whitespace.
Removing .trim() ensures lossless CSV round-trip and correct auth.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix: exclude OTP prompts from password detection and guard jump host save

- Add negative patterns (one-time, otp, verification, token, code) to
  isAPasswordPrompt to avoid auto-filling SSH password into OTP fields
- Only save password when request hostname matches session hostname,
  preventing jump host passwords from overwriting the destination host

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix: skip formula injection guard for password column in CSV export

Password values starting with =, +, -, @ were getting a ' prefix from
the CSV formula injection protection, breaking round-trip fidelity.
Now password column is escaped for CSV syntax only, preserving the
credential verbatim.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix: only skip formula guard for data rows, not header row

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-05 14:39:39 +08:00

1836 lines
97 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
export type Messages = Record<string, string>;
const en: Messages = {
// Common
'common.save': 'Save',
'common.cancel': 'Cancel',
'common.close': 'Close',
'common.reset': 'Reset',
'common.zoomIn': 'Zoom in',
'common.zoomOut': 'Zoom out',
'common.settings': 'Settings',
'common.search': 'Search',
'common.searchPlaceholder': 'Search...',
'common.connect': 'Connect',
'common.terminal': 'Terminal',
'common.create': 'Create',
'common.import': 'Import',
'common.generate': 'Generate',
'common.delete': 'Delete',
'common.edit': 'Edit',
'common.clear': 'Clear',
'common.optional': 'Optional',
'common.selectPlaceholder': 'Select...',
'common.add': 'Add',
'common.rename': 'Rename',
'common.refresh': 'Refresh',
'common.continue': 'Continue',
'common.enabled': 'Enabled',
'common.disabled': 'Disabled',
'common.error': 'Error',
'common.validation': 'Validation',
'common.unknownError': 'Unknown error',
'common.noResultsFound': 'No results found',
'common.back': 'Back',
'common.apply': 'Apply',
'common.use': 'Use',
'common.useGlobal': 'Use global',
'common.saveChanges': 'Save Changes',
'common.advanced': 'Advanced',
'common.left': 'Left',
'common.right': 'Right',
'common.more': 'More',
'common.selectAHost': 'Select a host',
'common.selectAHostPlaceholder': 'Select a host...',
'sort.az': 'A-z',
'sort.za': 'Z-a',
'sort.newest': 'Newest to oldest',
'sort.oldest': 'Oldest to newest',
'sort.group': 'By group',
'field.label': 'Label',
'field.type': 'Type',
'auth.keyType': 'Type {type}',
'auth.showAllKeys': 'Show all keys',
// Dialogs / prompts
'confirm.deleteHost': 'Delete Host "{name}"?',
'confirm.deleteIdentity': 'Delete Identity "{name}"?',
'confirm.removeProvider': 'Remove provider "{name}"?',
'dialog.createWorkspace.title': 'Create Workspace',
'dialog.renameWorkspace.title': 'Rename workspace',
'dialog.renameSession.title': 'Rename session',
'field.name': 'Name',
'field.selectHosts': 'Select Hosts',
'placeholder.workspaceName': 'Workspace name',
'placeholder.sessionName': 'Session name',
'placeholder.searchHosts': 'Search hosts...',
'toast.settingsUnavailable': 'Settings window is unavailable on this platform.',
'credentials.protectionUnavailable.title': 'Credential Protection Unavailable',
'credentials.protectionUnavailable.message': 'Saved passwords and keys cannot be auto-decrypted on this device. Re-enter credentials before connecting.',
'credentials.protectionUnavailable.action': 'Open Settings',
// Settings shell
'settings.title': 'Settings',
'settings.tab.application': 'Application',
'settings.tab.appearance': 'Appearance',
'settings.tab.terminal': 'Terminal',
'settings.tab.shortcuts': 'Shortcuts',
'settings.tab.syncCloud': 'Sync & Cloud',
'settings.tab.system': 'System',
// Settings > System
'settings.system.title': 'System',
'settings.system.description': 'System information and temporary file management.',
'settings.system.tempDirectory': 'Temporary Files',
'settings.system.location': 'Location',
'settings.system.fileCount': 'Files',
'settings.system.totalSize': 'Size',
'settings.system.openFolder': 'Open folder',
'settings.system.refresh': 'Refresh',
'settings.system.clearTempFiles': 'Clear temp files',
'settings.system.clearing': 'Clearing...',
'settings.system.clearResult': 'Deleted {deleted} file(s), {failed} failed.',
'settings.system.tempDirectoryHint': 'Temporary files are created when opening remote files with external applications. They are automatically cleaned up when SFTP sessions close.',
'settings.system.credentials.title': 'Credential Protection',
'settings.system.credentials.status': 'Status',
'settings.system.credentials.checking': 'Checking...',
'settings.system.credentials.available': 'Available (OS keychain ready)',
'settings.system.credentials.unavailable': 'Unavailable (cannot decrypt saved credentials)',
'settings.system.credentials.unknown': 'Unknown (not supported in this environment)',
'settings.system.credentials.unavailableHint': 'Credentials encrypted on another user profile or machine cannot be decrypted here. Re-enter and save credentials on this device.',
'settings.system.credentials.portabilityHint': 'Cloud Sync is portable because it uses your master key encryption. Local safeStorage encryption is device/user scoped.',
// Settings > System > Crash Logs
'settings.system.crashLogs.title': 'Crash Logs',
'settings.system.crashLogs.description': 'View error logs from the main process to help diagnose unexpected behavior.',
'settings.system.crashLogs.noLogs': 'No crash logs found.',
'settings.system.crashLogs.entries': '{count} entries',
'settings.system.crashLogs.clear': 'Clear all logs',
'settings.system.crashLogs.cleared': 'Cleared {count} log file(s).',
'settings.system.crashLogs.source': 'Source',
'settings.system.crashLogs.time': 'Time',
'settings.system.crashLogs.message': 'Message',
'settings.system.crashLogs.stack': 'Stack Trace',
'settings.system.crashLogs.hint': 'Crash logs are retained for 30 days and automatically rotated.',
'settings.system.crashLogs.collapse': 'Collapse',
'settings.system.crashLogs.expand': 'Show details',
// Settings > System > Software Update
'settings.update.title': 'Software Update',
'settings.update.currentVersion': 'Current version',
'settings.update.checkForUpdates': 'Check for Updates',
'settings.update.checking': 'Checking...',
'settings.update.upToDate': 'You are using the latest version.',
'settings.update.available': 'New version {version} is available.',
'settings.update.download': 'Download Update',
'settings.update.downloading': 'Downloading... {percent}%',
'settings.update.readyToInstall': 'Update downloaded and ready to install.',
'settings.update.restartNow': 'Restart to Update',
'settings.update.error': 'Failed to check for updates.',
'settings.update.downloadError': 'Download failed.',
'settings.update.manualDownload': 'Download from GitHub',
'settings.update.manualDownloadHint': 'Auto-update is not available on this platform. Download the latest version from GitHub.',
'settings.update.hint': 'Netcatty checks for updates from GitHub Releases.',
'settings.update.lastCheckedJustNow': 'just now',
'settings.update.lastCheckedMinutesAgo': '{n} min ago',
'settings.update.lastCheckedHoursAgo': '{n} hr ago',
'settings.update.lastCheckedPrefix': 'Last checked: ',
'settings.update.autoUpdateEnabled': 'Automatic Updates',
'settings.update.autoUpdateEnabledDesc': 'Automatically check and download updates when available.',
// Settings > Session Logs
'settings.sessionLogs.title': 'Session Logs',
'settings.sessionLogs.description': 'Configure session log export and auto-save settings.',
'settings.sessionLogs.autoSave': 'Auto-Save',
'settings.sessionLogs.enableAutoSave': 'Enable auto-save',
'settings.sessionLogs.enableAutoSaveDesc': 'Automatically save session logs when terminal sessions end.',
'settings.sessionLogs.directory': 'Save Directory',
'settings.sessionLogs.noDirectory': 'No directory selected',
'settings.sessionLogs.browse': 'Browse',
'settings.sessionLogs.openFolder': 'Open folder',
'settings.sessionLogs.directoryHint': 'Logs will be organized by host in subdirectories.',
'settings.sessionLogs.format': 'Log Format',
'settings.sessionLogs.formatDesc': 'Choose the format for saved log files.',
'settings.sessionLogs.formatTxt': 'Plain Text (.txt)',
'settings.sessionLogs.formatRaw': 'Raw with ANSI (.log)',
'settings.sessionLogs.formatHtml': 'HTML (.html)',
'settings.sessionLogs.hint': 'Session logs capture all terminal output for troubleshooting and auditing purposes.',
// Settings > Global Hotkey (Quake Mode)
'settings.globalHotkey.title': 'Global Hotkey',
'settings.globalHotkey.toggleWindow': 'Toggle Window',
'settings.globalHotkey.toggleWindowDesc': 'Press a key combination to set a global shortcut for showing/hiding the window.',
'settings.globalHotkey.notSet': 'Not set',
'settings.globalHotkey.reset': 'Reset to default',
'settings.globalHotkey.closeToTray': 'Close to System Tray',
'settings.globalHotkey.closeToTrayDesc': 'When enabled, closing the window will minimize to the system tray instead of quitting.',
'settings.globalHotkey.enabled': 'Enable Global Hotkey',
'settings.globalHotkey.enabledDesc': 'Register system-wide keyboard shortcuts. When disabled, all global hotkeys are unregistered.',
'settings.globalHotkey.hint': 'Global hotkey works system-wide to quickly show or hide the window (Quake-style terminal).',
// Tray Panel
'tray.openMainWindow': 'Open Main Window',
'tray.sessions': 'Sessions',
'tray.portForwarding': 'Port Forwarding',
'tray.status.connected': 'Connected',
'tray.status.connecting': 'Connecting',
'tray.status.disconnected': 'Disconnected',
'tray.status.active': 'Active',
'tray.status.inactive': 'Inactive',
'tray.status.error': 'Error',
'tray.recentHosts': 'Recent Hosts',
'tray.empty.title': 'Nothing here yet',
'tray.empty.subtitle': 'Go connect to a server, they miss you 🚀',
'tray.quit': 'Quit Netcatty',
// Vault Sidebar
'vault.sidebar.collapse': 'Collapse sidebar',
'vault.sidebar.expand': 'Expand sidebar',
// Settings > Application
'settings.application.checkUpdates': 'Check for updates',
'settings.application.reportProblem': 'Report a problem',
'settings.application.reportProblem.subtitle': 'Generate a pre-filled GitHub issue',
'settings.application.community': 'Community',
'settings.application.community.subtitle': 'On GitHub Discussions',
'settings.application.github': 'GitHub',
'settings.application.github.subtitle': 'Source code',
'settings.application.whatsNew': "What's new",
'settings.application.whatsNew.subtitle': 'Show release notes',
'settings.vault.title': 'Vault',
'settings.vault.showRecentHosts': 'Show recently connected hosts',
'settings.vault.showRecentHostsDesc': 'Display a section of recently connected hosts at the top of the vault',
// Update notifications
'update.available.title': 'Update Available',
'update.available.message': 'A new version {version} is available. Click to download.',
'update.checking': 'Checking for updates...',
'update.upToDate.title': 'Up to Date',
'update.upToDate.message': 'You are running the latest version ({version}).',
'update.error': 'Failed to check for updates',
'update.downloadNow': 'Download Now',
'update.viewInSettings': 'View in Settings',
'update.readyToInstall.title': 'Update Ready',
'update.readyToInstall.message': 'Version {version} downloaded and ready to install.',
'update.restartNow': 'Restart Now',
'update.downloadFailed.title': 'Update Failed',
'update.downloadFailed.message': 'Failed to download update. You can download it manually.',
'update.openReleases': 'Open Releases',
'update.remindLater': 'Remind Later',
'update.skipVersion': 'Skip This Version',
// Settings > Appearance
'settings.appearance.uiTheme': 'UI Theme',
'settings.appearance.theme': 'Theme',
'settings.appearance.theme.desc': 'Choose light, dark, or follow system preference',
'settings.appearance.theme.light': 'Light',
'settings.appearance.theme.dark': 'Dark',
'settings.appearance.theme.system': 'System',
'settings.appearance.accentColor': 'Accent Color',
'settings.appearance.customColor': 'Custom color',
'settings.appearance.accentColor.mode': 'Use custom accent',
'settings.appearance.accentColor.mode.desc': 'Override the theme accent color',
'settings.appearance.accentColor.custom': 'Custom accent',
'settings.appearance.themeColor': 'Theme Color',
'settings.appearance.themeColor.desc': 'Pick a preset palette for each theme',
'settings.appearance.themeColor.light': 'Light palette',
'settings.appearance.themeColor.dark': 'Dark palette',
'settings.appearance.customCss': 'Custom CSS',
'settings.appearance.customCss.desc':
'Add custom CSS to personalize the app appearance. Changes apply immediately.',
'settings.appearance.customCss.placeholder':
'/* Example: */\n.terminal { background: #1a1a2e !important; }\n:root { --radius: 0.25rem; }',
'settings.appearance.language': 'Language',
'settings.appearance.language.desc': 'Choose the UI language',
'settings.appearance.uiFont': 'Interface Font',
'settings.appearance.uiFont.desc': 'Choose the font for the application interface',
// Settings > Terminal
'settings.terminal.section.theme': 'Terminal Theme',
'settings.terminal.themeModal.title': 'Select Theme',
'settings.terminal.themeModal.darkThemes': 'Dark Themes',
'settings.terminal.themeModal.lightThemes': 'Light Themes',
'settings.terminal.theme.selectButton': 'Select Theme',
'settings.terminal.section.font': 'Font',
'settings.terminal.section.cursor': 'Cursor',
'settings.terminal.section.keyboard': 'Keyboard',
'settings.terminal.section.accessibility': 'Accessibility',
'settings.terminal.section.behavior': 'Behavior',
'settings.terminal.section.scrollback': 'Scrollback',
'settings.terminal.section.keywordHighlight': 'Keyword highlighting',
'settings.terminal.font.family': 'Font',
'settings.terminal.font.family.desc': 'Terminal font family',
'settings.terminal.font.size': 'Font size',
'settings.terminal.font.size.desc': 'Terminal text size',
'settings.terminal.font.weight': 'Font weight',
'settings.terminal.font.weight.desc': 'Weight for regular text (100-900)',
'settings.terminal.font.weightBold': 'Bold font weight',
'settings.terminal.font.weightBold.desc': 'Weight for bold text (100-900)',
'settings.terminal.font.linePadding': 'Line padding',
'settings.terminal.font.linePadding.desc': 'Additional space between lines (0-10)',
'settings.terminal.font.emulationType': 'Terminal emulation type',
'settings.terminal.cursor.style': 'Cursor style',
'settings.terminal.cursor.style.block': 'Block',
'settings.terminal.cursor.style.bar': 'Bar',
'settings.terminal.cursor.style.underline': 'Underline',
'settings.terminal.cursor.blink': 'Cursor blink',
'settings.terminal.keyboard.altAsMeta': 'Use Option as Meta key',
'settings.terminal.keyboard.altAsMeta.desc':
'Use Option (Alt) as the Meta key instead of for special characters',
'settings.terminal.accessibility.minimumContrastRatio': 'Minimum contrast ratio',
'settings.terminal.accessibility.minimumContrastRatio.desc':
'Adjust colors to meet contrast requirements (1 = disabled, 21 = max)',
'settings.terminal.behavior.rightClick': 'Right-click behavior',
'settings.terminal.behavior.rightClick.desc': 'Action when right-clicking in terminal',
'settings.terminal.behavior.rightClick.menu': 'Show menu',
'settings.terminal.behavior.rightClick.paste': 'Paste',
'settings.terminal.behavior.rightClick.selectWord': 'Select word',
'settings.terminal.behavior.copyOnSelect': 'Copy on select',
'settings.terminal.behavior.copyOnSelect.desc': 'Automatically copy selected text. In tmux/vim with mouse mode, hold Option on macOS or Shift on Windows/Linux to select',
'settings.terminal.behavior.middleClickPaste': 'Middle-click paste',
'settings.terminal.behavior.middleClickPaste.desc':
'Paste clipboard content on middle-click',
'settings.terminal.behavior.bracketedPaste': 'Bracketed paste mode',
'settings.terminal.behavior.bracketedPaste.desc':
'Wrap pasted text with escape sequences so the shell can distinguish paste from typed input. Disable if you see ^[[200~ artifacts.',
'settings.terminal.behavior.osc52Clipboard': 'OSC-52 clipboard',
'settings.terminal.behavior.osc52Clipboard.desc':
'Allow remote programs (tmux, vim, etc.) to access the local clipboard via OSC-52 escape sequences.',
'settings.terminal.behavior.osc52Clipboard.off': 'Disabled',
'settings.terminal.behavior.osc52Clipboard.writeOnly': 'Write only',
'settings.terminal.behavior.osc52Clipboard.readWrite': 'Read & Write',
'settings.terminal.behavior.osc52Clipboard.prompt': 'Write + Prompt on Read',
'terminal.osc52.readPrompt.title': 'Clipboard Read Request',
'terminal.osc52.readPrompt.desc': 'A remote program is requesting to read your clipboard. Allow?',
'terminal.osc52.readPrompt.allow': 'Allow',
'terminal.osc52.readPrompt.deny': 'Deny',
'settings.terminal.behavior.scrollOnInput': 'Scroll on input',
'settings.terminal.behavior.scrollOnInput.desc': 'Scroll terminal to bottom when typing',
'settings.terminal.behavior.scrollOnOutput': 'Scroll on output',
'settings.terminal.behavior.scrollOnOutput.desc':
'Scroll terminal to bottom when new output arrives',
'settings.terminal.behavior.scrollOnKeyPress': 'Scroll on key press',
'settings.terminal.behavior.scrollOnKeyPress.desc':
'Scroll terminal to bottom when pressing a key (e.g., Enter)',
'settings.terminal.behavior.scrollOnPaste': 'Scroll on paste',
'settings.terminal.behavior.scrollOnPaste.desc':
'Scroll terminal to bottom when pasting text',
'settings.terminal.behavior.smoothScrolling': 'Smooth scrolling',
'settings.terminal.behavior.smoothScrolling.desc':
'Animate terminal viewport scrolling instead of jumping instantly',
'settings.terminal.behavior.linkModifier': 'Link modifier key',
'settings.terminal.behavior.linkModifier.desc': 'Hold this key to click on links in terminal',
'settings.terminal.behavior.linkModifier.none': 'None (click directly)',
'settings.terminal.behavior.linkModifier.ctrl': 'Ctrl',
'settings.terminal.behavior.linkModifier.alt': 'Alt / Option',
'settings.terminal.behavior.linkModifier.meta': 'Cmd / Win',
'settings.terminal.scrollback.desc': 'Limit number of terminal rows. Set to 0 for no limit.',
'settings.terminal.scrollback.rows': 'Number of rows *',
'settings.terminal.keywordHighlight.title': 'Keyword highlighting',
'settings.terminal.keywordHighlight.resetColors': 'Reset to default colors',
'settings.terminal.keywordHighlight.addCustom': 'Add Custom Rule',
'settings.terminal.keywordHighlight.editCustom': 'Edit Rule',
'settings.terminal.keywordHighlight.labelField': 'Label & Color',
'settings.terminal.keywordHighlight.labelPlaceholder': 'Label (e.g., Down)',
'settings.terminal.keywordHighlight.patternField': 'Regex Pattern',
'settings.terminal.keywordHighlight.patternPlaceholder': 'Regex (e.g., \\bdown\\b)',
'settings.terminal.keywordHighlight.invalidPattern': 'Invalid regex pattern',
'settings.terminal.keywordHighlight.preview': 'Preview',
'settings.terminal.section.localShell': 'Local Shell',
'settings.terminal.localShell.shell': 'Shell executable',
'settings.terminal.localShell.shell.desc': 'Path to the shell executable (e.g., /bin/zsh, pwsh.exe). Leave empty for system default.',
'settings.terminal.localShell.shell.placeholder': 'System default',
'settings.terminal.localShell.shell.detected': 'Detected',
'settings.terminal.localShell.shell.notFound': 'Shell executable not found',
'settings.terminal.localShell.shell.isDirectory': 'Path is a directory, not an executable',
'settings.terminal.localShell.shell.default': 'System Default',
'settings.terminal.localShell.shell.custom': 'Custom...',
'settings.terminal.localShell.shell.customPath': 'Shell executable path',
'settings.terminal.localShell.shell.commonPaths': 'Common paths',
'settings.terminal.localShell.shell.pathValid': 'Path valid',
'settings.terminal.localShell.startDir': 'Starting directory',
'settings.terminal.localShell.startDir.desc': 'Directory to start in when opening a local terminal. Leave empty for home directory.',
'settings.terminal.localShell.startDir.placeholder': 'Home directory',
'settings.terminal.localShell.startDir.notFound': 'Directory not found',
'settings.terminal.localShell.startDir.isFile': 'Path is a file, not a directory',
'settings.terminal.section.connection': 'Connection',
'settings.terminal.connection.keepaliveInterval': 'Keepalive Interval',
'settings.terminal.connection.keepaliveInterval.desc': 'How often (in seconds) to send SSH-level keepalive packets to server. Set to 0 to disable.',
'settings.terminal.section.serverStats': 'Server Stats (Linux)',
'settings.terminal.serverStats.show': 'Show Server Stats',
'settings.terminal.serverStats.show.desc': 'Display CPU, memory, and disk usage in the terminal statusbar (Linux servers only).',
'settings.terminal.serverStats.refreshInterval': 'Refresh Interval',
'settings.terminal.serverStats.refreshInterval.desc': 'How often to refresh server stats.',
'settings.terminal.serverStats.seconds': 'seconds',
// Settings > Terminal > Rendering
'settings.terminal.section.rendering': 'Rendering',
'settings.terminal.rendering.renderer': 'Renderer',
'settings.terminal.rendering.renderer.desc': 'Choose the terminal rendering technology. Auto will use DOM on low-memory devices. Changes take effect on new terminal sessions.',
'settings.terminal.rendering.auto': 'Auto',
// Settings > Terminal > Workspace Focus Indicator
'settings.terminal.section.workspaceFocus': 'Workspace Focus Indicator',
'settings.terminal.workspaceFocus.style': 'Focus indicator style',
'settings.terminal.workspaceFocus.style.desc': 'How to indicate which pane is focused in split view.',
'settings.terminal.workspaceFocus.dim': 'Dim unfocused panes',
'settings.terminal.workspaceFocus.border': 'Border on focused pane',
// Settings > Terminal > Autocomplete
'settings.terminal.section.autocomplete': 'Autocomplete',
'settings.terminal.autocomplete.enabled': 'Enable autocomplete',
'settings.terminal.autocomplete.enabled.desc': 'Show command suggestions based on history and command specs as you type.',
'settings.terminal.autocomplete.ghostText': 'Ghost text',
'settings.terminal.autocomplete.ghostText.desc': 'Show inline gray suggestion text after the cursor (like fish shell).',
'settings.terminal.autocomplete.popupMenu': 'Popup menu',
'settings.terminal.autocomplete.popupMenu.desc': 'Show a floating list of multiple suggestions.',
// Settings > Shortcuts
'settings.shortcuts.section.scheme': 'Hotkey Scheme',
'settings.shortcuts.scheme.label': 'Keyboard shortcuts',
'settings.shortcuts.scheme.desc': 'Choose which keyboard layout to use for shortcuts',
'settings.shortcuts.scheme.disabled': 'Disabled',
'settings.shortcuts.scheme.mac': 'Mac (Cmd)',
'settings.shortcuts.scheme.pc': 'PC (Ctrl)',
'settings.shortcuts.section.custom': 'Custom Shortcuts',
'settings.shortcuts.resetAll': 'Reset All',
'settings.shortcuts.recording': 'Press keys...',
'settings.shortcuts.none': 'None',
'settings.shortcuts.category.tabs': 'Tabs',
'settings.shortcuts.category.terminal': 'Terminal',
'settings.shortcuts.category.navigation': 'Navigation',
'settings.shortcuts.category.app': 'App',
'settings.shortcuts.category.sftp': 'SFTP',
// Context menus / common actions
'action.newHost': 'New Host',
'action.newSubfolder': 'New Subfolder',
'action.copyPublicKey': 'Copy Public Key',
'action.keyExport': 'Key Export',
'action.edit': 'Edit',
'action.delete': 'Delete',
'action.duplicate': 'Duplicate',
'action.open': 'Open',
'action.copy': 'Copy',
'action.run': 'Run',
'action.start': 'Start',
'action.stop': 'Stop',
'action.remove': 'Remove',
'action.convertToHost': 'Convert to Host',
// Sync
'sync.cloudSync': 'Cloud Sync',
'sync.settings': 'Sync Settings',
'sync.active': 'Cloud Sync Active',
'sync.syncing': 'Syncing...',
'sync.error': 'Sync Error',
'sync.notConfigured': 'Not Configured',
'sync.failed': 'Sync failed',
'sync.connected': 'Connected',
'sync.syncNow': 'Sync Now',
'sync.recentActivity': 'Recent activity',
'sync.history.uploaded': 'Uploaded',
'sync.history.downloaded': 'Downloaded',
'sync.history.resolved': 'Resolved',
'sync.toast.completedMessage': 'Sync completed successfully',
'sync.toast.errorTitle': 'Sync Error',
'sync.autoSync.failedTitle': 'Sync failed',
'sync.autoSync.syncedTitle': 'Synced from cloud',
'sync.autoSync.syncedMessage': 'Your data has been updated from the cloud.',
'sync.autoSync.noProvider': 'No cloud provider connected. Open Settings → Sync & Cloud to connect one.',
'sync.autoSync.alreadySyncing': 'Sync is already in progress.',
'sync.autoSync.vaultLocked': 'Vault is locked. Open Settings → Sync & Cloud to unlock.',
'sync.autoSync.conflictDetected': 'Sync conflict detected. Open Settings → Sync & Cloud to resolve.',
'sync.autoSync.syncFailed': 'Sync failed',
'sync.credentialsUnavailable': 'This device cannot decrypt some saved credentials. Re-enter credentials locally before syncing.',
'time.never': 'Never',
'time.justNow': 'Just now',
'time.minutesAgo': '{minutes}m ago',
// Vault navigation
'vault.nav.hosts': 'Hosts',
'vault.nav.keychain': 'Keychain',
'vault.nav.portForwarding': 'Port Forwarding',
'vault.nav.snippets': 'Snippets',
'vault.nav.knownHosts': 'Known Hosts',
'vault.nav.logs': 'Logs',
'vault.groups.title': 'Groups',
'vault.groups.total': '{count} total',
'vault.groups.hostsCount': '{count} Hosts',
'vault.groups.newSubgroup': 'New Subgroup',
'vault.groups.rename': 'Rename Group',
'vault.groups.delete': 'Delete Group',
'vault.groups.createSubfolder': 'Create Subfolder',
'vault.groups.createRoot': 'Create Root Group',
'vault.groups.createDialog.desc': 'Create a new group for organizing hosts.',
'vault.groups.renameDialogTitle': 'Rename Group',
'vault.groups.renameDialog.desc': 'Rename an existing group.',
'vault.groups.deleteDialogTitle': 'Delete Group',
'vault.groups.deleteDialog.desc': 'This will permanently delete the group and move all hosts to the root level.',
'vault.groups.deleteDialog.managedDesc': 'This is a managed SSH config group. Deleting it will also delete all hosts and unlink from the source file.',
'vault.groups.deleteDialog.deleteHosts': 'Also delete all hosts in this group',
'vault.groups.ungrouped': 'Ungrouped',
'vault.groups.field.name': 'Group Name',
'vault.groups.placeholder.example': 'e.g. Production',
'vault.groups.parentLabel': 'Parent',
'vault.groups.pathLabel': 'Path',
'vault.groups.settings': 'Group Settings',
'vault.groups.details': 'Group Details',
'vault.groups.details.general': 'General',
'vault.groups.details.ssh': 'SSH',
'vault.groups.details.telnet': 'Telnet',
'vault.groups.details.advanced': 'Advanced',
'vault.groups.details.appearance': 'Appearance',
'vault.groups.details.mosh': 'Mosh',
'vault.groups.details.parentGroup': 'Parent Group',
'vault.groups.details.none': 'None',
'vault.groups.details.inherited': 'Inherited from group',
'vault.groups.details.addProtocol': 'Add Protocol',
'vault.groups.details.removeProtocol': 'Remove Protocol',
'vault.groups.details.fontFamily': 'Font Family',
'vault.groups.details.fontSize': 'Font Size',
'vault.groups.errors.required': 'Group name is required.',
'vault.groups.errors.invalidChars': "Group name cannot include '/' or '\\\\'.",
'vault.groups.errors.duplicatePath': 'A group with this name already exists at this location.',
'vault.managedSource.unmanage': 'Unmanage',
'vault.managedSource.unmanageSuccess': 'Successfully unmanaged group',
'vault.hosts.header.entries': '{count} entries',
'vault.hosts.header.live': '{count} live',
// Vault hosts header/actions
'vault.hosts.search.placeholder': 'Find a host or ssh user@hostname / ssh -p 2222 user@hostname...',
'vault.hosts.connect': 'Connect',
'vault.view.grid': 'Grid',
'vault.view.list': 'List',
'vault.view.tree': 'Tree',
'vault.tree.expandAll': 'Expand All',
'vault.tree.collapseAll': 'Collapse All',
'vault.hosts.newHost': 'New Host',
'vault.hosts.newGroup': 'New Group',
'vault.hosts.import': 'Import',
'vault.hosts.export': 'Export',
'vault.hosts.export.toast.success': 'Exported {count} hosts to CSV',
'vault.hosts.export.toast.successWithSkipped': 'Exported {count} hosts to CSV ({skipped} unsupported hosts skipped)',
'vault.hosts.export.toast.noHosts': 'No hosts to export',
'vault.hosts.allHosts': 'All hosts',
'vault.hosts.pinned': 'Pinned',
'vault.hosts.recentlyConnected': 'Recently Connected',
'vault.hosts.pinToTop': 'Pin to Top',
'vault.hosts.unpin': 'Unpin',
'vault.hosts.copyCredentials': 'Copy Credentials',
'vault.hosts.copyCredentials.toast.success': 'Credentials copied to clipboard',
'vault.hosts.copyCredentials.toast.noPassword': 'No password saved for this host',
'vault.hosts.multiSelect': 'Multi-select',
'vault.hosts.selected': '{count} selected',
'vault.hosts.selectAll': 'Select All',
'vault.hosts.deselectAll': 'Deselect All',
'vault.hosts.deleteSelected': 'Delete ({count})',
'vault.hosts.deleteMultiple.success': 'Deleted {count} hosts',
'vault.hosts.moveToGroup.success': 'Moved {host} to {group}',
'vault.hosts.empty.title': 'Set up your hosts',
'vault.hosts.empty.desc': 'Save hosts to quickly connect to your servers, VMs, and containers.',
// Vault import
'vault.import.title': 'Add data to your vault',
'vault.import.desc':
'Transfer your connections from popular clients. Select a file format to start the migration.',
'vault.import.chooseFormat': 'Select a file format',
'vault.import.csv.tip': 'Bulk import: use the CSV template.',
'vault.import.csv.downloadTemplate': 'Download CSV template',
'vault.import.toast.start': 'Importing from {format}...',
'vault.import.toast.completedTitle': 'Import completed',
'vault.import.toast.failedTitle': 'Import failed',
'vault.import.toast.noEntries': 'No importable entries found in {format}.',
'vault.import.toast.noNewHosts': 'No new hosts imported from {format}.',
'vault.import.toast.summary':
'Imported {count} hosts (skipped {skipped}, duplicates {duplicates}).',
'vault.import.toast.firstIssue': 'First issue: {issue}',
'vault.import.sshConfig.chooseMode': 'Choose how to import your SSH config file.',
'vault.import.sshConfig.modeQuestion': 'How would you like to import?',
'vault.import.sshConfig.importOnly': 'Import Only',
'vault.import.sshConfig.importOnlyDesc': 'One-time import. Changes won\'t sync back to the file.',
'vault.import.sshConfig.managed': 'Managed Sync',
'vault.import.sshConfig.managedDesc': 'Keep in sync. Changes will be saved back to the file.',
'vault.import.sshConfig.managedGroup': 'ssh config',
'vault.import.sshConfig.managedSuccess': 'Imported {count} hosts. File is now managed.',
'vault.import.sshConfig.alreadyManaged': 'This file is already being managed.',
'vault.import.sshConfig.alreadyManagedDesc': 'This file is already managed under group "{group}". Remove the existing managed source first if you want to re-import.',
'vault.import.sshConfig.noFilePath': 'Cannot manage this file.',
'vault.import.sshConfig.noFilePathDesc': 'Unable to determine the file path. Managed sync requires access to the file system.',
// Known Hosts
'knownHosts.search.placeholder': 'Search known hosts...',
'knownHosts.action.scanSystem': 'Scan System',
'knownHosts.action.importFile': 'Import File',
'knownHosts.action.browseFile': 'Browse File',
'knownHosts.empty.title': 'No Known Hosts',
'knownHosts.empty.desc':
"Known hosts are SSH servers you've connected to before. Import from your system's known_hosts file to get started.",
'knownHosts.results.showingLimited':
'Showing {shown} of {total} hosts. Use search to find specific hosts.',
'knownHosts.toast.scanUnavailable': 'System scan is unavailable on this platform.',
'knownHosts.toast.scanNoFile': 'No system known_hosts file found.',
'knownHosts.toast.scanNoEntries': 'No usable entries found in known_hosts.',
'knownHosts.toast.scanImported': 'Imported {count} new hosts.',
'knownHosts.toast.scanNoNew': 'No new hosts found.',
'knownHosts.toast.scanFailed': 'Failed to scan system known_hosts.',
// Port Forwarding
'pf.empty.title': 'Set up port forwarding',
'pf.empty.desc': 'Save port forwarding to access databases, web apps, and other services.',
'pf.title': 'Port Forwarding',
'pf.rulesCount': '{count} rules',
'pf.wizard.editTitle': 'Edit Port Forwarding',
'pf.wizard.newTitle': 'New Port Forwarding',
'pf.wizard.saveChanges': 'Save Changes',
'pf.wizard.done': 'Done',
'pf.wizard.continue': 'Continue',
'pf.wizard.cancel': 'Cancel',
'pf.wizard.skipWizard': 'Skip wizard',
'pf.error.hostNotFound': 'Host not found',
'pf.toast.titleWithLabel': 'Port Forwarding: {label}',
'pf.type.local': 'Local',
'pf.type.remote': 'Remote',
'pf.type.dynamic': 'Dynamic',
'pf.type.menu.local': 'Local Forwarding',
'pf.type.menu.remote': 'Remote Forwarding',
'pf.type.menu.dynamic': 'Dynamic Forwarding',
'pf.type.local.desc': "Local forwarding lets you access a remote server's listening port as though it were local.",
'pf.type.remote.desc': 'Remote forwarding opens a port on the remote machine and forwards connections to the local (current) host.',
'pf.type.dynamic.desc': 'Dynamic port forwarding turns Netcatty into a SOCKS proxy server.',
'pf.wizard.type.title': 'Select the port forwarding type:',
'pf.wizard.localConfig.title': 'Set the local port and binding address:',
'pf.wizard.localConfig.desc': 'This port will be open on the local (current) device, and it will receive the traffic.',
'pf.wizard.localConfig.localPort': 'Local port number *',
'pf.wizard.bindAddress': 'Bind address',
'pf.wizard.remoteHost.title': 'Select the remote host:',
'pf.wizard.remoteHost.desc': 'Select a host where the port will be open. Traffic from this port will be forwarded to the destination host.',
'pf.wizard.remoteConfig.title': 'Set the port and binding address:',
'pf.wizard.remoteConfig.desc': 'Traffic will be forwarded from the specified port and interface address of the selected host.',
'pf.wizard.remoteConfig.remotePort': 'Remote port number *',
'pf.wizard.destination.title': 'Select the destination host:',
'pf.wizard.destination.desc.local': 'Enter the remote destination that you want to access through the tunnel.',
'pf.wizard.destination.desc.remote': 'The destination address and port where the traffic will be forwarded.',
'pf.wizard.destination.address': 'Destination address *',
'pf.wizard.destination.addressPlaceholder': 'e.g. 127.0.0.1 or 192.168.1.100',
'pf.wizard.destination.port': 'Destination port number *',
'pf.wizard.sshServer.title': 'Select the SSH server:',
'pf.wizard.sshServer.desc.dynamic': 'Select the SSH server that will act as your SOCKS proxy.',
'pf.wizard.sshServer.desc.default': 'Select the SSH server that will tunnel your traffic to the destination.',
'pf.wizard.label.title': 'Select the label:',
'pf.wizard.label.placeholder.dynamic': 'e.g. SOCKS Proxy',
'pf.wizard.label.placeholder.default': 'e.g. MySQL Production',
'pf.wizard.label.placeholder.remoteRule': 'e.g. Remote Rule',
'pf.wizard.placeholders.portExample': 'e.g. {port}',
'pf.action.newForwarding': 'New Forwarding',
'pf.form.labelPlaceholder': 'Rule label',
'pf.form.intermediateHost': 'Intermediate host *',
'pf.form.createRule': 'Create Rule',
'pf.form.openWizard': 'Open Wizard',
'pf.form.openWizardTitle': 'Open Port Forwarding Wizard',
'pf.view.grid': 'Grid',
'pf.view.list': 'List',
'pf.rule.summary.dynamic': 'SOCKS on {bindAddress}:{localPort}',
'pf.rule.summary.default': '{bindAddress}:{localPort} -> {remoteHost}:{remotePort}',
'pf.tooltip.relayHost': 'Relay Host',
'pf.tooltip.hostLabel': 'Host',
'pf.tooltip.hostAddress': 'Address',
'pf.tooltip.noHost': 'No relay host configured',
'pf.tooltip.localDesc': 'Local port forwarding: Access remote services through SSH tunnel',
'pf.tooltip.remoteDesc': 'Remote port forwarding: Expose local services to remote host',
'pf.tooltip.dynamicDesc': 'Dynamic SOCKS proxy: Route traffic through SSH tunnel',
'pf.deleteActive.title': 'Delete Active Port Forwarding?',
'pf.deleteActive.desc': 'This port forwarding rule "{label}" is currently active. Deleting it will stop the tunnel first.',
'pf.deleteActive.confirm': 'Stop and Delete',
'pf.form.autoStart': 'Auto Start',
'pf.form.autoStartDesc': 'Automatically start this rule when the app launches',
// SFTP
'sftp.newFolder': 'New Folder',
'sftp.newFile': 'New File',
'sftp.filter': 'Filter',
'sftp.filter.placeholder': 'Filter by filename...',
'sftp.bookmark.add': 'Bookmark this path',
'sftp.bookmark.remove': 'Remove bookmark',
'sftp.bookmark.addGlobal': '+Global',
'sftp.bookmark.addGlobalTooltip': 'Save as global bookmark (shared across all hosts)',
'sftp.bookmark.empty': 'No bookmarks yet',
'sftp.columns.name': 'Name',
'sftp.columns.modified': 'Modified',
'sftp.columns.size': 'Size',
'sftp.columns.kind': 'Kind',
'sftp.columns.actions': 'Actions',
'sftp.emptyDirectory': 'Empty directory',
'sftp.nav.up': 'Go up',
'sftp.nav.home': 'Go to home',
'sftp.nav.refresh': 'Refresh',
'sftp.upload': 'Upload',
'sftp.uploadFiles': 'Upload files',
'sftp.uploadFolder': 'Upload folder',
'sftp.dragDropToUpload': 'Drag and drop files here to upload',
'sftp.retry': 'Retry',
'sftp.context.open': 'Open',
'sftp.context.navigateTo': 'Navigate to',
'sftp.context.moveTo': 'Move to...',
'sftp.context.moveToParent': 'Move to parent directory',
'sftp.moveTo.title': 'Move to directory',
'sftp.moveTo.placeholder': 'Enter target directory path',
'sftp.moveTo.confirm': 'Move',
'sftp.moveTo.pathNotFound': 'Directory not found or inaccessible',
'sftp.context.download': 'Download',
'sftp.context.copyToOtherPane': 'Copy to other pane',
'sftp.viewMode.label': 'View mode',
'sftp.viewMode.list': 'List view',
'sftp.viewMode.tree': 'Tree view',
'sftp.tree.loadError': 'Failed to load directory',
'sftp.tree.loading': 'Loading...',
'sftp.kind.folder': 'Folder',
'sftp.context.rename': 'Rename',
'sftp.context.permissions': 'Permissions',
'sftp.context.delete': 'Delete',
'sftp.context.refresh': 'Refresh',
'sftp.context.downloadSelected': 'Download selected ({count})',
'sftp.context.deleteSelected': 'Delete selected ({count})',
'sftp.dropFilesHere': 'Drop files here',
'sftp.itemsCount': '{count} items',
'sftp.selectedCount': '{count} selected',
'sftp.path.doubleClickToEdit': 'Double-click to edit path',
'sftp.showHiddenPaths': 'Hidden paths',
'sftp.task.waiting': 'Waiting...',
'sftp.transfer.preparing': 'preparing...',
'sftp.status.loading': 'Loading...',
'sftp.status.uploading': 'Uploading...',
'sftp.status.ready': 'Ready',
'sftp.transfers': 'Transfers',
'sftp.transfers.active': '{count} active',
'sftp.transfers.clearCompleted': 'Clear completed',
'sftp.transfers.calculatingTotal': 'Calculating total size...',
'sftp.transfers.filesCount': '{count} files',
'sftp.transfers.filesProgress': '{current}/{total} files',
'sftp.transfers.expandChildren': 'Show files',
'sftp.transfers.collapseChildren': 'Hide files',
'sftp.transfers.expandChildList': 'Show detail',
'sftp.transfers.collapseChildList': 'Hide',
'sftp.transfers.dragToResize': 'Drag to resize',
'sftp.goUp': 'Go up',
'sftp.goToTerminalCwd': 'Go to terminal directory',
'sftp.encoding.label': 'Filename Encoding',
'sftp.encoding.auto': 'Auto',
'sftp.encoding.utf8': 'UTF-8',
'sftp.encoding.gb18030': 'GB18030',
'sftp.goHome': 'Go to home',
'sftp.folderName': 'Folder name',
'sftp.folderName.placeholder': 'Enter folder name',
'sftp.fileName': 'File name',
'sftp.fileName.placeholder': 'Enter file name',
'sftp.prompt.newFolderName': 'New folder name?',
'sftp.rename.title': 'Rename',
'sftp.rename.newName': 'New name',
'sftp.rename.placeholder': 'Enter new name',
'sftp.confirm.deleteOne': 'Delete "{name}"?',
'sftp.deleteConfirm.single': 'Delete "{name}"?',
'sftp.deleteConfirm.title': 'Delete {count} item(s)?',
'sftp.deleteConfirm.desc': 'This action cannot be undone. The following will be deleted:',
'sftp.deleteConfirm.descSingle': 'This action cannot be undone.',
'sftp.deleteConfirm.host': 'Host',
'sftp.deleteConfirm.path': 'Path',
'sftp.error.loadFailed': 'Failed to load directory',
'sftp.error.downloadFailed': 'Download failed',
'sftp.error.uploadFailed': 'Upload failed',
'sftp.error.deleteFailed': 'Delete failed',
'sftp.error.createFolderFailed': 'Failed to create folder',
'sftp.error.createFileFailed': 'Failed to create file',
'sftp.error.invalidFileName': 'Filename contains invalid characters: {chars}',
'sftp.error.reservedName': 'This filename is reserved by the system',
'sftp.overwrite.title': 'File Already Exists',
'sftp.overwrite.desc': 'A file named "{name}" already exists. Do you want to replace it?',
'sftp.overwrite.confirm': 'Replace',
'sftp.error.renameFailed': 'Failed to rename',
'sftp.picker.title': 'Select Host',
'sftp.picker.desc': 'Pick a host for the {side} pane',
'sftp.picker.searchPlaceholder': 'Search hosts...',
'sftp.picker.local.title': 'Local filesystem',
'sftp.picker.local.desc': 'Browse local files',
'sftp.picker.local.badge': 'Local',
'sftp.picker.noMatch': 'No matching hosts',
'sftp.permissions.title': 'Edit Permissions',
'sftp.permissions.owner': 'Owner',
'sftp.permissions.group': 'Group',
'sftp.permissions.others': 'Others',
'sftp.permissions.octal': 'Octal',
'sftp.permissions.symbolic': 'Symbolic',
'sftp.permissions.success': 'Permissions updated successfully',
'sftp.permissions.failed': 'Failed to update permissions',
'sftp.pane.local': 'Local',
'sftp.pane.remote': 'Remote',
'sftp.pane.selectHost': 'Select host',
'sftp.pane.selectHostToStart': 'Select a host to start',
'sftp.pane.chooseFilesystem': 'Choose a local or remote filesystem to browse',
'sftp.tabs.addTab': 'Add new tab',
'sftp.tabs.closeTab': 'Close tab',
'sftp.tabs.newTab': 'New Tab',
'sftp.conflict.title': 'File Conflict',
'sftp.conflict.desc': 'A file with the same name already exists at the destination',
'sftp.conflict.alreadyExistsSuffix': 'already exists',
'sftp.conflict.existingFile': 'Existing file',
'sftp.conflict.newFile': 'New file',
'sftp.conflict.size': 'Size:',
'sftp.conflict.modified': 'Modified:',
'sftp.conflict.applyToAll': 'Apply this action to all {count} remaining conflicts',
'sftp.conflict.action.skip': 'Skip',
'sftp.conflict.action.keepBoth': 'Keep Both',
'sftp.conflict.action.replace': 'Replace',
// SFTP Upload Phases
'sftp.upload.phase.compressing': 'Compressing',
'sftp.upload.phase.uploading': 'Uploading',
'sftp.upload.phase.extracting': 'Extracting',
'sftp.upload.phase.compressed': 'Compressed',
// SFTP File Opener
'sftp.context.copyPath': 'Copy file path',
'sftp.context.openWith': 'Open with...',
'sftp.context.edit': 'Edit',
'sftp.context.preview': 'Preview',
'sftp.opener.title': 'Open with',
'sftp.opener.desc': 'Choose an application to open this file',
'sftp.opener.builtInEditor': 'Built-in Editor',
'sftp.opener.editDescription': 'Edit text files',
'sftp.opener.builtInImageViewer': 'Built-in Image Viewer',
'sftp.opener.previewDescription': 'Preview images',
'sftp.opener.systemApp': 'Choose Application...',
'sftp.opener.systemAppDescription': 'Select an application from your computer',
'sftp.opener.onlySystemApp': 'This file can only be opened with an external application',
'sftp.opener.noAppsAvailable': 'No applications available',
'sftp.opener.noExtension': 'files without extension',
'sftp.opener.setDefault': 'Always use this for {ext} files',
'sftp.opener.confirmTitle': 'Set as Default?',
'sftp.opener.confirmDescription': 'Do you want to always use {app} for {ext} files?',
'sftp.opener.yesRemember': 'Yes, remember this choice',
'sftp.opener.justOnce': 'Just this once',
'sftp.opener.confirm.title': 'Set Default Application',
'sftp.opener.confirm.desc': 'Do you want to always open .{ext} files with this application?',
'sftp.editor.title': 'Text Editor',
'sftp.editor.save': 'Save to Remote',
'sftp.editor.saving': 'Saving...',
'sftp.editor.saved': 'Saved successfully',
'sftp.editor.saveFailed': 'Failed to save file',
'sftp.editor.unsavedChanges': 'You have unsaved changes. Close anyway?',
'sftp.editor.syntaxHighlight': 'Syntax Highlighting',
'sftp.preview.title': 'Image Preview',
'sftp.preview.zoomIn': 'Zoom In',
'sftp.preview.zoomOut': 'Zoom Out',
'sftp.preview.resetZoom': 'Reset Zoom',
'sftp.preview.fitToWindow': 'Fit to Window',
// Settings > SFTP File Associations
'settings.tab.sftpFileAssociations': 'SFTP',
'settings.sftp.transferConcurrency': 'Transfer Concurrency',
'settings.sftp.transferConcurrency.desc': 'Number of files to transfer in parallel when uploading or downloading folders. Higher values may improve speed but can overwhelm some servers.',
'settings.sftp.defaultOpener': 'Default File Opener',
'settings.sftp.defaultOpener.desc': 'Choose the default application for opening files without a specific file association',
'settings.sftp.defaultOpener.ask': 'Always ask',
'settings.sftp.defaultOpener.askDesc': 'Show a dialog to choose an application each time',
'settings.sftp.defaultOpener.builtInDesc': 'Open text files in the built-in editor by default',
'settings.sftp.defaultOpener.systemApp': 'Choose Application...',
'settings.sftp.defaultOpener.systemAppDesc': 'Open files with a specific application by default',
'settings.sftpFileAssociations.title': 'SFTP File Associations',
'settings.sftpFileAssociations.desc': 'Configure default applications for opening files by extension',
'settings.sftpFileAssociations.extension': 'Extension',
'settings.sftpFileAssociations.application': 'Application',
'settings.sftpFileAssociations.noAssociations': 'No file associations configured',
'settings.sftpFileAssociations.remove': 'Remove',
'settings.sftpFileAssociations.removeConfirm': 'Remove association for .{ext}?',
// Settings > SFTP Behavior
'settings.sftp.doubleClickBehavior': 'Double-click behavior',
'settings.sftp.doubleClickBehavior.desc': 'Choose the action when double-clicking a file in SFTP View',
'settings.sftp.doubleClickBehavior.open': 'Open file',
'settings.sftp.doubleClickBehavior.transfer': 'Transfer to other pane',
'settings.sftp.doubleClickBehavior.openDesc': 'Open the file in the default application',
'settings.sftp.doubleClickBehavior.transferDesc': 'Transfer the file to the other pane\'s active host',
// Settings > SFTP Auto Sync
'settings.sftp.autoSync': 'Auto-sync to remote',
'settings.sftp.autoSync.desc': 'Automatically sync file changes back to the remote server when opening files with external applications',
'settings.sftp.autoSync.enable': 'Enable auto-sync',
'settings.sftp.autoSync.enableDesc': 'When you save a file in an external application, changes will be automatically uploaded to the remote server',
// Settings > SFTP Auto Open Sidebar
'settings.sftp.autoOpenSidebar': 'Auto-open sidebar on connect',
'settings.sftp.autoOpenSidebar.desc': 'Automatically open the SFTP file browser sidebar when connecting to a host',
'settings.sftp.autoOpenSidebar.enable': 'Enable auto-open sidebar',
'settings.sftp.autoOpenSidebar.enableDesc': 'The SFTP sidebar will open automatically when a terminal session connects to a remote host',
'settings.sftp.defaultViewMode': 'Default View Mode',
'settings.sftp.defaultViewMode.desc': 'Choose the default view mode when opening a new SFTP tab. Per-host preferences override this setting.',
'settings.sftp.defaultViewMode.list': 'List View',
'settings.sftp.defaultViewMode.listDesc': 'Display files in a flat list for the current directory',
'settings.sftp.defaultViewMode.tree': 'Tree View',
'settings.sftp.defaultViewMode.treeDesc': 'Display files in a hierarchical tree structure',
'sftp.autoSync.success': 'File synced to remote: {fileName}',
'sftp.autoSync.error': 'Failed to sync file: {error}',
// SFTP Folder Upload Progress
'sftp.upload.progress': 'Uploading {current} of {total} files...',
'sftp.upload.uploading': 'Uploading...',
'sftp.upload.compressing': 'Compressing...',
'sftp.upload.extracting': 'Extracting...',
'sftp.upload.scanning': 'Scanning files...',
'sftp.upload.completed': 'Completed',
'sftp.upload.compressed': 'Compressed Transfer',
'sftp.upload.currentFile': 'Current: {fileName}',
'sftp.upload.cancelled': 'Upload cancelled',
'sftp.upload.cancel': 'Cancel',
'sftp.upload.completedToPath': 'Uploaded to {path}',
// SFTP Download
'sftp.download.completed': 'Downloaded',
'sftp.download.cancelled': 'Download cancelled',
// SFTP Reconnecting
'sftp.reconnecting.title': 'Reconnecting...',
'sftp.reconnecting.desc': 'Connection lost, attempting to reconnect',
'sftp.reconnected': 'Connection restored',
'sftp.error.reconnectFailed': 'Failed to reconnect. Please try again.',
'sftp.error.connectionLostManual': 'Connection lost. Please reconnect manually.',
'sftp.error.connectionLostReconnecting': 'Connection lost. Reconnecting...',
'sftp.error.sessionLost': 'SFTP session lost. Please reconnect.',
// Settings > SFTP Show Hidden Files
'settings.sftp.showHiddenFiles': 'Show hidden files',
'settings.sftp.showHiddenFiles.desc': 'Display hidden files (dotfiles on Unix/macOS and files with the hidden attribute on Windows) in the SFTP file browser.',
'settings.sftp.showHiddenFiles.enable': 'Show hidden files',
'settings.sftp.showHiddenFiles.enableDesc': 'Display hidden files when browsing both local and remote filesystems',
// Settings > SFTP Compressed Upload
'settings.sftp.compressedUpload': 'Folder Compression Transfer',
'settings.sftp.compressedUpload.desc': 'Compress folders before uploading to significantly reduce transfer time.',
'settings.sftp.compressedUpload.enable': 'Enable folder compression',
'settings.sftp.compressedUpload.enableDesc': 'Automatically compress folders using tar before transfer. Requires tar support on the server. Falls back to regular transfer if not available.',
// Quick Switcher
'qs.search.placeholder': 'Search hosts or tabs',
'qs.jumpTo': 'Jump To',
'qs.localTerminal': 'Local Terminal',
'qs.localShells': 'Local Shells',
'qs.default': 'Default',
// Select Host panel
'selectHost.title': 'Select Host',
'selectHost.noHostsFound': 'No hosts found',
'selectHost.newHost': 'New Host',
'selectHost.continue': 'Continue',
'selectHost.continueWithCount': 'Continue ({count} selected)',
// Quick Connect
'quickConnect.knownHost.title': 'Are you sure you want to connect?',
'quickConnect.knownHost.authenticity': 'The authenticity of {hostname} can not be established.',
'quickConnect.knownHost.fingerprintLabel': '{keyType} fingerprint is SHA256:',
'quickConnect.knownHost.addQuestion': 'Do you want to add it to the list of known hosts?',
'quickConnect.knownHost.addAndContinue': 'Add and continue',
'quickConnect.addKey': 'Add key',
'quickConnect.warning.unparsedOptions': 'Some SSH arguments were ignored: {options}',
// Terminal
'terminal.connectionErrorTitle': 'Connection Error',
// Protocol select dialog
'protocolSelect.chooseProtocol': 'Choose protocol',
'protocolSelect.port': 'port:',
// Host Details
'hostDetails.title.details': 'Host Details',
'hostDetails.title.new': 'New Host',
'hostDetails.saveAria': 'Save',
'hostDetails.section.address': 'Address',
'hostDetails.hostname.placeholder': 'IP or Hostname',
'hostDetails.section.general': 'General',
'hostDetails.section.sftp': 'SFTP Settings',
'hostDetails.sftp.sudo': 'Sudo Mode',
'hostDetails.sftp.sudo.desc': 'Automatically acquire Root privileges using stored password',
'hostDetails.sftp.sudo.passwordWarning': 'Sudo mode requires a password. Configure one above, or ensure the server allows passwordless sudo.',
'hostDetails.sftp.encoding': 'Filename Encoding',
'hostDetails.sftp.encoding.desc': 'Select the encoding used to decode and send SFTP filenames.',
'hostDetails.label.placeholder': 'Label (e.g., Production Server)',
'hostDetails.group.placeholder': 'Parent Group',
'hostDetails.section.credentials': 'Credentials',
'hostDetails.section.portCredentials': 'Port & Credentials',
'hostDetails.section.appearance': 'Appearance',
'hostDetails.distro.title': 'Linux Distribution',
'hostDetails.distro.desc': 'Auto-detect on connect, or override the distro icon manually.',
'hostDetails.distro.mode': 'Source',
'hostDetails.distro.mode.auto': 'Auto-detect',
'hostDetails.distro.mode.manual': 'Manual override',
'hostDetails.distro.detectedLabel': 'Current',
'hostDetails.distro.manualLabel': 'Override',
'hostDetails.distro.pending': 'Detect after first connection',
'hostDetails.distro.unknown': 'Unknown',
'hostDetails.distro.option.linux': 'Generic Linux',
'hostDetails.distro.option.ubuntu': 'Ubuntu',
'hostDetails.distro.option.debian': 'Debian',
'hostDetails.distro.option.centos': 'CentOS',
'hostDetails.distro.option.rocky': 'Rocky Linux',
'hostDetails.distro.option.fedora': 'Fedora',
'hostDetails.distro.option.arch': 'Arch Linux',
'hostDetails.distro.option.alpine': 'Alpine',
'hostDetails.distro.option.amazon': 'Amazon Linux',
'hostDetails.distro.option.opensuse': 'openSUSE / SLES',
'hostDetails.distro.option.redhat': 'Red Hat / RHEL',
'hostDetails.distro.option.almalinux': 'AlmaLinux',
'hostDetails.distro.option.oracle': 'Oracle Linux',
'hostDetails.distro.option.kali': 'Kali Linux',
'hostDetails.section.mosh': 'Mosh',
'hostDetails.username.placeholder': 'Username',
'hostDetails.password.placeholder': 'Password',
'hostDetails.password.show': 'Show password',
'hostDetails.password.hide': 'Hide password',
'hostDetails.password.save': 'Save password',
'hostDetails.identity.suggestions': 'Identities',
'hostDetails.identity.missing': 'Identity not found',
'hostDetails.credential.keyCertificate': 'Key, Certificate, Local Key File',
'hostDetails.credential.key': 'Key',
'hostDetails.credential.certificate': 'Certificate',
'hostDetails.credential.localKeyFile': 'Local Key File',
'hostDetails.credential.localKeyFilePlaceholder': '~/.ssh/id_ed25519',
'hostDetails.credential.browseKeyFile': 'Browse...',
'hostDetails.credential.missing': 'Credential not found',
'hostDetails.keys.search': 'Search keys...',
'hostDetails.keys.empty': 'No keys available',
'hostDetails.certs.search': 'Search certificates...',
'hostDetails.certs.empty': 'No certificates available',
'hostDetails.agentForwarding': 'Forward SSH Agent',
'hostDetails.agentForwarding.desc': 'Allow remote server to use your local SSH keys (e.g., for git operations)',
'hostDetails.agentForwarding.agentNotRunning': 'SSH Agent is not available',
'hostDetails.agentForwarding.agentNotRunningHint': 'No SSH agent detected. Enable OpenSSH Authentication Agent in Windows Services, or use a compatible agent such as Bitwarden, 1Password, or gpg-agent.',
'hostDetails.section.agentForwarding': 'SSH Agent',
'hostDetails.section.deviceType': 'Device Type',
'hostDetails.deviceType': 'Network Device Mode',
'hostDetails.deviceType.desc': 'Enable for network equipment (switches, routers, firewalls) connected via SSH. Commands are sent as-is without shell wrapping, compatible with vendor CLIs like Huawei VRP and Cisco IOS.',
'hostDetails.deviceType.warning': 'AI agent commands will be sent directly without exit code tracking. Only enable for devices that do not run a standard shell.',
'hostDetails.section.legacyAlgorithms': 'Legacy Algorithms',
'hostDetails.legacyAlgorithms': 'Allow Legacy Algorithms',
'hostDetails.legacyAlgorithms.desc': 'Enable deprecated SSH algorithms (diffie-hellman-group1, ssh-dss, 3des-cbc, etc.) for connecting to older network equipment.',
'hostDetails.legacyAlgorithms.warning': 'These algorithms have known security weaknesses. Only enable for legacy devices that do not support modern cryptography.',
'hostDetails.backspaceBehavior': 'Backspace Behavior',
'hostDetails.backspaceBehavior.default': 'Default',
'hostDetails.jumpHosts': 'Proxy via Hosts',
'hostDetails.jumpHosts.hops': '{count} hop(s)',
'hostDetails.jumpHosts.direct': 'Direct',
'hostDetails.jumpHosts.configure': 'Configure Proxy Hosts',
'hostDetails.proxy': 'Proxy via HTTP/SOCKS5',
'hostDetails.proxy.none': 'None',
'hostDetails.proxy.edit': 'Edit Proxy',
'hostDetails.proxy.configure': 'Configure Proxy',
'hostDetails.proxyPanel.title': 'Proxy via HTTP/SOCKS5',
'hostDetails.proxyPanel.hostPlaceholder': 'Proxy host',
'hostDetails.proxyPanel.credentials': 'Credentials',
'hostDetails.proxyPanel.usernamePlaceholder': 'Username',
'hostDetails.proxyPanel.passwordPlaceholder': 'Password',
'hostDetails.proxyPanel.identities': 'Identities',
'hostDetails.proxyPanel.remove': 'Remove Proxy',
'hostDetails.envVars': 'Environment Variables',
'hostDetails.envVars.add': 'Add Environment Variable',
'hostDetails.envVars.title': 'Environment Variables',
'hostDetails.envVars.desc': 'Set an environment variable for {host}.',
'hostDetails.envVars.note':
'Some SSH servers by default only allow variables with prefix LC_ and LANG_.',
'hostDetails.envVars.variable': 'Variable',
'hostDetails.envVars.value': 'Value',
'hostDetails.envVars.newVariable': 'New Variable',
'hostDetails.envVars.variableName': 'Variable name',
'hostDetails.chain.title': 'Edit Chain',
'hostDetails.chain.desc': 'Adding another host will create a connection to {host}.',
'hostDetails.chain.addHost': 'Add a Host',
'hostDetails.chain.target': 'Target',
'hostDetails.chain.availableHosts': 'Available Hosts',
'hostDetails.chain.clear': 'Clear',
'hostDetails.group.title': 'New Group',
'hostDetails.group.general': 'General',
'hostDetails.group.namePlaceholder': 'Group name',
'hostDetails.group.parentPlaceholder': 'Parent Group',
'hostDetails.group.cloudSync': 'Cloud Sync',
'hostDetails.group.addProtocol': 'Add protocol',
'hostDetails.startupCommand': 'Startup Command',
'hostDetails.startupCommand.placeholder': 'Command to run on connect (e.g., cd /app && ls)',
'hostDetails.startupCommand.help':
'This command will be executed automatically after SSH connection is established.',
'hostDetails.otherProtocols': 'Other Protocols',
'hostDetails.telnetOn': 'Telnet on',
'hostDetails.port': 'port',
'hostDetails.telnet.credentials': 'Credentials',
'hostDetails.telnet.username': 'Telnet Username',
'hostDetails.telnet.password': 'Telnet Password',
'hostDetails.charset.placeholder': 'Charset (e.g. UTF-8)',
'hostDetails.telnet.add': 'Add Telnet Protocol',
'hostDetails.tags': 'Tags',
'hostDetails.group': 'Group',
'hostDetails.selectGroup': 'Select Group',
'hostDetails.addTag': 'Add a tag...',
'hostDetails.createTag': 'Create tag',
'hostDetails.createGroup': 'Create group',
// Host form (legacy modal)
'hostForm.title.edit': 'Edit Host',
'hostForm.title.new': 'New Host',
'hostForm.desc.edit': 'Update connection details for this host',
'hostForm.desc.new': 'Create a new SSH host entry',
'hostForm.field.label': 'Label',
'hostForm.placeholder.label': 'My Production Server',
'hostForm.field.hostname': 'Hostname / IP',
'hostForm.placeholder.hostname': '192.168.1.1',
'hostForm.field.port': 'Port',
'hostForm.field.username': 'Username',
'hostForm.field.osType': 'OS Type',
'hostForm.placeholder.selectOs': 'Select OS',
'hostForm.field.group': 'Group',
'hostForm.placeholder.group': 'e.g. AWS, DigitalOcean',
'hostForm.field.tags': 'Tags',
'hostForm.placeholder.addTag': 'Add a tag...',
'hostForm.auth.method': 'Authentication Method',
'hostForm.auth.password': 'Password',
'hostForm.auth.sshKey': 'SSH Key',
'hostForm.auth.selectKey': 'Select an SSH Key',
'hostForm.auth.noKeys': 'No keys available',
'hostForm.auth.noKeysHint': 'No SSH keys found in Keychain. Please create one first.',
'hostForm.saveHost': 'Save Host',
// Connection logs
'logs.table.date': 'Date',
'logs.table.user': 'User',
'logs.table.host': 'Host',
'logs.table.saved': 'Saved',
'logs.empty.title': 'No Connection Logs',
'logs.empty.desc':
'Your connection history will appear here when you connect to hosts or open local terminals.',
'logs.loadMore': 'Load {count} more logs',
'logs.ongoing': 'ongoing',
'logs.localTerminal': 'Local Terminal',
'logs.action.save': 'Save',
'logs.action.unsave': 'Unsave',
'logs.action.delete': 'Delete',
// Log view
'logView.customizeAppearance': 'Customize appearance',
'logView.appearance': 'Appearance',
'logView.readOnly': 'Read-only',
'logView.export': 'Export',
// Terminal toolbar / search / context menu / auth
'terminal.toolbar.openSftp': 'Open SFTP',
'terminal.toolbar.availableAfterConnect': 'Available after connect',
'terminal.toolbar.sftp': 'SFTP',
'terminal.toolbar.scripts': 'Scripts',
'terminal.toolbar.library': 'Library',
'terminal.toolbar.noSnippets': 'No snippets available',
'terminal.toolbar.terminalSettings': 'Terminal settings',
'terminal.toolbar.searchTerminal': 'Search terminal (Ctrl+F)',
'terminal.toolbar.search': 'Search',
'terminal.toolbar.broadcast': 'Broadcast',
'terminal.toolbar.broadcastEnable': 'Enable Broadcast Mode',
'terminal.toolbar.broadcastDisable': 'Disable Broadcast Mode',
'terminal.toolbar.composeBar': 'Compose Bar',
'terminal.composeBar.placeholder': 'Type command here, press Enter to send...',
'terminal.composeBar.send': 'Send',
'terminal.composeBar.close': 'Close compose bar',
'terminal.composeBar.broadcasting': 'Broadcasting to all sessions',
'terminal.toolbar.focus': 'Focus',
'terminal.toolbar.focusMode': 'Focus Mode',
'terminal.toolbar.encoding': 'Terminal Encoding',
'terminal.toolbar.encoding.utf8': 'UTF-8',
'terminal.toolbar.encoding.gb18030': 'GB18030',
'terminal.toolbar.closeSession': 'Close session',
'terminal.toolbar.hostHighlight.title': 'Host Keyword Highlighting',
'terminal.toolbar.hostHighlight.noRules': 'No custom highlight rules defined for this host',
'terminal.toolbar.hostHighlight.addRule': 'Add New Rule',
'terminal.toolbar.hostHighlight.labelPlaceholder': 'Label (e.g., Error)',
'terminal.toolbar.hostHighlight.patternPlaceholder': 'Regex pattern (e.g., \\bfailed\\b)',
'terminal.toolbar.hostHighlight.invalidPattern': 'Invalid regex pattern',
'terminal.toolbar.hostHighlight.clearAll': 'Clear All',
'terminal.toolbar.hostHighlight.changeColor': 'Change highlight color for',
'terminal.toolbar.hostHighlight.selectColor': 'Select color for new rule',
'terminal.serverStats.cpu': 'CPU Usage',
'terminal.serverStats.cpuCores': 'CPU Core Usage',
'terminal.serverStats.memory': 'Memory Usage',
'terminal.serverStats.memoryDetails': 'Memory Details',
'terminal.serverStats.memUsed': 'Used',
'terminal.serverStats.memBuffers': 'Buffers',
'terminal.serverStats.memCached': 'Cache',
'terminal.serverStats.memFree': 'Free',
'terminal.serverStats.swap': 'Swap',
'terminal.serverStats.swapUsed': 'Swap Used',
'terminal.serverStats.swapFree': 'Swap Free',
'terminal.serverStats.swapTotal': 'Total',
'terminal.serverStats.topProcesses': 'Top Processes by Memory',
'terminal.serverStats.disk': 'Disk Usage (Root)',
'terminal.serverStats.diskDetails': 'Mounted Disks',
'terminal.serverStats.network': 'Network Speed',
'terminal.serverStats.networkDetails': 'Network Interfaces',
'terminal.serverStats.noData': 'No data available',
'terminal.dragDrop.localTitle': 'Drop to Insert Paths',
'terminal.dragDrop.localMessage': 'File paths will be inserted into the terminal',
'terminal.dragDrop.remoteTitle': 'Drop to Upload Files',
'terminal.dragDrop.remoteMessage': 'Files will be uploaded via SFTP',
'terminal.dragDrop.notConnected': 'Cannot drop files - terminal is not connected',
'terminal.dragDrop.errorTitle': 'Drop Error',
'terminal.dragDrop.errorMessage': 'Failed to process dropped files',
'terminal.search.placeholder': 'Search...',
'terminal.search.noResults': 'No results',
'terminal.search.prevMatch': 'Previous match (Shift+Enter)',
'terminal.search.nextMatch': 'Next match (Enter)',
'terminal.menu.copy': 'Copy',
'terminal.menu.paste': 'Paste',
'terminal.menu.selectAll': 'Select All',
'terminal.menu.splitHorizontal': 'Split Horizontal',
'terminal.menu.splitVertical': 'Split Vertical',
'terminal.menu.clearBuffer': 'Clear Buffer',
'terminal.menu.closeTerminal': 'Close terminal',
'terminal.auth.password': 'Password',
'terminal.auth.sshKey': 'SSH Key',
'terminal.auth.username': 'Username',
'terminal.auth.username.placeholder': 'root',
'terminal.auth.passwordLabel': 'Password',
'terminal.auth.password.placeholder': 'Enter password',
'terminal.auth.passphrase': 'Passphrase',
'terminal.auth.passphrase.placeholder': 'Optional passphrase for the selected private key',
'terminal.auth.certificate': 'Certificate',
'terminal.auth.selectKey': 'Select Key',
'terminal.auth.noKeysHint': 'No keys available. Add keys in Keychain.',
'terminal.auth.continueSave': 'Continue & Save',
'terminal.auth.credentialsUnavailable': 'Saved credentials cannot be decrypted on this device. Please re-enter and save them again.',
'terminal.auth.jumpCredentialsUnavailable': 'A jump host has saved credentials that cannot be decrypted on this device. Open host settings and re-enter them.',
'terminal.auth.proxyCredentialsUnavailable': 'Proxy credentials cannot be decrypted on this device. Open host settings and re-enter the proxy password.',
'terminal.auth.keyUnavailableFallbackPassword': 'Saved SSH key is unavailable on this device. Falling back to password authentication.',
'terminal.progress.timeoutIn': 'Timeout in {seconds}s',
'terminal.progress.disconnected': 'Disconnected',
'terminal.progress.cancelling': 'Cancelling...',
'terminal.progress.startOver': 'Start over',
'terminal.connection.dismissDisconnectedDialog': 'Dismiss disconnected notice',
'terminal.connection.chainOf': 'Chain {current} of {total}',
'terminal.connection.showLogs': 'Show logs',
'terminal.connection.hideLogs': 'Hide logs',
'terminal.connection.protocol.ssh': 'SSH',
'terminal.connection.protocol.telnet': 'Telnet',
'terminal.connection.protocol.mosh': 'Mosh',
'terminal.connection.protocol.serial': 'Serial',
'terminal.connection.protocol.local': 'Local Shell',
'terminal.themeModal.title': 'Terminal Appearance',
'terminal.themeModal.tab.theme': 'Theme',
'terminal.themeModal.tab.font': 'Font',
'terminal.themeModal.tab.custom': 'Custom',
'terminal.themeModal.globalTheme': 'Global Theme',
'terminal.themeModal.globalFont': 'Global Font',
'terminal.themeModal.fontSize': 'Font Size',
'terminal.themeModal.fontWeight': 'Font Weight',
'terminal.themeModal.livePreview': 'Live Preview',
'terminal.themeModal.themeType': '{type} theme',
// Custom Themes
'terminal.customTheme.section': 'Custom Themes',
'terminal.customTheme.yourThemes': 'Your Themes',
'terminal.customTheme.new': 'New Theme',
'terminal.customTheme.newDesc': 'Clone current theme and customize',
'terminal.customTheme.newTitle': 'New Custom Theme',
'terminal.customTheme.editTitle': 'Edit Theme',
'terminal.customTheme.import': 'Import .itermcolors',
'terminal.customTheme.importDesc': 'Import from iTerm2 color scheme file',
'terminal.customTheme.importError': 'Failed to parse the selected file. Please ensure it is a valid .itermcolors XML file.',
'terminal.customTheme.delete': 'Delete Theme',
'terminal.customTheme.confirmDelete': 'Confirm Delete',
'terminal.customTheme.name': 'Name',
'terminal.customTheme.namePlaceholder': 'My Custom Theme',
'terminal.customTheme.type': 'Type',
'terminal.customTheme.group.general': 'General',
'terminal.customTheme.group.normal': 'Normal Colors',
'terminal.customTheme.group.bright': 'Bright Colors',
'terminal.customTheme.color.background': 'Background',
'terminal.customTheme.color.foreground': 'Foreground',
'terminal.customTheme.color.cursor': 'Cursor',
'terminal.customTheme.color.selection': 'Selection',
'terminal.customTheme.color.black': 'Black',
'terminal.customTheme.color.red': 'Red',
'terminal.customTheme.color.green': 'Green',
'terminal.customTheme.color.yellow': 'Yellow',
'terminal.customTheme.color.blue': 'Blue',
'terminal.customTheme.color.magenta': 'Magenta',
'terminal.customTheme.color.cyan': 'Cyan',
'terminal.customTheme.color.white': 'White',
'terminal.customTheme.color.brightBlack': 'Bright Black',
'terminal.customTheme.color.brightRed': 'Bright Red',
'terminal.customTheme.color.brightGreen': 'Bright Green',
'terminal.customTheme.color.brightYellow': 'Bright Yellow',
'terminal.customTheme.color.brightBlue': 'Bright Blue',
'terminal.customTheme.color.brightMagenta': 'Bright Magenta',
'terminal.customTheme.color.brightCyan': 'Bright Cyan',
'terminal.customTheme.color.brightWhite': 'Bright White',
// Cloud Sync Settings
'cloudSync.gate.title': 'End-to-End Encrypted Sync',
'cloudSync.gate.desc':
'Your data is encrypted locally before syncing. Cloud providers never see your plaintext data. Set a master key to enable secure sync.',
'cloudSync.gate.masterKey': 'Master Key',
'cloudSync.gate.confirmMasterKey': 'Confirm Master Key',
'cloudSync.gate.placeholder': 'Enter a strong password',
'cloudSync.gate.confirmPlaceholder': 'Confirm your password',
'cloudSync.gate.mismatch': 'Passwords do not match',
'cloudSync.gate.warning':
'I understand that if I forget my master key, my data cannot be recovered. There is no password reset.',
'cloudSync.gate.enableVault': 'Enable Encrypted Vault',
'cloudSync.gate.enabledToast': 'Encrypted vault enabled',
'cloudSync.gate.setupFailed': 'Failed to set up master key',
'cloudSync.passwordStrength.tooShort': 'Too short',
'cloudSync.passwordStrength.weak': 'Weak',
'cloudSync.passwordStrength.moderate': 'Moderate',
'cloudSync.passwordStrength.strong': 'Strong',
'cloudSync.passwordStrength.veryStrong': 'Very Strong',
'cloudSync.provider.notConnected': 'Not connected',
'cloudSync.provider.sync': 'Sync',
'cloudSync.provider.connect': 'Connect',
'cloudSync.provider.connecting': 'Connecting...',
'cloudSync.provider.webdav': 'WebDAV',
'cloudSync.provider.webdav.desc': 'Connect to a self-hosted WebDAV endpoint',
'cloudSync.provider.s3': 'S3 Compatible',
'cloudSync.provider.s3.desc': 'Connect to S3-compatible object storage',
'cloudSync.provider.comingSoon': 'Coming soon',
'cloudSync.webdav.title': 'WebDAV Settings',
'cloudSync.webdav.desc': 'Configure a WebDAV endpoint for encrypted sync.',
'cloudSync.webdav.endpoint': 'Endpoint URL',
'cloudSync.webdav.authType': 'Auth Type',
'cloudSync.webdav.auth.basic': 'Basic',
'cloudSync.webdav.auth.digest': 'Digest',
'cloudSync.webdav.auth.token': 'Token',
'cloudSync.webdav.username': 'Username',
'cloudSync.webdav.password': 'Password',
'cloudSync.webdav.token': 'Token',
'cloudSync.webdav.showSecret': 'Show secret',
'cloudSync.webdav.allowInsecure': 'Allow insecure connection (ignore certificate errors)',
'cloudSync.webdav.validation.endpoint': 'Enter a valid WebDAV endpoint.',
'cloudSync.webdav.validation.credentials': 'Username and password are required.',
'cloudSync.webdav.validation.token': 'Token is required.',
'cloudSync.s3.title': 'S3 Settings',
'cloudSync.s3.desc': 'Connect to S3-compatible object storage for encrypted sync.',
'cloudSync.s3.endpoint': 'Endpoint URL',
'cloudSync.s3.region': 'Region',
'cloudSync.s3.bucket': 'Bucket',
'cloudSync.s3.accessKeyId': 'Access Key ID',
'cloudSync.s3.secretAccessKey': 'Secret Access Key',
'cloudSync.s3.sessionToken': 'Session Token (optional)',
'cloudSync.s3.prefix': 'Key Prefix (optional)',
'cloudSync.s3.forcePathStyle': 'Force path-style URLs (for MinIO/R2, etc.)',
'cloudSync.s3.showSecret': 'Show secrets',
'cloudSync.s3.validation.required': 'Endpoint, region, bucket, access key, and secret are required.',
'cloudSync.smb.title': 'SMB Settings',
'cloudSync.smb.desc': 'Connect to an SMB/CIFS file share for encrypted sync.',
'cloudSync.smb.share': 'Share Path',
'cloudSync.smb.username': 'Username',
'cloudSync.smb.password': 'Password',
'cloudSync.smb.domain': 'Domain (optional)',
'cloudSync.smb.domainPlaceholder': 'e.g., WORKGROUP',
'cloudSync.smb.port': 'Port (optional)',
'cloudSync.smb.showSecret': 'Show password',
'cloudSync.smb.validation.share': 'Share path is required.',
'cloudSync.smb.validation.port': 'Port must be a number between 1 and 65535.',
'cloudSync.connect.smb.success': 'SMB connected successfully',
'cloudSync.connect.smb.failedTitle': 'SMB connection failed',
'cloudSync.provider.smb': 'SMB Share',
'cloudSync.connect.webdav.success': 'WebDAV connected successfully',
'cloudSync.connect.webdav.failedTitle': 'WebDAV connection failed',
'cloudSync.connect.s3.success': 'S3 connected successfully',
'cloudSync.connect.s3.failedTitle': 'S3 connection failed',
'cloudSync.lastSync.never': 'Never',
'cloudSync.lastSync.justNow': 'Just now',
'cloudSync.lastSync.minutesAgo': '{minutes} min ago',
'cloudSync.changeKey': 'Change Key',
'cloudSync.providers.title': 'Cloud Providers',
'cloudSync.syncAll': 'Sync All Connected Providers',
'cloudSync.autoSync.title': 'Auto-sync',
'cloudSync.autoSync.desc': 'Automatically sync when changes are made',
'cloudSync.status.title': 'Sync Status',
'cloudSync.status.localVersion': 'Local Version',
'cloudSync.status.remoteVersion': 'Remote Version',
'cloudSync.history.title': 'Sync History',
'cloudSync.history.upload': 'Upload',
'cloudSync.history.download': 'Download',
'cloudSync.history.resolved': 'Resolved',
'cloudSync.history.error': 'Error',
'cloudSync.changeKey.title': 'Change Master Key',
'cloudSync.changeKey.current': 'Current Master Key',
'cloudSync.changeKey.new': 'New Master Key',
'cloudSync.changeKey.confirmNew': 'Confirm New Master Key',
'cloudSync.changeKey.currentPlaceholder': 'Enter current master key',
'cloudSync.changeKey.newPlaceholder': 'Enter new master key',
'cloudSync.changeKey.confirmPlaceholder': 'Confirm new master key',
'cloudSync.changeKey.fillAll': 'Please fill in all fields',
'cloudSync.changeKey.minLength': 'New master key must be at least 8 characters',
'cloudSync.changeKey.notMatch': 'New master keys do not match',
'cloudSync.changeKey.incorrectCurrent': 'Incorrect current master key',
'cloudSync.changeKey.failed': 'Failed to change master key',
'cloudSync.changeKey.desc': 'This will re-encrypt your vault. Make sure you remember the new key.',
'cloudSync.changeKey.showKeys': 'Show keys',
'cloudSync.changeKey.updatedToast': 'Master key updated',
'cloudSync.changeKey.updateButton': 'Update Key',
'cloudSync.unlock.title': 'Enter Master Key',
'cloudSync.unlock.masterKey': 'Master Key',
'cloudSync.unlock.desc':
'Enter your master key once to enable encrypted sync. It will be stored securely using your OS keychain.',
'cloudSync.unlock.placeholder': 'Enter your master key',
'cloudSync.unlock.empty': 'Please enter your master key',
'cloudSync.unlock.incorrect': 'Incorrect master key',
'cloudSync.unlock.failed': 'Failed to unlock vault',
'cloudSync.unlock.showKey': 'Show key',
'cloudSync.unlock.notNow': 'Not now',
'cloudSync.unlock.readyToast': 'Vault ready',
'cloudSync.unlock.unlockButton': 'Unlock',
'cloudSync.header.vaultReady': 'Vault ready',
'cloudSync.header.preparingVault': 'Preparing vault...',
'cloudSync.header.providersConnected': '{count} provider(s) connected',
'cloudSync.githubFlow.title': 'Connect to GitHub',
'cloudSync.githubFlow.desc': 'Copy the code below and enter it on GitHub to authorize Netcatty.',
'cloudSync.githubFlow.copyCode': 'Copy code',
'cloudSync.githubFlow.copied': 'Copied!',
'cloudSync.githubFlow.openGitHub': 'Open GitHub',
'cloudSync.githubFlow.waiting': 'Waiting for authorization...',
'cloudSync.conflict.title': 'Version conflict detected',
'cloudSync.conflict.desc': 'Choose which version to keep',
'cloudSync.conflict.local': 'LOCAL',
'cloudSync.conflict.cloud': 'CLOUD',
'cloudSync.conflict.keepLocal': 'Overwrite cloud (keep local)',
'cloudSync.conflict.useCloud': 'Download cloud (overwrite local)',
'cloudSync.connect.browserContinue': 'Complete authorization in browser',
'cloudSync.connect.github.success': 'GitHub connected successfully',
'cloudSync.connect.github.failedTitle': 'GitHub connection failed',
'cloudSync.connect.github.timeout': 'GitHub connection timed out. Check your network or proxy settings.',
'cloudSync.connect.github.networkError': 'Unable to reach GitHub. Check your network or proxy settings.',
'cloudSync.connect.google.failedTitle': 'Google connection failed',
'cloudSync.connect.onedrive.failedTitle': 'OneDrive connection failed',
'cloudSync.sync.success': 'Synced to {provider}',
'cloudSync.sync.failed': 'Sync failed',
'cloudSync.sync.failedTitle': 'Sync failed',
'cloudSync.sync.errorTitle': 'Sync error',
'cloudSync.resolve.downloaded': 'Downloaded cloud data',
'cloudSync.resolve.uploaded': 'Uploaded local data',
'cloudSync.resolve.failedTitle': 'Conflict resolution failed',
'cloudSync.clearLocal.title': 'Clear Local Data',
'cloudSync.clearLocal.desc': 'Reset local version and sync history. Next sync will download from cloud.',
'cloudSync.clearLocal.button': 'Clear',
'cloudSync.clearLocal.dialog.title': 'Clear Local Vault Data?',
'cloudSync.clearLocal.dialog.desc': 'This will reset local version to 0 and clear sync history. Your next sync will download data from the cloud, replacing local data.',
'cloudSync.clearLocal.dialog.cancel': 'Cancel',
'cloudSync.clearLocal.dialog.confirm': 'Clear Local Data',
'cloudSync.clearLocal.toast.title': 'Local data cleared',
'cloudSync.clearLocal.toast.desc': 'Local version reset to 0. Sync to download from cloud.',
// Keychain
'keychain.filter.key': 'KEY',
'keychain.filter.certificate': 'CERTIFICATE',
'keychain.action.generateKey': 'Generate Key',
'keychain.action.importKey': 'Import Key',
'keychain.action.newIdentity': 'New Identity',
'keychain.action.importCertificate': 'Import Certificate',
'keychain.view.grid': 'Grid',
'keychain.view.list': 'List',
'keychain.section.keys': 'Keys',
'keychain.section.identities': 'Identities',
'keychain.count.items': '{count} items',
'keychain.empty.title': 'Set up your keys',
'keychain.empty.desc': 'Import or generate SSH keys for secure authentication.',
'keychain.panel.generateKey': 'Generate Key',
'keychain.panel.newKey': 'New Key',
'keychain.panel.keyDetails': 'Key Details',
'keychain.panel.editKey': 'Edit Key',
'keychain.panel.editIdentity': 'Edit Identity',
'keychain.panel.newIdentity': 'New Identity',
'keychain.panel.keyExport': 'Key Export',
'keychain.validation.labelRequired': 'Please enter a label for the key',
'keychain.validation.labelAndPrivateKeyRequired': 'Label and private key are required',
'keychain.validation.labelAndUsernameRequired': 'Label and username are required',
'keychain.error.generationUnavailable':
'Key generation not available - please ensure the app is running in Electron',
'keychain.error.generateKeyPairFailed': 'Failed to generate key pair',
'keychain.error.generateKeyFailed': 'Failed to generate key',
'keychain.error.keyGenerationTitle': 'Key Generation',
'keychain.export.exportTo': 'Export to *',
'keychain.export.selectHost': 'Select Host',
'keychain.export.location': 'Location ~ $1 *',
'keychain.export.filename': 'Filename ~ $2 *',
'keychain.export.note':
'Key export currently supports only {unix} systems. Use the {advanced} section to customize the export script.',
'keychain.export.script': 'Script *',
'keychain.export.scriptPlaceholder': 'Export script...',
'keychain.export.missingCredentials':
'Host has no saved password or key. Please add password credentials to the host first.',
'keychain.export.successTitle': 'Export Successful',
'keychain.export.successMessage': 'Public key exported and attached to {host}',
'keychain.export.failedTitle': 'Export Failed',
'keychain.export.failedMessage': 'Failed to export key: {error}',
'keychain.export.failedPrefix': 'Export failed: {error}',
'keychain.export.exitCode': 'Command exited with code {code}',
'keychain.export.exporting': 'Exporting...',
'keychain.export.exportAndAttach': 'Export and Attach',
'keychain.export.title': 'Key export',
'keychain.export.exportToRequired': 'Export to *',
'keychain.export.selectHostPlaceholder': 'Select a host...',
'keychain.export.locationLabel': 'Location ~ $1 *',
'keychain.export.filenameLabel': 'Filename ~ $2 *',
'keychain.export.advanced': 'Advanced',
'keychain.export.note.supportsOnly': 'Key export currently supports only',
'keychain.export.note.systems': 'systems.',
'keychain.export.note.use': 'Use',
'keychain.export.note.customize': 'section to customize the export script.',
'keychain.export.scriptRequired': 'Script *',
'keychain.export.exportToHost': 'Export to host',
'keychain.export.failedGeneric': 'Export failed: {message}',
'keychain.field.label': 'Label',
'keychain.field.labelRequired': 'Label *',
'keychain.field.labelPlaceholder': 'Key label',
'keychain.field.privateKeyRequired': 'Private key *',
'keychain.field.publicKey': 'Public key',
'keychain.field.certificatePlaceholder': 'Certificate content (optional)',
'keychain.generate.keyType': 'Key type',
'keychain.generate.keySize': 'Key size',
'keychain.generate.labelPlaceholder': 'Key label',
'keychain.generate.passphrasePlaceholder': 'Passphrase (optional)',
'keychain.generate.savePassphrase': 'Save passphrase',
'keychain.generate.generate': 'Generate',
'keychain.generate.generateSave': 'Generate & Save',
'keychain.import.dropHint': 'Drop a key file here',
'keychain.import.importFromFile': 'Import from file',
'keychain.import.saveKey': 'Save Key',
'keychain.import.importedKeyLabel': 'Imported Key',
'keychain.identity.usernameRequired': 'Username *',
'keychain.identity.method.passwordOnly': 'Password',
'keychain.identity.summary.password': 'Auth password',
'keychain.identity.summary.key': 'Auth key',
'keychain.identity.summary.certificate': 'Auth certificate',
'keychain.identity.summary.passwordAndKey': 'Auth password and key',
'keychain.identity.summary.passwordAndCertificate': 'Auth password and certificate',
'keychain.identity.summary.none': 'No credentials',
'keychain.identity.selectCredential': 'Select {kind}',
'keychain.identity.save': 'Save',
'keychain.identity.update': 'Update',
'keychain.keyDialog.newTitle': 'New Key',
'keychain.keyDialog.newDesc': 'Add a new SSH key',
'keychain.keyDialog.editTitle': 'Edit Key',
'keychain.keyDialog.editDesc': 'Update this SSH key',
'keychain.keyDialog.updateKey': 'Update Key',
// Tabs
'tabs.closeSessionAria': 'Close session',
'tabs.closeLogViewAria': 'Close log view',
'tabs.logPrefix': 'Log:',
'tabs.logLocal': 'Local',
'tabs.copyTab': 'Copy Tab',
'keychain.edit.labelRequired': 'Label *',
'keychain.edit.keyLabelPlaceholder': 'Key label',
'keychain.edit.privateKeyRequired': 'Private key *',
'keychain.edit.publicKey': 'Public key',
'keychain.edit.certificate': 'Certificate',
'keychain.edit.certificatePlaceholder': 'Certificate content (optional)',
'keychain.edit.keyExport': 'Key export',
'keychain.edit.exportToHost': 'Export to host',
// Snippets
'snippets.searchPlaceholder': 'Search snippets...',
'snippets.action.newSnippet': 'New Snippet',
'snippets.action.newPackage': 'New Package',
'snippets.panel.newTitle': 'New Snippet',
'snippets.panel.editTitle': 'Edit Snippet',
'snippets.field.description': 'Action description',
'snippets.field.descriptionPlaceholder': 'Example: check network load',
'snippets.field.package': 'Add a Package',
'snippets.field.packagePlaceholder': 'Select or create package',
'snippets.field.createPackage': 'Create Package',
'snippets.field.scriptRequired': 'Script *',
'snippets.targets.title': 'Targets',
'snippets.targets.add': 'Add targets',
'snippets.history.title': 'Shell History',
'snippets.history.subtitle': '{count} commands',
'snippets.history.emptyTitle': 'No shell history yet',
'snippets.history.emptyDesc': 'Commands you execute will appear here',
'snippets.history.loadMore': 'Load more',
'snippets.history.separator': '•',
'snippets.history.labelPlaceholder': 'Set a label for this snippet',
'snippets.history.saveAsSnippet': 'Save as Snippet',
'snippets.history.time.justNow': 'just now',
'snippets.history.time.minutesAgo': '{count}m ago',
'snippets.history.time.hoursAgo': '{count}h ago',
'snippets.history.time.daysAgo': '{count}d ago',
'snippets.breadcrumb.allPackages': 'All packages',
'snippets.breadcrumb.separator': '',
'snippets.empty.title': 'Create snippet',
'snippets.empty.desc': 'Save your most used commands as snippets to reuse them in one click.',
'snippets.section.packages': 'Packages',
'snippets.section.snippets': 'Snippets',
'snippets.package.count': '{count} snippet(s)',
'snippets.commandFallback': 'Command',
'snippets.view.grid': 'Grid',
'snippets.view.list': 'List',
'snippets.packageDialog.title': 'New Package',
'snippets.packageDialog.parent': 'Parent: {parent}',
'snippets.packageDialog.root': 'Root',
'snippets.packageDialog.placeholder': 'e.g. ops/maintenance',
'snippets.packageDialog.hint': 'Use "/" to create nested packages.',
// Snippets Rename Dialog
'snippets.renameDialog.title': 'Rename Package',
'snippets.renameDialog.currentPath': 'Current path: {path}',
'snippets.renameDialog.placeholder': 'Enter new name',
'snippets.renameDialog.error.empty': 'Package name cannot be empty',
'snippets.renameDialog.error.duplicate': 'A package with this name already exists',
'snippets.renameDialog.error.invalidChars': 'Package name can only contain letters, numbers, hyphens, and underscores',
'snippets.field.noAutoRun': 'Paste only (do not auto-execute)',
// Snippet Shortkey
'snippets.field.shortkey': 'Keyboard Shortcut',
'snippets.shortkey.placeholder': 'Click to set shortcut',
'snippets.shortkey.recording': 'Press a key combination...',
'snippets.shortkey.hint': 'Press this shortcut in terminal to quickly send the command.',
'snippets.shortkey.clear': 'Clear shortcut',
'snippets.shortkey.error.systemConflict': 'This shortcut conflicts with a system shortcut',
'snippets.shortkey.error.snippetConflict': 'This shortcut is already used by snippet: {name}',
// Serial Port
'serial.button': 'Serial',
'serial.modal.title': 'Connect to Serial Port',
'serial.modal.desc': 'Configure serial port connection settings',
'serial.field.port': 'Serial Port',
'serial.field.selectPort': 'Select a port...',
'serial.field.baudRate': 'Baud Rate',
'serial.field.dataBits': 'Data Bits',
'serial.field.stopBits': 'Stop Bits',
'serial.field.stopBits15Warning': '1.5 stop bits may not be supported on all Windows devices',
'serial.field.parity': 'Parity',
'serial.field.flowControl': 'Flow Control',
'serial.noPorts': 'No serial ports detected. Connect a device and refresh.',
'serial.field.customPort': 'Custom Port Path',
'serial.field.customPortPlaceholder': 'e.g. /dev/ttys001 or COM1',
'serial.type.hardware': 'Hardware',
'serial.type.pseudo': 'Pseudo Terminal',
'serial.type.custom': 'Custom',
'serial.parity.none': 'None',
'serial.parity.even': 'Even',
'serial.parity.odd': 'Odd',
'serial.parity.mark': 'Mark',
'serial.parity.space': 'Space',
'serial.flowControl.none': 'None',
'serial.flowControl.xon/xoff': 'XON/XOFF (Software)',
'serial.flowControl.rts/cts': 'RTS/CTS (Hardware)',
'serial.field.localEcho': 'Force Local Echo',
'serial.field.localEchoDesc': 'Echo typed characters locally (for devices without remote echo)',
'serial.field.lineMode': 'Line Mode',
'serial.field.lineModeDesc': 'Buffer input and send on Enter (instead of character-by-character)',
'serial.field.charset': 'Charset',
'serial.connectionError': 'Failed to connect to serial port',
'serial.field.baudRatePlaceholder': 'Select or enter baud rate...',
'serial.field.baudRateEmpty': 'Enter a custom baud rate',
'serial.field.customBaudRate': 'Using custom baud rate',
'serial.field.saveConfig': 'Save Configuration',
'serial.field.saveConfigDesc': 'Save this serial configuration to hosts for quick access',
'serial.field.configLabel': 'Configuration Name',
'serial.field.configLabelPlaceholder': 'e.g. Arduino Uno',
'serial.connectAndSave': 'Connect & Save',
'serial.edit.title': 'Serial Port Settings',
// Keyboard Interactive Authentication (2FA/MFA)
'keyboard.interactive.title': 'Authentication Required',
'keyboard.interactive.desc': 'The server requires additional authentication.',
'keyboard.interactive.descWithHost': 'The server {hostname} requires additional authentication.',
'keyboard.interactive.response': 'Response',
'keyboard.interactive.enterCode': 'Enter verification code',
'keyboard.interactive.enterResponse': 'Enter response',
'keyboard.interactive.submit': 'Submit',
'keyboard.interactive.verifying': 'Verifying...',
'keyboard.interactive.savePassword': 'Save password',
// Passphrase Modal for encrypted SSH keys
'passphrase.title': 'SSH Key Passphrase',
'passphrase.desc': 'Enter the passphrase for {keyName}',
'passphrase.descWithHost': 'Enter the passphrase for {keyName} to connect to {hostname}',
'passphrase.label': 'Passphrase',
'passphrase.keyPath': 'Key',
'passphrase.unlock': 'Unlock',
'passphrase.unlocking': 'Unlocking...',
'passphrase.skip': 'Skip',
// Text Editor
'sftp.editor.wordWrap': 'Word Wrap',
// AI Settings
'ai.agentSettings': 'Agent Settings',
'ai.title': 'AI',
'ai.description': 'Configure AI providers, agents, and safety settings',
'ai.providers': 'Providers',
'ai.providers.empty': 'No providers configured. Add a provider to get started.',
'ai.providers.add': 'Add Provider',
'ai.providers.active': 'Active',
'ai.providers.apiKeyConfigured': 'API key configured',
'ai.providers.noApiKey': 'No API key',
'ai.providers.configure': 'Configure',
'ai.providers.remove': 'Remove',
'ai.providers.name': 'Display Name',
'ai.providers.name.placeholder': 'e.g. My Provider',
'ai.providers.apiKey': 'API Key',
'ai.providers.apiKey.placeholder': 'Enter API key',
'ai.providers.apiKey.decrypting': 'Decrypting...',
'ai.providers.baseUrl': 'Base URL',
'ai.providers.skipTLSVerify': 'Skip TLS certificate verification (for self-signed certs)',
'ai.providers.defaultModel': 'Default Model',
'ai.providers.defaultModel.placeholder': 'e.g. gpt-4o, claude-sonnet-4-20250514',
'ai.providers.refreshModels': 'Refresh models',
'ai.providers.searchModel': 'Search or type model ID...',
'ai.providers.filterModels': 'Filter models...',
'ai.providers.loadingModels': 'Loading models...',
'ai.providers.noMatchingModels': 'No matching models',
'ai.providers.clickToLoadModels': 'Click to load models',
'ai.providers.showingModels': 'Showing first 100 of {count} models. Type to filter.',
'ai.providers.advancedParams': 'Advanced Parameters',
'ai.providers.advancedParams.hint': 'Leave blank to use provider defaults.',
'ai.providers.advancedParams.maxTokens.placeholder': 'e.g. 4096',
'ai.providers.advancedParams.default': 'Provider default',
// AI Codex
'ai.codex': 'Codex',
'ai.codex.title': 'Codex CLI',
'ai.codex.description': 'Uses codex + codex-acp for ACP protocol streaming. Login with ChatGPT subscription here, or configure an OpenAI provider API key (passed as CODEX_API_KEY).',
'ai.codex.detecting': 'Detecting...',
'ai.codex.notFound': 'Not found',
'ai.codex.awaitingLogin': 'Awaiting login',
'ai.codex.connectedChatGPT': 'Connected via ChatGPT',
'ai.codex.connectedApiKey': 'Connected via API key',
'ai.codex.notConnected': 'Not connected',
'ai.codex.statusUnknown': 'Status unknown',
'ai.codex.path': 'Path:',
'ai.codex.notFoundHint': 'Could not find codex in PATH. Install it or specify the executable path below.',
'ai.codex.customPathPlaceholder': 'e.g. /usr/local/bin/codex',
'ai.codex.check': 'Check',
'ai.codex.openLogin': 'Open Login',
'ai.codex.logout': 'Logout',
'ai.codex.connectChatGPT': 'Connect ChatGPT',
'ai.codex.refreshStatus': 'Refresh Status',
'ai.codex.apiKeyHint': 'Enabled OpenAI provider API key detected. Codex ACP can also authenticate without ChatGPT login.',
// AI Claude Code
'ai.claude.title': 'Claude Code',
'ai.claude.description': "Anthropic's agentic coding assistant. Uses claude-agent-acp for ACP protocol streaming.",
'ai.claude.detecting': 'Detecting...',
'ai.claude.detected': 'Detected',
'ai.claude.notFound': 'Not found',
'ai.claude.path': 'Path:',
'ai.claude.notFoundHint': 'Could not find claude in PATH. Install it or specify the executable path below.',
'ai.claude.customPathPlaceholder': 'e.g. /usr/local/bin/claude',
'ai.claude.check': 'Check',
// AI GitHub Copilot CLI
'ai.copilot.title': 'GitHub Copilot CLI',
'ai.copilot.description': 'Uses GitHub Copilot CLI via ACP over stdio (`copilot --acp --stdio`). Once detected, it can be selected as an external coding agent.',
'ai.copilot.detecting': 'Detecting...',
'ai.copilot.detected': 'Detected',
'ai.copilot.notFound': 'Not found',
'ai.copilot.path': 'Path:',
'ai.copilot.notFoundHint': 'Could not find copilot in PATH. Install it or specify the executable path below.',
'ai.copilot.customPathPlaceholder': 'e.g. /usr/local/bin/copilot',
'ai.copilot.check': 'Check',
// AI Default Agent
'ai.defaultAgent': 'Default Agent',
'ai.defaultAgent.description': 'Agent to use when starting a new AI session',
'ai.defaultAgent.catty': 'Catty (Built-in)',
// AI Chat
'ai.chat.noProvider': 'No AI provider is configured. Go to **Settings → AI → Providers** to add and enable a provider.',
'ai.chat.toolDenied': 'Action was rejected by the user.',
'ai.chat.toolApproved': 'Approved',
'ai.chat.toolApprovalHint': 'Press Enter to approve, Escape to reject',
'ai.chat.approve': 'Approve',
'ai.chat.reject': 'Reject',
'ai.chat.toolLabel': 'Tool',
'ai.chat.targetLabel': 'Target',
'ai.chat.permissionRequired': 'Permission Required',
'ai.chat.permissionDescription': 'The AI agent wants to execute a tool call that requires your approval.',
'ai.chat.commandBlocked': 'This command is blocked by your security policy and cannot be executed.',
'ai.chat.recommendAllow': 'Allow',
'ai.chat.recommendConfirm': 'Confirm',
'ai.chat.recommendDeny': 'Deny',
'ai.chat.exportConversation': 'Export conversation',
'ai.chat.exportAs': 'Export As',
'ai.chat.exportMarkdown': 'Markdown',
'ai.chat.exportJSON': 'JSON',
'ai.chat.exportPlainText': 'Plain Text',
'ai.chat.thinking': 'Thinking',
'ai.chat.thoughtFor': 'Thought for {duration}',
'ai.chat.thought': 'Thought',
'ai.chat.agents': 'Agents',
'ai.chat.detectedOnMachine': 'Detected on this machine',
'ai.chat.rescan': 'Re-scan',
'ai.chat.permObserver': 'Observer',
'ai.chat.permConfirm': 'Confirm',
'ai.chat.permAuto': 'Auto',
'ai.chat.permObserverDesc': 'Read only',
'ai.chat.permConfirmDesc': 'Ask before actions',
'ai.chat.permAutoDesc': 'Execute freely',
'ai.chat.emptyHint': 'Ask about your servers, run commands, or get help with configurations.',
'ai.chat.placeholder': 'Message {agent} — @ to include context, / for commands',
'ai.chat.placeholderDefault': 'Message Catty Agent...',
'ai.chat.noModel': 'No model',
'ai.chat.recent': 'Recent',
'ai.chat.viewAll': 'View All',
'ai.chat.untitled': 'Untitled',
'ai.chat.justNow': 'Just now',
'ai.chat.minutesAgo': '{n}m ago',
'ai.chat.hoursAgo': '{n}h ago',
'ai.chat.daysAgo': '{n}d ago',
'ai.chat.newChat': 'New Chat',
'ai.chat.allSessions': 'All Sessions',
'ai.chat.noSessions': 'No previous sessions',
'ai.chat.retryHint': 'You can retry by sending your message again.',
'ai.chat.approvalTimeout': 'Tool approval timed out after 5 minutes. You can retry by sending your message again.',
'ai.chat.menuHosts': 'Hosts',
'ai.chat.menuContext': 'Context',
'ai.chat.menuFiles': 'Files',
'ai.chat.menuImage': 'Image',
'ai.chat.menuMentionHost': 'Mention Host',
// AI Error
'ai.codex.bridgeError': 'Codex main-process handlers are not loaded yet. Fully restart Netcatty, or restart the Electron dev process, then try again.',
// AI Web Search
'ai.webSearch.title': 'Web Search',
'ai.webSearch.enable': 'Enable Web Search',
'ai.webSearch.enable.description': 'Allow the AI agent to search the web for current information.',
'ai.webSearch.provider': 'Search Provider',
'ai.webSearch.provider.description': 'Choose a web search API provider.',
'ai.webSearch.apiKey': 'API Key',
'ai.webSearch.apiKey.description': 'API key for the selected search provider.',
'ai.webSearch.apiKey.placeholder': 'Enter API key...',
'ai.webSearch.apiHost': 'API Host',
'ai.webSearch.apiHost.description': 'Custom API endpoint. Leave default unless you use a proxy.',
'ai.webSearch.apiHost.searxngDescription': 'URL of your SearXNG instance (required).',
'ai.webSearch.maxResults': 'Max Results',
'ai.webSearch.maxResults.description': 'Maximum number of search results to return (1-20).',
// AI Safety Settings
'ai.safety.title': 'Safety',
'ai.safety.permissionMode': 'Permission Mode',
'ai.safety.permissionMode.description': 'Controls how the AI interacts with your terminals. Observer mode blocks all write operations via MCP Server, enforced for both built-in and ACP agents. Confirm mode is advisory for ACP agents (they control their own tool approval flow).',
'ai.safety.permissionMode.observer': 'Observer - Read only, no actions',
'ai.safety.permissionMode.confirm': 'Confirm - Ask before actions',
'ai.safety.permissionMode.autonomous': 'Autonomous - Execute freely',
'ai.safety.commandTimeout': 'Command Timeout',
'ai.safety.commandTimeout.description': 'Maximum seconds a command can run before being terminated. Applies to both built-in and ACP agents.',
'ai.safety.commandTimeout.unit': 'sec',
'ai.safety.maxIterations': 'Max Iterations',
'ai.safety.maxIterations.description': 'Maximum number of AI tool-use loops to prevent runaway execution. ACP agents may have their own internal iteration limits that take precedence.',
'ai.safety.blocklist': 'Command Blocklist',
'ai.safety.blocklist.description': 'Regex patterns to block dangerous commands. Applies to both built-in and ACP agents via MCP Server.',
'ai.safety.blocklist.placeholder': 'Regex pattern...',
'ai.safety.blocklist.reset': 'Reset to defaults',
'ai.safety.blocklist.add': 'Add pattern',
'ai.safety.note': 'Command Blocklist, Command Timeout, and Observer mode are enforced at the MCP Server level, applying to all agent types. Confirm mode and Max Iterations are fully enforced for the built-in agent; ACP agents may have their own internal controls for these settings.',
};
export default en;