2022 lines
111 KiB
TypeScript
2022 lines
111 KiB
TypeScript
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}"?',
|
||
'confirm.closeBusyTerminal.title': 'Confirm close',
|
||
'confirm.closeBusyTerminal.message': 'Process "{command}" is still running and will be terminated.',
|
||
'confirm.closeBusyTerminal.messageWithMore': 'Process "{command}" and {count} other running process(es) will be terminated.',
|
||
'confirm.closeBusyTerminal.cancel': 'Cancel',
|
||
'confirm.closeBusyTerminal.close': 'Close',
|
||
'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.application.openExternal.failedTitle': 'Cannot open link',
|
||
'settings.application.openExternal.failedBody': 'The link could not be opened in either the system browser or the built-in browser window.',
|
||
'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',
|
||
'settings.vault.showOnlyUngroupedHostsInRoot': 'Only show ungrouped hosts at root',
|
||
'settings.vault.showOnlyUngroupedHostsInRootDesc': 'When enabled, the root host list only shows hosts without a group. Open a group from the sidebar to see grouped hosts.',
|
||
'settings.vault.showSftpTab': 'Show SFTP tab',
|
||
'settings.vault.showSftpTabDesc': 'Display the standalone SFTP view in the top tab bar. When hidden, use the in-session SFTP side panel instead.',
|
||
|
||
// 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. Major UI regions expose a [data-section="..."] attribute you can target — e.g. snippets-panel, host-details-panel, group-details-panel, serial-host-details-panel, ai-chat-panel, vault-sidebar, vault-main, vault-hosts-header, vault-host-list, vault-view, terminal-workspace, terminal-workspace-sidebar, top-tabs.',
|
||
'settings.appearance.customCss.placeholder':
|
||
'/* Examples — use !important to beat Tailwind utility specificity */\n\n/* Make snippet sidebar text larger */\n[data-section="snippets-panel"] {\n font-size: 14px !important;\n}\n\n/* Custom terminal background */\n.terminal { background: #1a1a2e !important; }\n\n/* Tweak global border radius */\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.theme.followApp': 'Follow Application Theme',
|
||
'settings.terminal.theme.followApp.desc': 'Automatically match the terminal background to the current app theme for a seamless look.',
|
||
'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.clearWipesScrollback': '`clear` wipes scrollback',
|
||
'settings.terminal.behavior.clearWipesScrollback.desc':
|
||
'Make `clear` also wipe the scrollback buffer (POSIX default). Disable to keep history visible after `clear`.',
|
||
'settings.terminal.behavior.preserveSelectionOnInput': 'Keep selection while typing',
|
||
'settings.terminal.behavior.preserveSelectionOnInput.desc':
|
||
'Don\'t clear mouse-selected text when typing — useful for selecting a path then pasting it after a command prefix like `sz `.',
|
||
'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.connection.x11Display': 'X11 display',
|
||
'settings.terminal.connection.x11Display.desc': 'Optional local display address for X11 forwarding. Leave empty to use the system default.',
|
||
'settings.terminal.connection.x11Display.placeholder': 'Auto (:0 or DISPLAY)',
|
||
'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.setDisabled': 'Set to disabled',
|
||
'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.inspectFailedTitle': 'Sync paused',
|
||
'sync.autoSync.inspectFailedMessage': 'Could not reach the cloud to check for changes. Auto-sync will retry when data changes or the app is restarted.',
|
||
'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.restoreInProgress': 'A vault restore is in progress in another window. Please wait for it to finish.',
|
||
'sync.autoSync.interruptedApplyTitle': 'Sync paused — previous restore interrupted',
|
||
'sync.autoSync.interruptedApplyMessage': 'A previous restore did not finish cleanly, so the local vault may be inconsistent. Open Settings → Sync & Cloud → Restore and apply a protective backup before auto-sync resumes.',
|
||
'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.autoSync.restoredTitle': 'Vault restored',
|
||
'sync.autoSync.restoredMessage': 'Your vault has been restored from the cloud.',
|
||
'sync.autoSync.keptLocalTitle': 'Kept local vault',
|
||
'sync.autoSync.keptLocalMessage': 'Your empty local vault was kept. Cloud data was not applied.',
|
||
'sync.autoSync.emptyVaultConflict.title': 'Empty Vault Detected',
|
||
'sync.autoSync.emptyVaultConflict.description': 'Your local vault is empty, but the cloud has data. This usually happens after an update or storage reset. What would you like to do?',
|
||
'sync.autoSync.emptyVaultConflict.cloudLabel': 'Cloud',
|
||
'sync.autoSync.emptyVaultConflict.restore': 'Restore from Cloud',
|
||
'sync.autoSync.emptyVaultConflict.restoreDesc': 'Recommended — recover your hosts, keys, and snippets from the cloud backup',
|
||
'sync.autoSync.emptyVaultConflict.keepEmpty': 'Keep Empty',
|
||
'sync.autoSync.emptyVaultConflict.keepEmptyDesc': 'Start fresh with an empty vault',
|
||
'sync.autoSync.emptyVaultConflict.cloudSummary': '{hosts} hosts, {keys} keys, {snippets} snippets, {proxyProfiles} proxies',
|
||
'sync.autoSync.emptyVaultManual': 'Cannot sync: the local vault is empty. Restore from a local backup or enable Force Push in the sync panel first.',
|
||
|
||
'sync.blocked.title': 'Sync paused',
|
||
'sync.blocked.reason.bulkShrink': 'Would delete {lost} of {baseCount} {entityType} from cloud ({percent}% reduction).',
|
||
'sync.blocked.reason.largeShrink': 'Would delete {lost} {entityType} from cloud.',
|
||
'sync.blocked.detail': 'This is usually caused by a degraded local state (keychain failure, partial data load). Restore from a local backup, or force-push if you truly meant to remove these entries.',
|
||
'sync.blocked.restoreButton': 'Restore from local backup',
|
||
'sync.blocked.forcePushButton': 'Force push anyway',
|
||
|
||
'sync.forcePush.title': 'Confirm force push',
|
||
'sync.forcePush.body': 'You are about to remove {lost} {entityType} from the cloud. This cannot be undone. Proceed?',
|
||
'sync.forcePush.confirm': 'Yes, push anyway',
|
||
'sync.forcePush.cancel': 'Cancel',
|
||
|
||
'sync.entityType.hosts': 'hosts',
|
||
'sync.entityType.keys': 'keys',
|
||
'sync.entityType.identities': 'identities',
|
||
'sync.entityType.proxyProfiles': 'proxy profiles',
|
||
'sync.entityType.snippets': 'snippets',
|
||
'sync.entityType.customGroups': 'groups',
|
||
'sync.entityType.snippetPackages': 'snippet packages',
|
||
'sync.entityType.knownHosts': 'known-host entries',
|
||
'sync.entityType.portForwardingRules': 'port-forwarding rules',
|
||
'sync.entityType.groupConfigs': 'group configs',
|
||
|
||
'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.proxies': 'Proxies',
|
||
'vault.nav.portForwarding': 'Port Forwarding',
|
||
'vault.nav.snippets': 'Snippets',
|
||
'vault.nav.knownHosts': 'Known Hosts',
|
||
'vault.nav.logs': 'Logs',
|
||
|
||
'proxyProfiles.action.add': 'Add Proxy',
|
||
'proxyProfiles.search.placeholder': 'Search proxies…',
|
||
'proxyProfiles.section.proxies': 'Proxies',
|
||
'proxyProfiles.count.items': '{count} items',
|
||
'proxyProfiles.empty.title': 'No Proxies',
|
||
'proxyProfiles.empty.desc': 'Create reusable HTTP or SOCKS5 proxies and select them from host details.',
|
||
'proxyProfiles.usage': '{count} linked',
|
||
'proxyProfiles.copyName': '{name} Copy',
|
||
'proxyProfiles.panel.newTitle': 'New Proxy',
|
||
'proxyProfiles.field.name': 'Proxy name',
|
||
'proxyProfiles.error.required': 'Name, host, and port are required.',
|
||
'proxyProfiles.error.port': 'Port must be between 1 and 65535.',
|
||
'proxyProfiles.viewMode': 'Proxy view mode',
|
||
'proxyProfiles.delete.title': 'Delete proxy?',
|
||
'proxyProfiles.delete.desc': 'Deleting "{name}" will unlink it from {count} host or group settings.',
|
||
|
||
'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.retryAction': 'Retry',
|
||
'sftp.transfers.dismissAction': 'Dismiss',
|
||
'sftp.transfers.resizeNameColumn': 'Resize file name column',
|
||
'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.stop': 'Stop',
|
||
'sftp.conflict.action.skip': 'Skip',
|
||
'sftp.conflict.action.keepBoth': 'Keep Both',
|
||
'sftp.conflict.action.duplicate': 'Duplicate',
|
||
'sftp.conflict.action.merge': 'Merge',
|
||
'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.distro.option.cisco': 'Cisco',
|
||
'hostDetails.distro.option.juniper': 'Juniper Networks',
|
||
'hostDetails.distro.option.huawei': 'Huawei',
|
||
'hostDetails.distro.option.hpe': 'HPE / H3C',
|
||
'hostDetails.distro.option.mikrotik': 'MikroTik',
|
||
'hostDetails.distro.option.fortinet': 'Fortinet',
|
||
'hostDetails.distro.option.paloalto': 'Palo Alto Networks',
|
||
'hostDetails.distro.option.zyxel': 'ZyXEL',
|
||
'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.x11Forwarding': 'Forward X11 apps',
|
||
'hostDetails.x11Forwarding.desc': 'Show remote graphical apps on your local desktop when a local X server is running.',
|
||
'hostDetails.section.x11Forwarding': 'X11 Forwarding',
|
||
'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.proxyPanel.savedProxy': 'Saved proxy',
|
||
'hostDetails.proxyPanel.selectSaved': 'Select saved proxy',
|
||
'hostDetails.proxyPanel.customProxy': 'Custom proxy',
|
||
'hostDetails.proxyPanel.missing': 'Missing',
|
||
'hostDetails.proxyPanel.missingSaved': 'Missing saved proxy',
|
||
'hostDetails.proxyPanel.error.required': 'Proxy host and port are required.',
|
||
'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.more': 'More actions',
|
||
'terminal.toolbar.scripts': 'Scripts',
|
||
'terminal.toolbar.library': 'Library',
|
||
'terminal.toolbar.noSnippets': 'No snippets available',
|
||
'terminal.toolbar.terminalSettings': 'Terminal settings',
|
||
'terminal.toolbar.searchTerminal': 'Search terminal',
|
||
'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.pasteSelection': 'Paste Selection',
|
||
'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',
|
||
'terminal.hiddenTheme.title': 'Current hidden theme',
|
||
'terminal.hiddenTheme.desc': 'This theme is hidden from manual picks and will be replaced when you choose another theme.',
|
||
'topTabs.toggleTheme.systemExitTitle': 'System theme is active',
|
||
'topTabs.toggleTheme.systemExitMessage': 'Open Settings to choose a fixed Light or Dark theme.',
|
||
'topTabs.toggleTheme.openSettings': 'Open Settings',
|
||
|
||
// 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.localBackups.title': 'Local Backup History',
|
||
'cloudSync.localBackups.desc': 'Netcatty keeps local restore points before app version changes and before vault restores.',
|
||
'cloudSync.localBackups.retentionTitle': 'Backup Retention',
|
||
'cloudSync.localBackups.retentionDesc': 'Choose how many local backups Netcatty should keep.',
|
||
'cloudSync.localBackups.maxCount': 'Max backups',
|
||
'cloudSync.localBackups.maxSaved': 'Saved backup retention: {count}',
|
||
'cloudSync.localBackups.maxInvalid': 'Please enter a number between 1 and 100.',
|
||
'cloudSync.localBackups.empty': 'No local backups yet.',
|
||
'cloudSync.localBackups.reason.appVersionChange': 'Before app version change',
|
||
'cloudSync.localBackups.reason.beforeRestore': 'Before restore',
|
||
'cloudSync.localBackups.versionChange': '{from} -> {to}',
|
||
'cloudSync.localBackups.counts': '{hosts} hosts, {keys} keys, {snippets} snippets',
|
||
'cloudSync.localBackups.restore': 'Restore',
|
||
'cloudSync.localBackups.restoreSuccess': 'Local backup restored.',
|
||
'cloudSync.localBackups.restoreFailedTitle': 'Restore failed',
|
||
'cloudSync.localBackups.restoreMissing': 'Backup not found.',
|
||
'cloudSync.localBackups.protectiveBackupFailed': 'Safety backup could not be created, so the restore was aborted to protect your current data. Resolve the underlying issue (e.g. keychain access) and try again. Details: {message}',
|
||
'cloudSync.localBackups.restoreConfirmTitle': 'Restore this backup?',
|
||
'cloudSync.localBackups.restoreConfirmDesc': 'Your current hosts, keys, snippets and settings will be replaced with the contents of this backup. A protective snapshot of your current data is taken automatically first.',
|
||
'cloudSync.localBackups.restoreConfirmButton': 'Restore',
|
||
'cloudSync.localBackups.restoreConfirmCancel': 'Cancel',
|
||
'cloudSync.localBackups.unavailableTitle': 'Local backups unavailable',
|
||
'cloudSync.localBackups.unavailableDesc': 'This platform does not expose a secure keychain to Netcatty, so local backups cannot be written safely. Install Netcatty on a system with a supported keychain to enable the local backup history.',
|
||
'cloudSync.localBackups.lockedTitle': 'Master key required',
|
||
'cloudSync.localBackups.lockedDesc': 'Set up or unlock your master key before restoring a backup, so restored credentials remain encrypted.',
|
||
'cloudSync.revisionHistory.viewButton': 'History',
|
||
'cloudSync.revisionHistory.title': 'Vault Version History',
|
||
'cloudSync.revisionHistory.description': 'Browse and restore previous versions of your vault from the Gist revision history.',
|
||
'cloudSync.revisionHistory.empty': 'No revisions found.',
|
||
'cloudSync.revisionHistory.current': 'Current',
|
||
'cloudSync.revisionHistory.revision': 'Revision',
|
||
'cloudSync.revisionHistory.revisionPreview': 'Revision Contents',
|
||
'cloudSync.revisionHistory.device': 'Device',
|
||
'cloudSync.revisionHistory.hosts': 'Hosts',
|
||
'cloudSync.revisionHistory.keys': 'Keys',
|
||
'cloudSync.revisionHistory.snippets': 'Snippets',
|
||
'cloudSync.revisionHistory.identities': 'Identities',
|
||
'cloudSync.revisionHistory.restoreButton': 'Restore This Version',
|
||
'cloudSync.revisionHistory.restored': 'Vault restored from selected revision.',
|
||
'cloudSync.revisionHistory.revisionNotFound': 'Revision not found or does not contain vault data.',
|
||
'cloudSync.revisionHistory.decryptFailed': 'Cannot decrypt this revision. It may have been encrypted with a different master password.',
|
||
'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.browserCancelled': 'Previous browser authorization was cancelled',
|
||
'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',
|
||
'tabs.closeOthers': 'Close Others',
|
||
'tabs.closeToRight': 'Close Tabs to the Right',
|
||
'tabs.closeAll': 'Close All',
|
||
'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.search.noResults.title': 'No matches',
|
||
'snippets.search.noResults.desc': 'No snippets or packages match "{query}". Try a different search term or clear the search to browse.',
|
||
'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',
|
||
'passphrase.remember': 'Remember this passphrase',
|
||
|
||
// Text Editor
|
||
'sftp.editor.wordWrap': 'Word Wrap',
|
||
'sftp.editor.maximize': 'Maximize',
|
||
'sftp.editor.unsavedTitle': 'Unsaved changes',
|
||
'sftp.editor.unsavedMessage': '{fileName} has unsaved changes. Save before closing?',
|
||
'sftp.editor.discardChanges': 'Discard',
|
||
'sftp.editor.saveAndClose': 'Save and close',
|
||
'sftp.editor.quitBlockedByDirty': 'Unsaved editors — please save or discard before quitting',
|
||
|
||
// 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 here, or enable an OpenAI-compatible provider API key and custom endpoint in Settings.',
|
||
'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.connectedCustomConfig': 'Connected via ~/.codex/config.toml',
|
||
'ai.codex.customConfigIncomplete': 'Custom config detected (env var missing)',
|
||
'ai.codex.customConfigHint': 'Using custom provider "{provider}" configured in ~/.codex/config.toml — no ChatGPT login needed.',
|
||
'ai.codex.customConfigMissingEnvKey': 'Warning: {envKey} is not set in your shell environment. Export it (or launch netcatty from a shell that has it) so Codex can authenticate.',
|
||
'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 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.toolAccess.title': 'Tool Access',
|
||
'ai.toolAccess.mode': 'Netcatty Access Mode',
|
||
'ai.toolAccess.description': 'Choose how external ACP agents access Netcatty sessions. MCP exposes the built-in server, while Skills + CLI points agents to the local Netcatty skill and CLI commands.',
|
||
'ai.toolAccess.mode.mcp': 'MCP',
|
||
'ai.toolAccess.mode.skills': 'Skills + CLI',
|
||
'ai.userSkills.title': 'User Skills',
|
||
'ai.userSkills.description': 'Open the Netcatty skills folder to add your own skill directories. Netcatty scans these skills automatically and injects only lightweight indexes unless a skill clearly matches the current request.',
|
||
'ai.userSkills.openFolder': 'Open Skills Folder',
|
||
'ai.userSkills.reload': 'Reload Skills',
|
||
'ai.userSkills.location': 'Location',
|
||
'ai.userSkills.loading': 'Scanning user skills...',
|
||
'ai.userSkills.summary': '{ready} ready, {warnings} warnings',
|
||
'ai.userSkills.empty': 'No user skills found yet. Open the folder to add skill directories with a SKILL.md file.',
|
||
'ai.userSkills.unavailable': 'User skills are unavailable in this environment.',
|
||
'ai.userSkills.status.ready': 'Ready',
|
||
'ai.userSkills.status.warning': 'Warning',
|
||
|
||
// 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.chat.menuUserSkills': 'User Skills',
|
||
|
||
// 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 through Netcatty, 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 through Netcatty execution.',
|
||
'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;
|