程序员阿江(Relakkes) 0e78439f9d Group desktop sessions by project root
The desktop sidebar needed a project-first navigation model that keeps worktree sessions attached to their source project instead of scattering them as separate paths. The UI now renders sessions under project groups with project-level actions and persisted ordering, while the server exposes a logical project root for worktree transcripts.

Constraint: Existing memory directory tree work must remain separate from the session sidebar behavior.

Rejected: Group by raw transcript projectPath | worktree paths fragment the same repository into multiple sidebar projects.

Confidence: high

Scope-risk: moderate

Directive: Keep future sidebar grouping keyed by projectRoot before projectPath so isolated worktrees stay under their source repository.

Tested: cd desktop && bun run test -- src/components/layout/Sidebar.test.tsx

Tested: bun test src/server/__tests__/sessions.test.ts

Tested: git diff --check
2026-05-15 16:01:36 +08:00

1392 lines
83 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

export const en = {
// ─── Common ──────────────────────────────────────
'common.cancel': 'Cancel',
'common.save': 'Save',
'common.delete': 'Delete',
'common.add': 'Add',
'common.run': 'Run',
'common.send': 'Send',
'common.stop': 'Stop',
'common.rename': 'Rename',
'common.retry': 'Retry',
'common.loading': 'Loading...',
'common.select': 'Select',
'common.enable': 'Enable',
'common.disable': 'Disable',
'common.active': 'ACTIVE',
'common.copyFailed': 'Copy failed.',
// ─── Sidebar ──────────────────────────────────────
'sidebar.newSession': 'New session',
'sidebar.scheduled': 'Scheduled',
'sidebar.terminal': 'Terminal',
'sidebar.settings': 'Settings',
'sidebar.searchPlaceholder': 'Search sessions...',
'sidebar.noSessions': 'No sessions yet',
'sidebar.noMatching': 'No matching sessions',
'sidebar.sessionListFailed': 'Session list failed to load',
'sidebar.refreshSessions': 'Refresh sessions',
'sidebar.projects': 'Projects',
'sidebar.projectActions': 'Project actions for {project}',
'sidebar.pinProject': 'Pin Project',
'sidebar.unpinProject': 'Unpin Project',
'sidebar.openInFinder': 'Open in Finder',
'sidebar.openInFinderFailed': 'Could not open the project in Finder.',
'sidebar.openInFinderUnavailable': 'No file manager is available.',
'sidebar.createPermanentWorktree': 'Create Permanent Worktree',
'sidebar.renameProject': 'Rename Project',
'sidebar.archiveSessions': 'Archive Conversations',
'sidebar.removeProject': 'Remove',
'sidebar.newSessionInProject': 'New session in {project}',
'sidebar.showMoreSessions': 'Show {count} more',
'sidebar.showFewerSessions': 'Show fewer',
'sidebar.expandProject': 'Expand {project}',
'sidebar.collapseProject': 'Collapse {project}',
'sidebar.worktree': 'worktree',
'sidebar.missingDir': 'missing dir',
'sidebar.confirmDelete': 'Delete this session? This cannot be undone.',
'sidebar.batchManage': 'Batch manage',
'sidebar.batchSelectedCount': '{count} selected',
'sidebar.batchSelectAll': 'Select all',
'sidebar.batchDeselectAll': 'Deselect all',
'sidebar.batchSelectGroup': 'Select {group}',
'sidebar.batchDeleteSelected': 'Delete selected ({count})',
'sidebar.batchDeleteConfirm': 'Delete {count} sessions? This cannot be undone.',
'sidebar.batchDeleteConfirmBody': 'The following sessions will be deleted:',
'sidebar.batchDeleteMore': '...and {count} more',
'sidebar.batchExit': 'Cancel batch mode',
'sidebar.batchDeleteSucceeded': 'Deleted {count} sessions.',
'sidebar.batchDeleteFailed': '{count} sessions could not be deleted.',
'sidebar.allProjects': 'All projects',
'sidebar.other': 'Other',
'sidebar.timeGroup.today': 'Today',
'sidebar.timeGroup.yesterday': 'Yesterday',
'sidebar.timeGroup.last7days': 'Last 7 days',
'sidebar.timeGroup.last30days': 'Last 30 days',
'sidebar.timeGroup.older': 'Older',
'sidebar.collapse': 'Collapse sidebar',
'sidebar.expand': 'Expand sidebar',
// ─── Title Bar ──────────────────────────────────────
'titlebar.code': 'Code',
'titlebar.terminal': 'Terminal',
'titlebar.history': 'History',
// ─── Open Project ──────────────────────────────────────
'openProject.openProject': 'Open project',
'openProject.openIn': 'Open in {target}',
'openProject.openFailed': 'Could not open project',
// ─── Workspace Panel ───────────────────────────────
'workspace.changedFiles': 'Changed files',
'workspace.allFiles': 'All files',
'workspace.viewTabs': 'Workspace views',
'workspace.previewTabs': 'Preview tabs',
'workspace.filterPlaceholder': 'Filter files...',
'workspace.clearFilter': 'Clear file filter',
'workspace.refresh': 'Refresh workspace',
'workspace.closePanel': 'Close workspace panel',
'workspace.resizePanel': 'Resize workspace panel',
'workspace.closeTab': 'Close tab',
'workspace.preview': 'Preview',
'workspace.previewEmpty': 'Select a file to preview.',
'workspace.notGitRepo': 'Not a git repository.',
'workspace.missingWorkdir': 'Working directory is missing.',
'workspace.loadError': 'Failed to load workspace data.',
'workspace.noChanges': 'No changes',
'workspace.noFiles': 'No files',
'workspace.noMatchingFiles': 'No matching files',
'workspace.previewKind.diff': 'Diff',
'workspace.previewKind.file': 'File',
'workspace.previewState.loading': 'Loading preview...',
'workspace.previewState.binary': 'Binary file preview is unavailable.',
'workspace.previewState.tooLarge': 'File is too large to preview.',
'workspace.previewState.missing': 'File not found.',
'workspace.imagePreviewUnavailable': 'Image preview is unavailable.',
'workspace.previewLineLimit': 'Showing first {count} of {total} loaded lines.',
'workspace.previewAllLines': 'Showing all {total} loaded lines.',
'workspace.showAllLoadedLines': 'Show all loaded lines',
'workspace.collapsePreview': 'Collapse preview',
'workspace.addToChat': 'Add to chat',
'workspace.addSelectionToChat': 'Add to chat',
'workspace.copyPath': 'Copy path',
'workspace.pathCopied': 'Path copied.',
'workspace.localComment': 'Local comment',
'workspace.commentLine': 'Comment line {line}',
'workspace.commentLineTarget': 'Line {line}',
'workspace.commentPlaceholder': 'Describe what should change here...',
'workspace.addCommentToChat': 'Add comment',
// ─── Status Bar ──────────────────────────────────────
'status.connected': 'Connected',
'status.connecting': 'Connecting...',
'status.reconnecting': 'Reconnecting...',
'status.disconnected': 'Disconnected',
// ─── Settings ──────────────────────────────────────
'settings.title': 'Settings',
'settings.tab.providers': 'Providers',
'settings.tab.permissions': 'Permissions',
'settings.tab.activity': 'Token usage',
'settings.tab.general': 'General',
'settings.tab.h5Access': 'H5 Access',
'settings.tab.terminal': 'Terminal',
'settings.tab.skills': 'Skills',
'settings.tab.mcp': 'MCP',
'settings.tab.plugins': 'Plugins',
'settings.tab.diagnostics': 'Diagnostics',
// Settings > Usage
'settings.activity.title': 'Token usage',
'settings.activity.subtitleLoading': 'Based on local Claude Code CLI session transcripts',
'settings.activity.metric.yesterday': 'Yesterday',
'settings.activity.metric.today': 'Today',
'settings.activity.metric.last4': 'Last 4 days',
'settings.activity.metric.last30': '30 days',
'settings.activity.metric.streak': 'Streak',
'settings.activity.metric.bestStreak': 'best {days} days',
'settings.activity.heatmapLabel': 'Token usage by day',
'settings.activity.count.sessionOne': '{count} session',
'settings.activity.count.sessionOther': '{count} sessions',
'settings.activity.count.dayOne': '{count} day',
'settings.activity.count.dayOther': '{count} days',
'settings.activity.weekday.mon': 'Mon',
'settings.activity.weekday.wed': 'Wed',
'settings.activity.weekday.fri': 'Fri',
'settings.activity.selectedDay': 'Selected day',
'settings.activity.sessions': 'Sessions',
'settings.activity.tokens': 'Tokens',
'settings.activity.messages': 'Messages',
'settings.activity.tools': 'Tools',
'settings.activity.less': 'Less',
'settings.activity.more': 'More',
// Settings > Terminal
'settings.terminal.title': 'Terminal',
'settings.terminal.description': 'Run host-machine commands for plugin, skill, and MCP setup. The desktop app includes claude-haha; replace documented claude <args> with claude-haha <args>, for example: claude-haha plugin install ... or claude-haha mcp add ...',
'settings.terminal.clear': 'Clear',
'settings.terminal.restart': 'Restart',
'settings.terminal.windowTitle': 'Host shell',
'settings.terminal.unavailableTitle': 'Desktop runtime required',
'settings.terminal.unavailableBody': 'Open this page in the packaged desktop app to start an interactive terminal.',
'settings.terminal.status.idle': 'Idle',
'settings.terminal.status.starting': 'Starting',
'settings.terminal.status.running': 'Running',
'settings.terminal.status.exited': 'Exited',
'settings.terminal.status.error': 'Error',
'settings.terminal.status.unavailable': 'Unavailable',
'terminal.newTab': 'New Terminal',
'terminal.openInTab': 'Open in Tab',
'terminal.closePanel': 'Close terminal panel',
'terminal.resizePanel': 'Resize terminal panel',
// Settings > Diagnostics
'settings.diagnostics.title': 'Diagnostics',
'settings.diagnostics.description': 'Server and CLI runtime logs for debugging startup, provider, and session failures.',
'settings.diagnostics.refresh': 'Refresh',
'settings.diagnostics.totalSize': 'Log size',
'settings.diagnostics.events': 'Events',
'settings.diagnostics.recentErrors': '24h warnings',
'settings.diagnostics.retention': 'Retention',
'settings.diagnostics.retentionValue': '{days} days / {size}',
'settings.diagnostics.logDirectory': 'Log directory',
'settings.diagnostics.openDirectory': 'Open',
'settings.diagnostics.exportBundle': 'Export Bundle',
'settings.diagnostics.copySummary': 'Copy Error Summary',
'settings.diagnostics.clearLogs': 'Clear Logs',
'settings.diagnostics.recentEvents': 'Recent Events',
'settings.diagnostics.privacyNote': 'Exported diagnostics are sanitized and do not include chat content, file contents, full environment variables, or API keys.',
'settings.diagnostics.noEvents': 'No diagnostic events yet.',
'settings.diagnostics.noRecentErrors': 'No recent warnings or errors.',
'settings.diagnostics.loadFailed': 'Failed to load diagnostics.',
'settings.diagnostics.openFailed': 'Failed to open diagnostics directory.',
'settings.diagnostics.exportFailed': 'Failed to export diagnostics bundle.',
'settings.diagnostics.exported': 'Exported {file}',
'settings.diagnostics.summaryCopied': 'Error summary copied.',
'settings.diagnostics.copyFailed': 'Failed to copy error summary.',
'settings.diagnostics.confirmClear': 'Clear all local diagnostic logs and exported bundles?',
'settings.diagnostics.cleared': 'Diagnostics cleared.',
'settings.diagnostics.clearFailed': 'Failed to clear diagnostics.',
'settings.diagnostics.eventDetails': 'Details',
'settings.diagnostics.doctorTitle': 'Doctor',
'settings.diagnostics.doctorDescription': 'Safe desktop repair for startup and UI state problems.',
'settings.diagnostics.doctorProtectedData': 'Never touches chat history, model config, skills, MCP, IM, or OAuth.',
'settings.diagnostics.doctorSafeKeys': 'Clears only: cc-haha-open-tabs, cc-haha-session-runtime, cc-haha-theme, cc-haha-locale, and cc-haha.persistence.schemaVersion.',
'settings.diagnostics.runDoctor': 'Run Doctor',
'settings.diagnostics.doctorCompleted': 'Doctor completed.',
'settings.diagnostics.doctorPartial': 'Doctor completed with {count} local cleanup issue(s).',
'settings.diagnostics.doctorFailed': 'Doctor failed.',
'settings.diagnostics.doctorResultLocal': 'Cleared {count} safe UI key(s).',
'settings.diagnostics.doctorResultFailedKeys': '{count} key(s) could not be removed.',
'settings.diagnostics.doctorServerRan': 'Server Doctor repair also ran.',
'settings.diagnostics.doctorServerUnavailable': 'Server Doctor was unavailable, so only local repair ran.',
'errorBoundary.title': 'Something went wrong.',
'errorBoundary.description': 'The error was recorded in Diagnostics.',
// Settings > Claude Official Login
'settings.claudeOfficialLogin.intro': 'Using official Claude models requires signing in to your Claude.ai account. Click the button below to open the official Claude login page in your browser; you\'ll be returned here after authorizing.',
'settings.claudeOfficialLogin.loginButton': 'Sign in to Claude',
'settings.claudeOfficialLogin.loginStarting': 'Opening…',
'settings.claudeOfficialLogin.logoutButton': 'Sign out',
'settings.claudeOfficialLogin.logoutProcessing': 'Processing…',
'settings.claudeOfficialLogin.loggedInPrefix': 'Signed in (Claude',
'settings.claudeOfficialLogin.subTypeUnknown': 'Unknown',
'settings.claudeOfficialLogin.errorPrefix': 'Error: ',
'settings.claudeOfficialLogin.openBrowserFailed': 'Failed to open browser; please visit the authorization URL manually.',
// Settings > Providers
'settings.providers.title': 'Providers',
'settings.providers.description': 'Manage API providers for model access.',
'settings.providers.addProvider': 'Add Provider',
'settings.providers.officialName': 'Claude Official',
'settings.providers.officialDesc': 'Anthropic native — no API key required',
'settings.providers.connected': 'Connected ({latency}ms)',
'settings.providers.failed': 'Failed: {error}',
'settings.providers.connectivityOk': '① Connectivity ({latency}ms)',
'settings.providers.connectivityFailed': '① Connectivity failed: {error}',
'settings.providers.proxyOk': '② Proxy pipeline ({latency}ms)',
'settings.providers.proxyFailed': '② Proxy failed: {error}',
'settings.providers.confirmDelete': 'Delete provider "{name}"? This cannot be undone.',
'settings.providers.activate': 'Activate',
'settings.providers.default': 'Default',
'settings.providers.setDefault': 'Set default',
'settings.providers.test': 'Test',
'settings.providers.edit': 'Edit',
'settings.providers.requestFailed': 'Request failed',
'settings.providers.addTitle': 'Add Provider',
'settings.providers.editTitle': 'Edit Provider',
'settings.providers.preset': 'Preset',
'settings.providers.name': 'Name',
'settings.providers.namePlaceholder': 'Provider name',
'settings.providers.notes': 'Notes',
'settings.providers.notesPlaceholder': 'Optional notes...',
'settings.providers.baseUrl': 'Base URL',
'settings.providers.baseUrlPlaceholder': 'https://api.example.com/anthropic',
'settings.providers.apiKey': 'API Key',
'settings.providers.apiKeyKeep': 'API Key (leave blank to keep current)',
'settings.providers.getApiKey': 'Get API Key',
'settings.providers.modelMapping': 'Model Mapping',
'settings.providers.mainModel': 'Main Model',
'settings.providers.haikuModel': 'Haiku Model',
'settings.providers.sonnetModel': 'Sonnet Model',
'settings.providers.opusModel': 'Opus Model',
'settings.providers.sameAsMain': 'Same as main',
'settings.providers.contextSettingsTitle': 'Context and auto-compact',
'settings.providers.contextSettingsDesc': 'Preset limits are applied automatically. Edit only when the provider changes limits or you use a custom model ID.',
'settings.providers.contextSettingsEdit': 'Advanced',
'settings.providers.contextSettingsHide': 'Hide',
'settings.providers.contextSummaryAuto': 'Auto-detect configured models; unknown models use the built-in fallback',
'settings.providers.contextFallbackAuto': 'Unknown models: auto',
'settings.providers.contextFallbackSummary': 'Unknown models: {tokens}',
'settings.providers.modelContextWindows': 'Model context windows',
'settings.providers.mainContextWindow': 'Main model context',
'settings.providers.haikuContextWindow': 'Haiku model context',
'settings.providers.sonnetContextWindow': 'Sonnet model context',
'settings.providers.opusContextWindow': 'Opus model context',
'settings.providers.contextWindowPlaceholder': 'e.g. 200000',
'settings.providers.modelContextWindowsDesc': 'Use each models real context window. Presets are filled automatically; blank values fall back to built-in detection or 200K.',
'settings.providers.modelContextWindowNumberError': 'Enter an integer.',
'settings.providers.modelContextWindowRangeError': 'Must be between 16000 and 10000000.',
'settings.providers.autoCompactWindow': 'Unknown Model Fallback Window',
'settings.providers.autoCompactWindowPlaceholder': 'Optional, e.g. 200000',
'settings.providers.autoCompactWindowDesc': 'Only used for models that cannot be identified; configured model windows take precedence.',
'settings.providers.autoCompactWindowNumberError': 'Enter an integer.',
'settings.providers.autoCompactWindowRangeError': 'Must be between 16000 and 10000000.',
'settings.providers.testConnection': 'Test Connection',
'settings.providers.settingsJson': 'Settings JSON',
'settings.providers.settingsJsonDesc': '~/.claude/cc-haha/settings.json — edit directly, will be written on save.',
'settings.providers.jsonError': 'JSON syntax error: {error}',
'settings.providers.apiFormat': 'API Format',
'settings.providers.apiFormatAnthropic': 'Anthropic Messages (native)',
'settings.providers.apiFormatOpenaiChat': 'OpenAI Chat Completions (proxy)',
'settings.providers.apiFormatOpenaiResponses': 'OpenAI Responses API (proxy)',
'settings.providers.proxyHint': 'Requests will be translated via the local proxy',
'settings.providers.authStrategy': 'Auth Variable',
'settings.providers.authStrategyApiKey': 'API Key (ANTHROPIC_API_KEY)',
'settings.providers.authStrategyApiKeyDesc': 'Direct Anthropic API access using x-api-key.',
'settings.providers.authStrategyAuthToken': 'Bearer Token (ANTHROPIC_AUTH_TOKEN)',
'settings.providers.authStrategyAuthTokenDesc': 'Most third-party Anthropic-compatible services using Authorization Bearer.',
'settings.providers.authStrategyAuthTokenEmptyApiKey': 'Bearer + Empty API_KEY',
'settings.providers.authStrategyAuthTokenEmptyApiKeyDesc': 'OpenRouter/Ollama-style setups that must avoid falling back to an Anthropic API key.',
'settings.providers.authStrategyDualSameToken': 'Write token to both variables',
'settings.providers.authStrategyDualSameTokenDesc': 'Services such as Hugging Face Router that check both variables.',
'settings.providers.authStrategyDualDummy': 'Write dummy to both variables',
'settings.providers.authStrategyDualDummyDesc': 'Local vLLM-compatible services that only need placeholder auth values.',
// Settings > Permissions
'settings.permissions.title': 'Permission Mode',
'settings.permissions.description': 'Controls how tool execution permissions are handled.',
'settings.permissions.default': 'Ask permissions',
'settings.permissions.defaultDesc': 'Ask before executing tools',
'settings.permissions.acceptEdits': 'Accept edits',
'settings.permissions.acceptEditsDesc': 'Auto-approve file edits, ask for others',
'settings.permissions.plan': 'Plan mode',
'settings.permissions.planDesc': 'Think and plan without executing',
'settings.permissions.bypass': 'Bypass all',
'settings.permissions.bypassDesc': 'Skip all permission checks (dangerous)',
// Settings > Adapters
'settings.tab.adapters': 'IM Adapters',
'settings.adapters.description': 'Configure IM adapters to chat with Claude Code via WeChat, DingTalk, Telegram, or Feishu.',
'settings.adapters.telegram': 'Telegram',
'settings.adapters.feishu': 'Feishu',
'settings.adapters.wechat': 'WeChat',
'settings.adapters.dingtalk': 'DingTalk',
'settings.adapters.botToken': 'Bot Token',
'settings.adapters.botTokenPlaceholder': 'Paste token from @BotFather',
'settings.adapters.appId': 'App ID',
'settings.adapters.appIdPlaceholder': 'e.g. cli_xxx',
'settings.adapters.appSecret': 'App Secret',
'settings.adapters.appSecretPlaceholder': 'From Feishu Open Platform',
'settings.adapters.encryptKey': 'Encrypt Key',
'settings.adapters.encryptKeyPlaceholder': 'Optional',
'settings.adapters.verificationToken': 'Verification Token',
'settings.adapters.verificationTokenPlaceholder': 'Optional',
'settings.adapters.allowedUsers': 'Allowed Users',
'settings.adapters.allowedUsersHint': 'Comma-separated. Leave empty to allow paired users only.',
'settings.adapters.tgAllowedUsersPlaceholder': 'e.g. 123456789, 987654321',
'settings.adapters.fsAllowedUsersPlaceholder': 'e.g. ou_xxx, ou_yyy',
'settings.adapters.wcAllowedUsersPlaceholder': 'e.g. wx_user_id_1, wx_user_id_2',
'settings.adapters.dtAllowedUsersPlaceholder': 'e.g. manager001, staff_yyy',
'settings.adapters.defaultProject': 'Default Project',
'settings.adapters.defaultProjectHint': 'Default working directory for new IM sessions. If empty, the bot uses the current user working directory.',
'settings.adapters.streamingCard': 'Streaming Card Mode',
'settings.adapters.streamingCardDesc': 'Real-time card updates for better experience',
'settings.adapters.serverUrl': 'Server URL',
'settings.adapters.serverUrlPlaceholder': 'ws://127.0.0.1:3456',
'settings.adapters.save': 'Save',
'settings.adapters.saved': 'Saved',
'settings.adapters.saving': 'Saving...',
'settings.adapters.startHint': 'After saving, run adapter: cd adapters && bun run {platform}',
'settings.adapters.pairing': 'Pairing',
'settings.adapters.pairingDesc': 'Generate a pairing code and send it to the Bot via IM private chat to bind your identity.',
'settings.adapters.generateCode': 'Generate Code',
'settings.adapters.regenerateCode': 'Regenerate',
'settings.adapters.codeExpired': 'Expired',
'settings.adapters.codeExpiresIn': 'Expires in',
'settings.adapters.minutes': 'min',
'settings.adapters.pairingCodeHint': 'Send this code to the Bot in DingTalk, Feishu, WeChat, or Telegram private chat. WeChat requires QR binding first.',
'settings.adapters.pairedUsers': 'Paired Users',
'settings.adapters.noPairedUsers': 'No paired users yet',
'settings.adapters.unbind': 'Unbind',
'settings.adapters.unbindConfirm': 'Are you sure you want to unbind this user? They will need to re-pair to use the bot.',
'settings.adapters.platform.telegram': 'Telegram',
'settings.adapters.platform.feishu': 'Feishu',
'settings.adapters.platform.wechat': 'WeChat',
'settings.adapters.platform.dingtalk': 'DingTalk',
'settings.adapters.dingtalkQrTitle': 'Bind DingTalk bot with QR',
'settings.adapters.dingtalkQrDesc': 'Scan with the DingTalk mobile app to create and authorize the bot. Client ID / Secret are saved automatically when it succeeds.',
'settings.adapters.dingtalkStartAuth': 'Scan to bind',
'settings.adapters.dingtalkUnbindBot': 'Unbind bot account',
'settings.adapters.dingtalkQrAlt': 'DingTalk authorization QR code',
'settings.adapters.dingtalkWaiting': 'Waiting for DingTalk scan confirmation...',
'settings.adapters.dingtalkBound': 'DingTalk bot is bound.',
'settings.adapters.dingtalkAuthFailed': 'DingTalk QR authorization failed.',
'settings.adapters.dingtalkAuthExpired': 'DingTalk QR authorization expired. Generate a new QR code.',
'settings.adapters.dingtalkUnbindFailed': 'Failed to unbind DingTalk.',
'settings.adapters.dingtalkClientId': 'Client ID',
'settings.adapters.dingtalkClientIdPlaceholder': 'Filled by QR auth, or enter manually',
'settings.adapters.dingtalkClientSecret': 'Client Secret',
'settings.adapters.dingtalkClientSecretPlaceholder': 'Filled by QR auth, or enter manually',
'settings.adapters.dingtalkEndpoint': 'Stream Endpoint',
'settings.adapters.dingtalkEndpointPlaceholder': 'Default https://api.dingtalk.com',
'settings.adapters.dingtalkPermissionCardTemplateId': 'Permission Card Template ID',
'settings.adapters.dingtalkPermissionCardTemplateIdPlaceholder': 'Optional interactive card template ID',
'settings.adapters.dingtalkPermissionCardTemplateIdHint': 'When set, permission requests use a DingTalk interactive card first. Leave empty to use /allow, /always, /deny text approval.',
'settings.adapters.wechatBind': 'Scan to Bind',
'settings.adapters.wechatRebind': 'Rescan',
'settings.adapters.wechatConnected': 'WeChat is bound',
'settings.adapters.wechatNotConnected': 'WeChat is not bound',
'settings.adapters.wechatQrHint': 'Generate a QR code, scan it in WeChat, then confirm. The adapter restarts after binding.',
'settings.adapters.wechatQrAlt': 'WeChat binding QR code',
'settings.adapters.wechatWaiting': 'Waiting for WeChat confirmation...',
'settings.adapters.wechatBindSuccess': 'WeChat bound successfully.',
'settings.adapters.wechatUnbindAccount': 'Unbind WeChat account',
'settings.adapters.wechatUnbound': 'WeChat account unbound.',
'settings.adapters.wechatUnbindFailed': 'Failed to unbind WeChat.',
'settings.adapters.wechatAllowedUsersHint': 'QR binding enables the account only. Users still need to send a pairing code, or you can add allowed WeChat user IDs here.',
// Settings > MCP
'settings.mcp.title': 'MCP servers',
'settings.mcp.description': 'Connect external tools and data sources for Claude Code. Add, edit, reconnect, and disable servers without leaving the desktop app.',
'settings.mcp.addServer': 'Add server',
'settings.mcp.empty': 'No MCP servers configured yet',
'settings.mcp.emptyHint': 'Add a custom stdio, HTTP, or SSE MCP server to start extending tool access.',
'settings.mcp.stats.total': 'Total servers',
'settings.mcp.stats.connected': 'Connected now',
'settings.mcp.stats.attention': 'Need attention',
'settings.mcp.scope.project': 'Project',
'settings.mcp.scope.local': 'Local',
'settings.mcp.scope.user': 'User',
'settings.mcp.scope.plugin': 'Plugin',
'settings.mcp.scopeDesc.local': 'Private to you for one project. Stored in your user config, scoped by the selected project.',
'settings.mcp.scopeDesc.project': 'Shared with the team through the selected projects `.mcp.json`.',
'settings.mcp.scopeDesc.user': 'Available in all projects for your user account.',
'settings.mcp.scope.dynamic': 'Built-in',
'settings.mcp.scope.enterprise': 'Enterprise',
'settings.mcp.scope.claudeai': 'Claude.ai',
'settings.mcp.scope.managed': 'Managed',
'settings.mcp.transport.http': 'Streamable HTTP',
'settings.mcp.globalOnlyHint': 'This page manages only user-global MCP servers for speed. Project-specific MCP will move into the chat slash-command experience.',
'settings.mcp.form.back': 'Back to servers',
'settings.mcp.form.createTitle': 'Connect to a custom MCP',
'settings.mcp.form.createHint': 'Set up a custom MCP server with the fields supported by Claude Code today.',
'settings.mcp.form.editTitle': 'Update {name} MCP',
'settings.mcp.form.editHint': 'Review connection details, save changes, or reconnect this server from the desktop app.',
'settings.mcp.form.transportLocked': 'If you would like to switch MCP server type, uninstall first.',
'settings.mcp.form.uninstall': 'Uninstall',
'settings.mcp.form.reconnect': 'Reconnect',
'settings.mcp.form.save': 'Save',
'settings.mcp.form.name': 'Name',
'settings.mcp.form.namePlaceholder': 'MCP server name',
'settings.mcp.form.scope': 'Config scope',
'settings.mcp.form.transport': 'Transport',
'settings.mcp.form.status': 'Status',
'settings.mcp.form.location': 'Config location',
'settings.mcp.form.rawConfig': 'Raw config',
'settings.mcp.form.command': 'Command to launch',
'settings.mcp.form.commandPlaceholder': 'npx',
'settings.mcp.form.commandHostHint': 'STDIO MCP commands run on the host machine. Install runtimes like Node.js, Python, Bun, or uv yourself and make sure the command is available in PATH.',
'settings.mcp.form.arguments': 'Arguments',
'settings.mcp.form.argumentPlaceholder': 'chrome-devtools-mcp@latest',
'settings.mcp.form.addArgument': 'Add argument',
'settings.mcp.form.environmentVariables': 'Environment variables',
'settings.mcp.form.addEnv': 'Add environment variable',
'settings.mcp.form.keyPlaceholder': 'Key',
'settings.mcp.form.valuePlaceholder': 'Value',
'settings.mcp.form.url': 'URL',
'settings.mcp.form.sseUrl': 'SSE URL',
'settings.mcp.form.urlPlaceholder': 'https://mcp.example.com/mcp',
'settings.mcp.form.headers': 'Headers',
'settings.mcp.form.addHeader': 'Add header',
'settings.mcp.form.oauthClientId': 'OAuth client ID',
'settings.mcp.form.oauthClientIdPlaceholder': 'Optional client ID',
'settings.mcp.form.oauthCallbackPort': 'OAuth callback port',
'settings.mcp.form.oauthCallbackPortPlaceholder': 'Optional fixed callback port',
'settings.mcp.form.headersHelper': 'Headers helper script',
'settings.mcp.form.headersHelperPlaceholder': 'Optional helper command path',
'settings.mcp.form.deleteTitle': 'Delete MCP server',
'settings.mcp.form.cancel': 'Cancel',
'settings.mcp.form.confirmDelete': 'Delete',
'settings.mcp.form.deleteConfirm': 'Delete MCP server "{name}"? This cannot be undone.',
'settings.mcp.form.deleteConfirmBody': 'Delete MCP server "{name}"? This action cannot be undone.',
'settings.mcp.targetProject.title': 'Target project',
'settings.mcp.targetProject.selected': 'Currently viewing local and shared MCP servers for: {path}',
'settings.mcp.targetProject.empty': 'Choose a project to inspect project-private or project-shared MCP servers.',
'settings.mcp.targetProject.emptyWithCurrent': 'Choose a target project. The current active session is: {path}',
'settings.mcp.targetProject.localSelected': 'This server will be private to you inside: {path}',
'settings.mcp.targetProject.localEmpty': 'Choose the project that should receive this private MCP server.',
'settings.mcp.targetProject.projectSelected': 'This server will be shared through: {path}/.mcp.json',
'settings.mcp.targetProject.projectEmpty': 'Choose the project whose `.mcp.json` should receive this shared MCP server.',
'settings.mcp.targetProject.globalTitle': 'Global install target',
'settings.mcp.targetProject.globalHint': 'User scope does not need a target project. It is stored in your global Claude config and is available everywhere.',
'settings.mcp.toast.created': 'Created MCP server "{name}"',
'settings.mcp.toast.saved': 'Saved MCP server "{name}"',
'settings.mcp.toast.deleted': 'Deleted MCP server "{name}"',
'settings.mcp.toast.enabled': 'Enabled MCP server "{name}"',
'settings.mcp.toast.disabled': 'Disabled MCP server "{name}"',
'settings.mcp.toast.reconnected': 'Reconnected MCP server "{name}"',
'settings.mcp.toast.saveFailed': 'Failed to save MCP server',
'settings.mcp.toast.deleteFailed': 'Failed to delete MCP server',
'settings.mcp.toast.toggleFailed': 'Failed to update MCP server state',
'settings.mcp.toast.reconnectFailed': 'Failed to reconnect MCP server',
// Settings > Agents
'settings.tab.agents': 'Agents',
'settings.agents.title': 'Installed Agents',
'settings.agents.description': 'Browse agents available to Claude across built-in, project, and user sources. Use /agents in TUI to inspect active sources and overrides.',
'settings.agents.browserTitle': 'Browse installed agents',
'settings.agents.browserEyebrow': 'Agent Browser',
'settings.agents.entryEyebrow': 'Agent Profile',
'settings.agents.empty': 'No agents available yet.',
'settings.agents.emptyHint': 'Add agent definitions in your Claude settings or project to see them here.',
'settings.agents.model': 'Model',
'settings.agents.tools': 'Tools',
'settings.agents.systemPrompt': 'System Prompt',
'settings.agents.noDescription': 'No description',
'settings.agents.noSystemPrompt': 'No system prompt defined.',
'settings.agents.backToList': 'Back to list',
'settings.agents.agentCount': '{count} agents',
'settings.agents.summary.totalAgents': 'Total agents',
'settings.agents.summary.activeAgents': 'Active agents',
'settings.agents.summary.sources': 'Sources',
'settings.agents.summary.source': 'Source',
'settings.agents.summary.model': 'Model',
'settings.agents.summary.tools': 'Tools',
'settings.agents.summary.status': 'Status',
'settings.agents.groupHint': '{count} agents available from {source}',
'settings.agents.status.active': 'Active',
'settings.agents.status.available': 'Available',
'settings.agents.overriddenBy': 'Overridden by {source}',
'settings.agents.overriddenByShort': 'shadowed by {source}',
'settings.agents.toolCount': '{count} tools',
'settings.agents.noTools': 'No tool restriction',
'settings.agents.promptHint': 'Read the current system prompt and compare how this agent is scoped.',
'settings.agents.source.userSettings': 'User',
'settings.agents.source.projectSettings': 'Project',
'settings.agents.source.localSettings': 'Local',
'settings.agents.source.policySettings': 'Managed',
'settings.agents.source.plugin': 'Plugin',
'settings.agents.source.flagSettings': 'CLI arg',
'settings.agents.source.built-in': 'Built-in',
// Settings > Skills
'settings.skills.title': 'Installed Skills',
'settings.skills.description': 'Skills extend Claude with specialized capabilities. Manage skills in ~/.claude/skills/',
'settings.skills.browserTitle': 'Browse installed skills',
'settings.skills.browserEyebrow': 'Skill Browser',
'settings.skills.browserDescription': 'Inspect bundled, project, and user skills, compare their scope, and open each skill folder to read its docs and source files.',
'settings.skills.entryEyebrow': 'Skill Entry',
'settings.skills.slashCommand': '/slash',
'settings.skills.tokenEstimate': '~{count} tokens',
'settings.skills.tokenEstimateShort': '~{count}',
'settings.skills.summary.totalSkills': 'Total skills',
'settings.skills.summary.totalFiles': 'Files',
'settings.skills.summary.sources': 'Sources',
'settings.skills.summary.tokens': 'Estimated tokens',
'settings.skills.summary.source': 'Source',
'settings.skills.summary.entry': 'Entry',
'settings.skills.groupHint': '{count} skills available from {source}',
'settings.skills.ready': 'Ready',
'settings.skills.unavailable': 'Unavailable',
'settings.skills.empty': 'No skills installed',
'settings.skills.emptyHint': 'Add skills to ~/.claude/skills/ to get started',
'settings.skills.back': 'Back to list',
'settings.skills.files': 'files',
'settings.skills.entryFile': 'entry file',
'settings.skills.metaTitle': 'Skill metadata',
'settings.skills.filesPanel': 'Files',
'settings.skills.filesPanelHint': 'Browse the entry file and supporting implementation files.',
'settings.skills.readingMode': 'Viewing in {mode}',
'settings.skills.docMode': 'document mode',
'settings.skills.codeMode': 'code mode',
'settings.skills.source.user': 'User',
'settings.skills.source.project': 'Project',
'settings.skills.source.plugin': 'Plugin',
'settings.skills.source.mcp': 'MCP',
'settings.skills.source.bundled': 'Built-in',
// Settings > Memory
'settings.tab.memory': 'Memory',
'settings.memory.title': 'Project Memory',
'settings.memory.description': 'Inspect and edit the Markdown memory files Claude writes for each project. These files are stored under ~/.claude/projects/<project>/memory/ and are loaded by the CLI runtime.',
'settings.memory.refresh': 'Refresh',
'settings.memory.projects': 'Projects',
'settings.memory.files': 'Memory files',
'settings.memory.resourceManager': 'Resource manager',
'settings.memory.editor': 'Editor',
'settings.memory.preview': 'Preview',
'settings.memory.rendered': 'Rendered',
'settings.memory.emptyProjects': 'No memory projects found.',
'settings.memory.emptyFiles': 'No memory files found yet.',
'settings.memory.selectFile': 'Select a memory file.',
'settings.memory.selectProject': 'Select a project.',
'settings.memory.noFileSelected': 'No file selected',
'settings.memory.current': 'Current',
'settings.memory.indexFile': 'Index',
'settings.memory.missing': 'Missing',
'settings.memory.fileCount': '{count} files',
'settings.memory.unsaved': 'Unsaved',
'settings.memory.saved': 'Saved',
'settings.memory.revert': 'Revert',
'settings.memory.projectSearchPlaceholder': 'Search projects by path...',
'settings.memory.fileSearchPlaceholder': 'Search memory files...',
'settings.memory.resourceSearchPlaceholder': 'Search projects or memory files...',
'settings.memory.noProjectMatches': 'No projects match this search.',
'settings.memory.noFileMatches': 'No memory files match this search.',
'settings.memory.clearSearch': 'Clear search',
'settings.memory.toggleFolder': 'Toggle {name}',
// Settings > Plugins
'settings.plugins.title': 'Installed Plugins',
'settings.plugins.description': 'Inspect installed plugins, see their health, and apply changes to the desktop runtime.',
'settings.plugins.browserTitle': 'Browse installed plugins',
'settings.plugins.browserEyebrow': 'Plugin Manager',
'settings.plugins.browserDescription': 'Plugins bundle skills, agents, hooks, MCP servers, and language tooling. This view keeps the desktop surface focused on installed plugins, health, and apply-to-runtime feedback.',
'settings.plugins.entryEyebrow': 'Plugin Detail',
'settings.plugins.summary.total': 'Total plugins',
'settings.plugins.summary.enabled': 'Enabled',
'settings.plugins.summary.attention': 'Needs attention',
'settings.plugins.summary.marketplaces': 'Marketplaces',
'settings.plugins.summary.skills': 'Skills',
'settings.plugins.summary.agents': 'Agents',
'settings.plugins.summary.mcp': 'MCP',
'settings.plugins.summary.hooks': 'Hooks',
'settings.plugins.group.attention': 'Needs attention',
'settings.plugins.group.enabled': 'Enabled',
'settings.plugins.group.disabled': 'Disabled',
'settings.plugins.groupHint': '{count} plugins in this section',
'settings.plugins.refresh': 'Refresh',
'settings.plugins.apply': 'Apply changes',
'settings.plugins.applyHint': 'Enable, disable, and update changes become active after applying them to the current desktop runtime.',
'settings.plugins.lastReload': 'Last apply: {enabled} active plugins, {skills} plugin skills, {errors} errors.',
'settings.plugins.reloadToast': 'Applied plugin changes: {enabled} active plugins, {skills} skills, {errors} errors.',
'settings.plugins.marketplacesTitle': 'Known marketplaces',
'settings.plugins.marketplacesHint': 'Read-only summary of marketplace sources already configured for this machine.',
'settings.plugins.marketplaceAutoUpdateOn': 'Auto-update on',
'settings.plugins.marketplaceAutoUpdateOff': 'Auto-update off',
'settings.plugins.marketplaceInstalledCount': '{count} installed',
'settings.plugins.marketplaceUpdatedAt': 'Updated {value}',
'settings.plugins.status.enabled': 'Enabled',
'settings.plugins.status.disabled': 'Disabled',
'settings.plugins.status.attention': 'Attention',
'settings.plugins.scope.user': 'User',
'settings.plugins.scope.project': 'Project',
'settings.plugins.scope.local': 'Local',
'settings.plugins.scope.managed': 'Managed',
'settings.plugins.scope.builtin': 'Built-in',
'settings.plugins.empty': 'No plugins installed',
'settings.plugins.emptyHint': 'Install plugins from Claude Code to manage them here.',
'settings.plugins.back': 'Back to list',
'settings.plugins.noDescription': 'No description available for this plugin.',
'settings.plugins.errorCount': '{count} errors',
'settings.plugins.enable': 'Enable',
'settings.plugins.disable': 'Disable',
'settings.plugins.update': 'Update',
'settings.plugins.uninstall': 'Uninstall',
'settings.plugins.confirmUninstall': 'Uninstall plugin "{name}"? This removes the installed copy for the selected scope.',
'settings.plugins.author': 'Author: {value}',
'settings.plugins.projectPath': 'Project: {value}',
'settings.plugins.installPath': 'Installed at: {value}',
'settings.plugins.managedHint': 'This plugin is managed by policy and cannot be changed from the desktop app.',
'settings.plugins.builtinHint': 'Built-in plugins can be reloaded here, but install and uninstall actions are not exposed.',
'settings.plugins.errorsTitle': 'Plugin errors',
'settings.plugins.capabilitiesTitle': 'Bundled capabilities',
'settings.plugins.capabilitiesHint': 'Capabilities exposed by this plugin after loading its manifest and runtime integrations.',
'settings.plugins.sharedNavigationDisabled': 'Enable this plugin and apply changes before opening its skills, agents, or MCP entries in the shared management pages.',
'settings.plugins.capabilityEmpty': 'None exposed',
'settings.plugins.capability.skills': '{count} skills',
'settings.plugins.capability.agents': '{count} agents',
'settings.plugins.capability.mcpServers': '{count} MCP servers',
'settings.plugins.capabilityLabel.skills': 'Skills',
'settings.plugins.capabilityLabel.commands': 'Commands',
'settings.plugins.capabilityLabel.agents': 'Agents',
'settings.plugins.capabilityLabel.hooks': 'Hooks',
'settings.plugins.capabilityLabel.mcpServers': 'MCP servers',
'settings.plugins.capabilityLabel.lspServers': 'LSP servers',
// Settings > About
'settings.tab.about': 'About',
'settings.about.version': 'Version',
'settings.about.changelog': 'Release Notes',
'settings.about.repo': 'GitHub Repository',
'settings.about.starHint': 'If this project helps you, consider giving it a Star',
'settings.about.feedback': 'Report an Issue',
'settings.about.feedbackDesc': 'Open a GitHub Issue for bugs or usage questions',
'settings.about.author': 'Author',
'settings.about.socialMedia': 'Social Media',
'settings.about.updates': 'App Updates',
'settings.about.updatesDesc': 'Check GitHub Releases, download the installer, and relaunch after install.',
// Settings > Computer Use
'settings.tab.computerUse': 'Computer Use',
'settings.computerUse.title': 'Computer Use',
'settings.computerUse.description': 'Allow Claude to take screenshots, click, type, and control your computer. Requires Python 3. On macOS, accessibility permissions are also needed.',
'settings.computerUse.enabledToggle': 'Enabled',
'settings.computerUse.disabledHint': 'Computer Use is off. New sessions will not inject the computer-use MCP server or expose desktop-control tools to the Coding Agent.',
'settings.computerUse.notSupported': 'Computer Use is only supported on macOS and Windows.',
'settings.computerUse.python': 'Python 3',
'settings.computerUse.pythonNotFound': 'Not installed. Please install Python 3 first.',
'settings.computerUse.pythonFound': 'Installed',
'settings.computerUse.pythonCustomInvalid': 'Custom interpreter unavailable',
'settings.computerUse.pythonPathLabel': 'Python Interpreter Path',
'settings.computerUse.pythonPathPlaceholder': 'Auto-detect, or choose python.exe / python3',
'settings.computerUse.pythonPathHint': 'Leave empty to auto-detect. Choose the Python executable from conda, pyenv, or another custom environment to prefer it for runtime setup.',
'settings.computerUse.pythonPathBrowse': 'Browse',
'settings.computerUse.pythonPathSave': 'Apply',
'settings.computerUse.pythonPathAuto': 'Auto',
'settings.computerUse.pythonPathSaved': 'Saved. Rechecks will prefer this interpreter.',
'settings.computerUse.pythonPathSaveFailed': 'Save failed. Try again.',
'settings.computerUse.pythonPathDialogTitle': 'Select Python Interpreter',
'settings.computerUse.pythonPathDialogFailed': 'Could not open the file picker. Paste the path manually.',
'settings.computerUse.venv': 'Virtual Environment',
'settings.computerUse.venvReady': 'Ready',
'settings.computerUse.venvNotReady': 'Not created',
'settings.computerUse.deps': 'Dependencies',
'settings.computerUse.depsReady': 'Installed',
'settings.computerUse.depsNotReady': 'Not installed',
'settings.computerUse.accessibility': 'Accessibility Permission',
'settings.computerUse.screenRecording': 'Screen Recording Permission',
'settings.computerUse.permGranted': 'Granted',
'settings.computerUse.permDenied': 'Denied — open System Settings > Privacy & Security to grant',
'settings.computerUse.permUnknown': 'Setup environment first to check',
'settings.computerUse.permScreenRecordingUnknownSoft': 'Auto-detection can be unreliable here; if System Settings already shows it enabled, Computer Use can usually proceed',
'settings.computerUse.permScreenRecordingManual': 'Cannot auto-detect — please verify in System Settings',
'settings.computerUse.setupBtn': 'Install Environment',
'settings.computerUse.setupRunning': 'Installing...',
'settings.computerUse.setupSuccess': 'Environment setup complete!',
'settings.computerUse.setupFail': 'Setup failed',
'settings.computerUse.allReady': 'All checks passed. Computer Use is ready.',
'settings.computerUse.downloadPython': 'Download Python 3',
'settings.computerUse.recheckBtn': 'Recheck Status',
'settings.computerUse.requirementsLabel': 'Required packages',
'settings.computerUse.appsTitle': 'Authorized Apps',
'settings.computerUse.appsDescription': 'Pre-authorize apps for Computer Use. Authorized apps can be controlled by Claude without runtime prompts.',
'settings.computerUse.appsLoading': 'Loading installed apps...',
'settings.computerUse.appsEmpty': 'No installed apps found. Please setup the environment first.',
'settings.computerUse.appsSearch': 'Search apps...',
'settings.computerUse.appsSaved': 'Saved',
'settings.computerUse.openAccessibility': 'Open Accessibility Settings',
'settings.computerUse.openScreenRecording': 'Open Screen Recording Settings',
'settings.computerUse.permRestartHint': 'After granting, restart the app for it to take effect.',
'settings.computerUse.flagClipboard': 'Clipboard Access',
'settings.computerUse.flagSystemKeys': 'System Key Combos',
// Settings > General
'settings.general.appearanceTitle': 'Appearance',
'settings.general.appearanceDescription': 'Switch between the warm classic workspace, dark workspace, and a pure white workspace.',
'settings.general.appearance.light': 'Warm Classic',
'settings.general.appearance.dark': 'Dark',
'settings.general.appearance.white': 'Pure White',
'settings.general.languageTitle': 'Language',
'settings.general.languageDescription': 'Choose the display language for the application.',
'settings.general.responseLangTitle': 'Response Language',
'settings.general.responseLangDescription': 'Instruct Claude to always respond in a specific language.',
'settings.general.responseLangDefault': 'Default (English)',
'settings.general.effortTitle': 'Effort Level',
'settings.general.effortDescription': 'Controls how much computation the model uses.',
'settings.general.effort.low': 'Low',
'settings.general.effort.medium': 'Medium',
'settings.general.effort.high': 'High',
'settings.general.effort.max': 'Max',
'settings.general.thinkingTitle': 'Thinking Mode',
'settings.general.thinkingDescription': 'Controls whether new sessions start with model thinking enabled. When off, compatible providers such as DeepSeek receive an explicit non-thinking parameter.',
'settings.general.thinkingEnabled': 'Enable thinking mode',
'settings.general.thinkingHint': 'Turn this off to start new sessions with --thinking disabled; useful for DeepSeek V4 Flash/Pro and other non-thinking workflows.',
'settings.general.notificationsTitle': 'System Notifications',
'settings.general.notificationsDescription': 'Use native OS notifications for permission prompts, agent replies, and scheduled task results.',
'settings.general.notificationsEnabled': 'Enable system notifications',
'settings.general.notificationsHintOn': 'When enabled, the app will request notification permission and use the OS notification center.',
'settings.general.notificationsHintOff': 'When disabled, permission prompts, agent replies, and scheduled tasks will not send desktop notifications.',
'settings.general.notificationsStatus': 'Permission',
'settings.general.notificationsStatusGranted': 'Granted',
'settings.general.notificationsStatusDenied': 'Blocked by system settings',
'settings.general.notificationsStatusDefault': 'Not requested',
'settings.general.notificationsStatusUnsupported': 'Unavailable in this environment',
'settings.general.notificationsAuthorize': 'Authorize',
'settings.general.notificationsOpenSettings': 'Open Settings',
'settings.general.notificationsTestTitle': 'Claude Code Haha notifications are enabled',
'settings.general.notificationsTestBody': 'Permission prompts and completed agent replies will now use system notifications.',
'settings.general.h5AccessTitle': 'H5 Access',
'settings.general.h5AccessDescription': 'Expose the desktop H5 app on your local network. Phones connect with a QR link that includes a short-lived H5 token.',
'settings.general.h5AccessEnabled': 'Enable H5 access',
'settings.general.h5AccessEnabledHint': 'The desktop server listens on the LAN address and allows access to desktop sessions.',
'settings.general.h5AccessStatusEnabled': 'Enabled',
'settings.general.h5AccessTokenPreview': 'Token preview',
'settings.general.h5AccessDisabledValue': 'Disabled',
'settings.general.h5AccessDisable': 'Disable',
'settings.general.h5AccessGenerateToken': 'Generate token',
'settings.general.h5AccessRegenerate': 'Regenerate token',
'settings.general.h5AccessGeneratedToken': 'Generated token',
'settings.general.h5AccessGeneratedTokenHint': 'Shown once. Copy it now and store it like a password.',
'settings.general.h5AccessShowToken': 'Show token',
'settings.general.h5AccessCopy': 'Copy',
'settings.general.h5AccessCopyUrl': 'Copy H5 URL',
'settings.general.h5AccessCopyLaunchUrl': 'Copy QR link',
'settings.general.h5AccessUrlCopied': 'H5 URL copied.',
'settings.general.h5AccessLaunchUrlCopied': 'QR link copied.',
'settings.general.h5AccessHideToken': 'Hide token',
'settings.general.h5AccessTokenNotAvailable': 'Regenerate to show a new token.',
'settings.general.h5AccessPublicUrl': 'Public URL',
'settings.general.h5AccessPublicUrlPlaceholder': 'https://chat.example.com',
'settings.general.h5AccessAllowedOrigins': 'Allowed origins',
'settings.general.h5AccessAllowedOriginsPlaceholder': 'https://chat.example.com, https://phone.example',
'settings.general.h5AccessOriginsHint': 'Enter one origin per line or separate multiple origins with commas.',
'settings.general.h5AccessOpenHint': 'Leave blank to use the detected LAN URL. Set this only when you expose H5 through a stable address.',
'settings.general.h5AccessSave': 'Save H5 settings',
'settings.general.h5AccessUrl': 'H5 URL',
'settings.general.h5AccessQrTitle': 'Phone connection',
'settings.general.h5AccessQrHint': 'Scan to open H5 with the token already filled in.',
'settings.general.h5AccessQrRefreshHint': 'Click Generate token to create a QR link that can be scanned.',
'settings.general.h5AccessQrEmptyHint': 'Generate a token to create the QR code.',
'settings.general.h5AccessQrAlt': 'H5 access QR code',
'settings.general.h5AccessSafetyNote': 'Only enable this on trusted networks. Anyone with the QR link can reach the desktop capabilities exposed by H5.',
'settings.general.h5AccessConfirmTitle': 'Enable LAN H5 access?',
'settings.general.h5AccessConfirmBody': 'This will expose the desktop H5 app on your LAN address and port. Devices with the QR token can access desktop sessions and related controls. Continue only on a trusted network.',
'settings.general.h5AccessConfirmEnable': 'Enable H5 access',
'settings.general.h5AccessError': 'Failed to update H5 access settings.',
'settings.general.webFetchPreflightTitle': 'WebFetch Preflight',
'settings.general.webFetchPreflightDescription': 'Desktop sessions skip Claude\'s domain preflight by default to avoid false failures on third-party providers and restricted networks.',
'settings.general.webFetchPreflightEnabled': 'Skip WebFetch domain preflight',
'settings.general.webFetchPreflightHint': 'Turn this off only if you explicitly want to restore the upstream safety preflight before each WebFetch request.',
'settings.general.webSearchTitle': 'WebSearch',
'settings.general.webSearchDescription': 'Choose how agent web search is resolved across official Claude, third-party providers, and local fallback keys.',
'settings.general.webSearch.mode.auto': 'Auto',
'settings.general.webSearch.mode.tavily': 'Tavily',
'settings.general.webSearch.mode.brave': 'Brave',
'settings.general.webSearch.mode.anthropic': 'Claude',
'settings.general.webSearch.mode.disabled': 'Off',
'settings.general.webSearchTavilyKey': 'Tavily API key',
'settings.general.webSearchBraveKey': 'Brave Search API key',
'settings.general.webSearchBravePlaceholder': 'Brave Search token',
'settings.general.webSearchGetApiKey': 'Get API key',
'settings.general.webSearchTavilyApiKeyLink': 'Get Tavily API key',
'settings.general.webSearchBraveApiKeyLink': 'Get Brave Search API key',
'settings.general.webSearchTavilyFreeHint': 'Create an account and copy a key; the free tier includes 1000 credits.',
'settings.general.webSearchBraveFreeHint': 'Create an account to generate a Search API key with free usage for testing.',
'settings.general.webSearchHint': 'Auto uses native Claude web search for Claude model names, then falls back to Tavily and Brave keys.',
'settings.general.webSearchSave': 'Save',
'settings.general.uiZoom': 'UI Zoom',
'settings.general.uiZoomDescription': 'Adjust the size of the entire interface.',
'settings.general.uiZoomShortcutHint': 'Shortcuts are faster:',
'settings.general.uiZoomShortcutMac': 'macOS',
'settings.general.uiZoomShortcutWindows': 'Windows / Linux',
'settings.general.uiZoomShortcutResetHint': '0 resets zoom to 100%.',
'settings.general.uiZoomReset': 'Reset UI zoom to 100%',
// ─── Empty Session ──────────────────────────────────────
'empty.title': 'New session',
'empty.subtitle': 'Start a fresh coding session. Claude is ready to help you build, debug, and architect your project.',
'empty.placeholder': 'Ask anything...',
'empty.addFiles': 'Add files or photos',
'empty.slashCommands': 'Slash commands',
'empty.failedToCreate': 'Failed to create session',
'empty.createError.workdirMissing': 'The project folder is missing or is not a directory. Pick an existing project and try again.',
'empty.createError.notGit': 'This project is not a Git repository, so branch launch is unavailable. Start in the current folder or pick a Git project.',
'empty.createError.branchNotFound': 'The selected branch no longer exists. Refresh the project context and choose another branch.',
'empty.createError.dirtyWorktree': 'Current project has uncommitted changes. Direct branch switching was blocked; enable "Isolated worktree" or commit/stash your changes first.',
'empty.createError.branchCheckedOut': 'That branch is already checked out in another worktree. Enable "Isolated worktree" or choose a different branch.',
'empty.createError.worktreeCreateFailed': 'Could not create the isolated worktree. Check that Git can write to this repository, then try again. Detail: {detail}',
'empty.createError.switchFailed': 'Could not switch the current project branch. Check the Git error, keep your changes safe, then try again. Detail: {detail}',
'empty.createError.contextFailed': 'Could not inspect this Git project. Check the repository state and try again.',
// ─── Repository Launch Controls ──────────────────────────────────────
'repoLaunch.selectBranch': 'Select branch',
'repoLaunch.searchBranch': 'Search branches',
'repoLaunch.noBranch': 'No branch',
'repoLaunch.noBranchMatch': 'No matching branches',
'repoLaunch.currentBranch': 'Current branch',
'repoLaunch.localBranch': 'Local branch',
'repoLaunch.remoteBranch': 'Remote branch',
'repoLaunch.checkedOut': 'Checked out in another worktree',
'repoLaunch.worktreeCurrent': 'Current worktree',
'repoLaunch.worktreeIsolated': 'Isolated worktree',
'repoLaunch.selectWorktree': 'Select worktree mode',
'repoLaunch.missingWorkdir': 'Working directory is missing.',
'repoLaunch.dirtyWarning': 'Uncommitted changes detected. Direct switching may be blocked; use isolated worktree to continue without touching this folder.',
'repoLaunch.checkedOutWarning': 'Selected branch is already checked out in another worktree. Direct launch may be blocked by Git; use "Isolated worktree" to avoid changing directories.',
// ─── Chat Input ──────────────────────────────────────
'chat.placeholder': 'Ask Claude to edit, debug or explain...',
'chat.placeholderMissing': 'This session points to a missing workspace. Create a new session or pick another project.',
'chat.addFiles': 'Add files or photos',
'chat.workspaceReferencesOnly': 'Added {count} workspace references',
'chat.contextReferencesOnly': 'Added {count} references',
'chat.addSelectionToChat': 'Add to chat',
'chat.userMessageReference': 'User message',
'chat.assistantMessageReference': 'Assistant message',
'chat.slashCommands': 'Slash commands',
'slash.mcp.title': 'Available MCP tools',
'slash.mcp.subtitle': 'Global and current-project MCP servers available in this chat context.',
'slash.mcp.subtitleWithProject': 'Showing global plus project MCP for: {path}',
'slash.mcp.emptyTitle': 'No MCP servers available',
'slash.mcp.emptyBody': 'No global or project MCP servers are available for this chat context.',
'slash.mcp.projectBadge': 'Project: {name}',
'slash.skills.title': 'Available skills',
'slash.skills.subtitle': 'User-invocable skills available in the current context.',
'slash.skills.subtitleWithProject': 'Showing skills for: {path}',
'slash.skills.emptyTitle': 'No skills available',
'slash.skills.emptyBody': 'No user-invocable skills were found for this context.',
'slash.plugins.title': 'Plugins',
'slash.plugins.subtitle': 'Plugin management will move into this slash-command surface.',
'slash.plugins.emptyTitle': 'Plugins panel coming soon',
'slash.plugins.emptyBody': 'This shared slash-command panel is wired up now; plugin data will be connected next.',
'slash.help.title': 'Slash commands',
'slash.help.subtitle': 'Run agent workflows, inspect session state, or open desktop panels.',
'slash.help.group.context': 'Context',
'slash.help.group.project': 'Project',
'slash.help.group.desktop': 'Desktop',
'slash.help.group.more': 'More',
'slash.help.moreAvailable': '{count} more commands available. Type / to search the full command list.',
'slash.inspector.title': 'Session inspector',
'slash.inspector.close': 'Close session inspector',
'slash.inspector.loading': 'Loading session data',
'slash.inspector.error.noActiveSession': 'No active session selected.',
'slash.inspector.error.unavailable': 'Session inspector data is unavailable. Restart the desktop server so /api/sessions/:id/inspection is loaded.',
'slash.inspector.tab.status': 'Status',
'slash.inspector.tab.usage': 'Usage',
'slash.inspector.tab.context': 'Context',
'slash.inspector.status.cliStatus': 'CLI Status',
'slash.inspector.status.running': 'Running',
'slash.inspector.status.notRunning': 'Not running',
'slash.inspector.status.activeModel': 'Active Model',
'slash.inspector.status.unknown': 'Unknown',
'slash.inspector.status.mcpConnections': 'MCP Connections',
'slash.inspector.status.connected': 'connected',
'slash.inspector.status.failed': 'failed',
'slash.inspector.status.registeredTools': 'Registered Tools',
'slash.inspector.status.commands': 'commands',
'slash.inspector.status.sessionMetadata': 'Session metadata',
'slash.inspector.status.version': 'Version',
'slash.inspector.status.sessionId': 'Session ID',
'slash.inspector.status.workingDirectory': 'Working Directory',
'slash.inspector.status.permissionMode': 'Permission Mode',
'slash.inspector.status.authToken': 'Auth Token',
'slash.inspector.status.outputStyle': 'Output Style',
'slash.inspector.status.default': 'Default',
'slash.inspector.status.mcpServers': 'MCP servers',
'slash.inspector.status.refresh': 'Refresh',
'slash.inspector.status.contextWindow': 'Context window',
'slash.inspector.usage.emptyTitle': 'No usage data yet',
'slash.inspector.usage.emptyBody': 'Usage appears after the CLI session starts and completes at least one turn.',
'slash.inspector.usage.contextSnapshotNotice': 'Showing token usage from the current context snapshot. Usage updates dynamically as context is fetched.',
'slash.inspector.usage.transcriptNotice': 'Showing usage reconstructed from the session transcript. API duration is only available for the currently running CLI process.',
'slash.inspector.usage.unknownCost': 'Costs may be inaccurate because one or more models have unknown pricing.',
'slash.inspector.usage.totalCost': 'Total cost',
'slash.inspector.usage.source': 'Source',
'slash.inspector.usage.source.contextSnapshot': 'Context snapshot',
'slash.inspector.usage.source.transcript': 'Transcript',
'slash.inspector.usage.source.currentProcess': 'Current process',
'slash.inspector.usage.apiDuration': 'API duration',
'slash.inspector.usage.wallDuration': 'Wall duration',
'slash.inspector.usage.usageSpan': 'Usage span',
'slash.inspector.usage.codeChanges': 'Code changes',
'slash.inspector.usage.input': 'Input',
'slash.inspector.usage.output': 'Output',
'slash.inspector.usage.cacheReadWrite': 'Cache read / write',
'slash.inspector.usage.webSearch': 'Web search',
'slash.inspector.usage.byModel': 'Usage by Model',
'slash.inspector.usage.tokens': 'Tokens',
'slash.inspector.usage.noModelTitle': 'No model usage',
'slash.inspector.usage.noModelBody': 'Token usage will appear here after a model response is recorded.',
'slash.inspector.context.loading': 'Loading context data',
'slash.inspector.context.emptyTitle': 'No context data yet',
'slash.inspector.context.emptyBody': 'Context usage requires an active CLI session.',
'slash.inspector.context.windowUsage': 'Context window usage',
'slash.inspector.context.used': 'used',
'slash.inspector.context.free': 'Free',
'slash.inspector.context.messages': 'Messages',
'slash.inspector.context.assistant': 'assistant',
'slash.inspector.context.toolResults': 'Tool results',
'slash.inspector.context.context': 'Context',
'slash.inspector.context.categoryTitle': 'Estimated usage by category',
'slash.inspector.context.noCategoriesTitle': 'No context categories',
'slash.inspector.context.noCategoriesBody': 'Context categories will appear after the CLI reports context analysis.',
'slash.inspector.context.memoryFiles': 'Memory files',
'slash.inspector.context.noMemoryFiles': 'No memory files are loaded in this session.',
'slash.inspector.context.openMemory': 'Open Memory',
'contextIndicator.ariaLabel': 'Context usage {percent}',
'contextIndicator.pendingAria': 'Context usage not calculated',
'contextIndicator.loadingAria': 'Context usage loading',
'contextIndicator.unavailableAria': 'Context usage unavailable',
'contextIndicator.title': 'Context',
'contextIndicator.modelUnknown': 'Unknown model',
'contextIndicator.used': 'Used',
'contextIndicator.free': 'Free',
'contextIndicator.window': 'Window',
'contextIndicator.loading': 'Loading context usage...',
'contextIndicator.pendingDetail': 'Context usage will be calculated after the session starts.',
'contextIndicator.unavailable': 'n/a',
'contextIndicator.unavailableDetail': 'Context usage is unavailable for this session.',
'contextIndicator.updatedUnknown': 'Not refreshed yet',
'contextIndicator.updatedNow': 'Updated just now',
'contextIndicator.updatedMinutes': 'Updated {count}m ago',
'contextIndicator.estimate': 'Estimate',
'chat.navigate': 'navigate',
'chat.select': 'select',
'chat.dismiss': 'dismiss',
'chat.stopTitle': 'Stop generation (Cmd+.)',
'chat.jumpToLatest': 'Latest',
'chat.memorySavedTitle': 'Saved {count} memory file(s)',
'chat.memorySavedFromToolsTitle': 'Saved {count} memory item(s)',
'chat.memoryReferencedTitle': '{count} memory reference(s)',
'chat.memoryOpenSettings': 'Open Memory',
'chat.memoryMoreFiles': '+{count} more',
'chat.memoryTechnicalDetails': 'Tool details',
'chat.rewindSuccessWithCode': 'Rewound {count} messages and restored tracked files.',
'chat.rewindSuccessConversationOnly': 'Rewound {count} messages. No file checkpoint was available for this turn.',
'chat.turnChangesTitle': '{count} files changed',
'chat.turnChangesLatestCardLabel': 'Turn changed files',
'chat.turnChangesHistoricalCardLabel': 'Turn changed files',
'chat.turnChangesLatestSubtitle': 'Current turn checkpoint',
'chat.turnChangesHistoricalSubtitle': 'Saved turn checkpoint',
'chat.turnChangesLatestUndo': 'Undo current turn',
'chat.turnChangesHistoricalUndo': 'Rewind to before this turn',
'chat.turnChangesUndoing': 'Undoing...',
'chat.turnChangesLatestUndoAria': 'Undo current turn changes',
'chat.turnChangesHistoricalUndoAria': 'Rewind to before this turn',
'chat.turnChangesLatestConfirmTitle': 'Undo current turn?',
'chat.turnChangesHistoricalConfirmTitle': 'Rewind to before this turn?',
'chat.turnChangesLatestConfirmBody': 'This will rewind the latest assistant response and restore tracked files for this turn.',
'chat.turnChangesHistoricalConfirmBody': 'This will rewind the conversation to before this turn and restore tracked files for that checkpoint.',
'chat.turnChangesLatestConfirmUndo': 'Undo current turn',
'chat.turnChangesHistoricalConfirmUndo': 'Rewind to before this turn',
'chat.turnChangesShowDiffAria': 'Show diff for {path}',
'chat.turnChangesHideDiffAria': 'Hide diff for {path}',
'chat.turnChangesDiffLoading': 'Loading diff...',
'chat.turnChangesDiffUnavailable': 'Diff unavailable.',
// ─── Streaming Indicator ──────────────────────────────────────
'streaming.thinking': 'Thinking',
'streaming.running': 'Running',
'streaming.working': 'Working',
// ─── Permission Dialog ──────────────────────────────────────
'permission.allowEditFile': 'Allow Claude to {toolName} {fileName}?',
'permission.allowEditFileGeneric': 'Allow Claude to {toolName} this file?',
'permission.allowBash': 'Allow Claude to run this command?',
'permission.allowTool': 'Allow Claude to use {toolName}?',
'permission.awaitingApproval': 'Awaiting approval',
'permission.responded': 'Responded',
'permission.allow': 'Allow',
'permission.allowForSession': 'Allow for session',
'permission.deny': 'Deny',
'permission.hideDetails': 'Hide details',
'permission.showFullInput': 'Show full input',
'permission.replacingContent': 'Replacing content in file',
// ─── Computer Use Approval ──────────────────────────────────────
'computerUseApproval.titleApps': 'Computer Use wants to control these apps',
'computerUseApproval.titleTcc': 'Computer Use needs macOS permissions',
'computerUseApproval.reason': 'Why Claude is asking',
'computerUseApproval.allow': 'Allow for session',
'computerUseApproval.deny': 'Deny',
'computerUseApproval.alreadyGranted': 'Already granted for this session',
'computerUseApproval.notInstalled': 'App not installed',
'computerUseApproval.sensitiveApp': 'This app is treated as sensitive and deserves extra review.',
'computerUseApproval.alsoRequested': 'Also requested',
'computerUseApproval.hideWhileWorking': '{count} other apps will be hidden while Claude works.',
'computerUseApproval.hideWhileWorkingRestore': '{count} other apps will be hidden while Claude works, then restored when Claude is done.',
'computerUseApproval.accessibility': 'Accessibility',
'computerUseApproval.screenRecording': 'Screen Recording',
'computerUseApproval.granted': 'Granted',
'computerUseApproval.notGranted': 'Not granted',
'computerUseApproval.openAccessibility': 'Open Accessibility',
'computerUseApproval.openScreenRecording': 'Open Screen Recording',
'computerUseApproval.tryAgain': 'Try again',
'computerUseApproval.tccHint': 'Grant the missing permissions in System Settings, then come back and choose "Try again".',
'computerUseApproval.tryAgainHint': 'Try again returns control to Claude so it can call request_access once more after macOS permission changes take effect.',
// ─── Ask User Question ──────────────────────────────────────
'question.needsInput': 'Claude needs your input',
'question.answered': 'Answered',
'question.customResponse': 'Or type a custom response:',
'question.typePlaceholder': 'Type your answer...',
'question.submit': 'Submit',
'question.answeredPrefix': 'Answered: ',
// ─── Thinking Block ──────────────────────────────────────
'thinking.label': 'Thinking',
// ─── Tool Calls ──────────────────────────────────────
'tool.errorOutput': 'Error Output',
'tool.toolOutput': 'Tool Output',
'tool.toolInput': 'Tool Input',
'tool.readFileContents': 'Read file contents',
'tool.createFile': 'Create file',
'tool.updateFileContents': 'Update file contents',
'tool.linesChanged': '{count} lines changed',
'tool.linesCreated': '{count} lines created',
'tool.linesOutput': '{count} lines output',
'tool.result': '{toolName} result',
'tool.resultGeneric': 'Tool result',
'tool.error': 'ERROR',
'tool.success': 'SUCCESS',
'tool.showLess': 'Show less',
'tool.showMore': 'Show {count} more characters',
// ─── Tool Group Verbs ──────────────────────────────────────
'toolGroup.readOne': 'Read 1 file',
'toolGroup.readMany': 'Read {count} files',
'toolGroup.createdOne': 'created a file',
'toolGroup.createdMany': 'created {count} files',
'toolGroup.editedOne': 'edited a file',
'toolGroup.editedMany': 'edited {count} files',
'toolGroup.ranOne': 'ran a command',
'toolGroup.ranMany': 'ran {count} commands',
'toolGroup.foundFiles': 'found files',
'toolGroup.searchedOne': 'searched code',
'toolGroup.searchedMany': 'searched {count} patterns',
'toolGroup.agentOne': 'dispatched an agent',
'toolGroup.agentMany': 'dispatched {count} agents',
'agentStatus.starting': 'Starting',
'agentStatus.running': 'Running',
'agentStatus.done': 'Done',
'agentStatus.failed': 'Failed',
'agentStatus.stopped': 'Stopped',
'agentStatus.noActivity': 'No tool activity yet',
'agentStatus.viewResult': 'View result',
'agentStatus.resultTitle': 'Agent result',
'toolGroup.searchedWeb': 'searched the web',
'toolGroup.fetchedOne': 'fetched a page',
'toolGroup.fetchedMany': 'fetched {count} pages',
// ─── Tasks ──────────────────────────────────────
'tasks.title': 'Tasks',
'tasks.completed': 'Tasks completed',
'tasks.dismissCompleted': 'Hide completed tasks',
'tasks.newTask': '+ New task',
'tasks.emptyTitle': 'No scheduled tasks yet.',
'tasks.emptyDesc': 'Create a recurring task to automate your engineering workflows.',
'tasks.createNew': 'Create new task',
'tasks.totalTasks': 'Total Tasks',
'tasks.active': 'Active',
'tasks.disabled': 'Disabled',
// ─── New Task Modal ──────────────────────────────────────
'newTask.title': 'New scheduled task',
'newTask.localWarning': 'Local tasks only run while your computer is awake.',
'newTask.name': 'Name',
'newTask.namePlaceholder': 'daily-code-review',
'newTask.description': 'Description',
'newTask.descPlaceholder': "Review yesterday's commits and flag anything concerning",
'newTask.frequency': 'Frequency',
'newTask.everyNMinutes': 'Every N minutes',
'newTask.everyNHours': 'Every N hours',
'newTask.daily': 'Daily',
'newTask.weekdays': 'Weekdays (MonFri)',
'newTask.specificDays': 'Specific days of week',
'newTask.monthly': 'Monthly',
'newTask.customCron': 'Custom cron expression',
'newTask.intervalMinutes': 'Every {n} minutes',
'newTask.intervalHours': 'Every {n} hours',
'newTask.atMinute': 'at minute :{m}',
'newTask.onMonthDay': 'On day {d} of each month',
'newTask.cronFormatHint': 'Format: minute hour day-of-month month day-of-week',
'newTask.invalidCron': 'Invalid cron expression',
'newTask.daySun': 'Sun',
'newTask.dayMon': 'Mon',
'newTask.dayTue': 'Tue',
'newTask.dayWed': 'Wed',
'newTask.dayThu': 'Thu',
'newTask.dayFri': 'Fri',
'newTask.daySat': 'Sat',
'newTask.delayNote': 'Scheduled tasks use a randomized delay of several minutes for server performance.',
'newTask.create': 'Create task',
'newTask.promptPlaceholder': 'Look at the commits from the last 24 hours. Summarize what changed, call out any risky patterns or missing tests, and note anything worth following up on.',
'newTask.notification': 'Notification',
'newTask.notifyOnComplete': 'Push notification on completion',
'newTask.notifyChannels': 'Notification channels',
'newTask.notifyHint': 'Send a native desktop notification or IM message when the task finishes.',
'newTask.notifyDesktop': 'Desktop',
'newTask.notConfigured': 'Not configured',
'newTask.noChannelConfigured': 'No IM channels configured yet. Go to Settings → IM Adapters to set up.',
'newTask.noChannelSelected': 'Select at least one notification channel.',
// ─── Cron Descriptions ──────────────────────────────────────
'cron.everyMinute': 'Runs every minute',
'cron.everyNMinutes': 'Runs every {n} minutes',
'cron.everyHour': 'Runs every hour',
'cron.everyNHours': 'Runs every {n} hours',
'cron.everyNHoursAtMinute': 'Runs every {n} hours at :{m}',
'cron.dailyAt': 'Runs daily at {time}',
'cron.weekdaysAt': 'Runs on weekdays at {time}',
'cron.specificDaysAt': 'Runs every {days} at {time}',
'cron.monthlyAt': 'Runs on the {day}th of every month at {time}',
'cron.customSchedule': 'Custom: {cron}',
'cron.dow.0': 'Sun',
'cron.dow.1': 'Mon',
'cron.dow.2': 'Tue',
'cron.dow.3': 'Wed',
'cron.dow.4': 'Thu',
'cron.dow.5': 'Fri',
'cron.dow.6': 'Sat',
// ─── Task Actions & Logs ──────────────────────────────────────
'tasks.runNow': 'Run now',
'tasks.confirmRun': 'Execute this task immediately?',
'tasks.confirmDisable': 'Disable this scheduled task?',
'tasks.confirmEnable': 'Enable this scheduled task?',
'tasks.confirmDelete': 'Permanently delete this task and all its logs?',
'tasks.running': 'Running...',
'tasks.viewLogs': 'Logs',
'tasks.logsTitle': 'Execution logs',
'tasks.noLogs': 'No execution logs yet',
'tasks.runStatus.running': 'Running',
'tasks.runStatus.completed': 'Completed',
'tasks.runStatus.failed': 'Failed',
'tasks.runStatus.timeout': 'Timeout',
'tasks.duration': '{s}s',
'tasks.viewOutput': 'Summary',
'tasks.hideOutput': 'Hide',
'tasks.close': 'Close',
'tasks.edit': 'Edit',
'tasks.editTitle': 'Edit scheduled task',
'tasks.saveChanges': 'Save changes',
'tasks.openSession': 'View conversation',
'tasks.createdAt': 'Created: ',
'tasks.lastRunAt': 'Last run: ',
'tasks.outputHintSession': 'Click "View conversation" to see the full output in session view.',
'tasks.noOutputText': 'No output available.',
// ─── Prompt Editor ──────────────────────────────────────
'promptEditor.worktree': 'worktree',
'promptEditor.bypassWarning': 'Bypass mode grants full system access',
'promptEditor.within': 'within',
'promptEditor.selectFolder': '— select a folder to limit scope',
// ─── Permission Mode Selector ──────────────────────────────────────
'permMode.executionPermissions': 'Execution Permissions',
'permMode.askPermissions': 'Ask permissions',
'permMode.askPermDesc': 'Confirm file edits and higher-risk commands when CLI asks',
'permMode.autoAccept': 'Auto accept edits',
'permMode.autoAcceptDesc': 'Claude writes to disk without asking',
'permMode.planMode': 'Plan mode',
'permMode.planModeDesc': 'Architecture & reasoning only, no files',
'permMode.bypass': 'Bypass permissions',
'permMode.bypassDesc': 'Full tool access for shell and file system',
'permMode.dontAsk': "Don't ask",
'permMode.enableBypassTitle': 'Enable bypass permissions?',
'permMode.enableBypassSubtitle': 'This grants full access to your system',
'permMode.enableBypassBody': 'Claude will have <strong>unrestricted</strong> access to execute shell commands and modify files within:',
'permMode.permReadWrite': 'Read, write, and delete any files',
'permMode.permShell': 'Execute arbitrary shell commands',
'permMode.permPackages': 'Install or remove packages',
'permMode.enableBypassBtn': 'Enable bypass',
// Mode labels (compact, for chips)
'permMode.label.default': 'Ask permissions',
'permMode.label.acceptEdits': 'Auto accept',
'permMode.label.plan': 'Plan mode',
'permMode.label.bypassPermissions': 'Bypass',
'permMode.label.dontAsk': "Don't ask",
// ─── Model Selector ──────────────────────────────────────
'model.selectModel': 'Select model',
'model.configuration': 'Model Configuration',
'model.effort': 'Effort',
// ─── Directory Picker ──────────────────────────────────────
'dirPicker.selectProject': 'Select a project...',
'dirPicker.recent': 'Recent',
'dirPicker.noRecent': 'No recent projects',
'dirPicker.chooseFolder': 'Choose a different folder',
'dirPicker.chooseProjectFolder': 'Choose project folder',
'dirPicker.useThisFolder': 'Use this folder',
'dirPicker.noSubdirs': 'No subdirectories',
// ─── File Search ──────────────────────────────────────
'fileSearch.searching': 'Searching...',
'fileSearch.noMatch': 'No files match',
'fileSearch.noFiles': 'No files in this directory',
'fileSearch.accessDenied': 'Cannot access this directory',
'fileSearch.loadFailed': 'Failed to load directory',
'fileSearch.navigate': 'navigate',
'fileSearch.attach': 'attach',
'fileSearch.select': 'select',
'fileSearch.open': 'open folder',
'fileSearch.close': 'close',
'fileSearch.directory': 'folder',
'fileSearch.currentDirectory': 'current folder',
'fileSearch.folderTag': 'folder',
'fileSearch.fileTag': 'file',
'fileSearch.openFolder': 'Open folder',
// ─── Teams ──────────────────────────────────────
'teams.backToLeader': '\u2190 Back to Leader',
'teams.viewing': 'Viewing:',
'teams.transcript': 'transcript',
'teams.noMessages': 'No messages yet',
'teams.team': 'Team:',
'teams.members': 'members',
'teams.working': 'Working...',
'teams.thinking': 'Thinking...',
'teams.running': 'running',
'teams.leader': 'team-lead',
'teams.memberPlaceholder': 'Message this teammate directly...',
'teams.memberSessionHint': 'Messages here go straight to this teammate while you watch its transcript update.',
// ─── Scheduled Tasks Pages ──────────────────────────────────────
'scheduledPage.title': 'Scheduled tasks',
'scheduledPage.subtitle': 'Run tasks on a schedule or whenever you need them. Type {code} in any existing session to create one.',
'scheduledPage.desktopNotice': 'Scheduled tasks only run while the desktop app is open. Make sure it stays running for tasks to fire on time.',
'scheduledPage.oldSubtitle': 'Manage automated operational routines and background maintenance.',
'scheduledPage.executionMode': 'Execution Mode',
'scheduledPage.localMode': 'Local Mode',
'scheduledPage.remoteMode': 'Remote Mode',
'scheduledPage.nextRun': 'Next Run',
'scheduledPage.systemHealth': 'System Health',
'scheduledPage.activeSession': 'Active Session',
'scheduledPage.colTaskName': 'Task Name',
'scheduledPage.colFrequency': 'Frequency',
'scheduledPage.colLastResult': 'Last Result',
'scheduledPage.colNextExecution': 'Next Execution',
'scheduledPage.colActions': 'Actions',
'scheduledPage.endOfList': 'End of scheduled list',
'scheduledPage.pausedTasks': '9 other tasks are currently paused or disabled for maintenance.',
'scheduledPage.recentLogs': 'Recent Output Logs',
'scheduledPage.viewArtifacts': 'View Full Artifacts',
'scheduledPage.resourceAllocation': 'Resource Allocation',
'scheduledPage.cpuCapacity': 'CPU Capacity',
'scheduledPage.memoryLoad': 'Memory Load',
'scheduledPage.connectedLocal': 'Connected to local node',
'scheduledPage.thisMonth': '{count} this month',
// ─── Update Checker ──────────────────────────────────────
'update.available': 'v{version} available',
'update.availableLabel': 'Available',
'update.checking': 'Checking for updates...',
'update.checkNow': 'Check now',
'update.checkedAt': 'Last checked {time}',
'update.currentVersionUnknown': 'Unknown',
'update.newVersion': 'New version v{version} available',
'update.downloading': 'Downloading...',
'update.idle': 'Check for updates to compare your installed version with the latest GitHub Release.',
'update.now': 'Update now',
'update.later': 'Later',
'update.progress': 'Downloading update... {progress}%',
'update.progressBytes': 'Downloading update... {downloaded} downloaded',
'update.releaseNotes': 'Release Notes',
'update.restarting': 'Restarting to finish update...',
'update.upToDate': 'You are up to date on v{version}.',
'update.failed': 'Update failed: {error}',
// ─── Active Session ──────────────────────────────────────
'session.untitled': 'Untitled Session',
'session.active': 'session active',
'session.lastUpdated': 'last updated {time}',
'session.messages': '{count} messages',
'session.workspaceUnavailable': 'Workspace unavailable: {dir}',
'session.timeJustNow': 'just now',
'session.timeMinutes': '{n}m ago',
'session.timeHours': '{n}h ago',
'session.timeDays': '{n}d ago',
// ─── App Shell ──────────────────────────────────────
'app.serverFailed': 'Local server failed to start',
'app.serverFailedHint': 'Please include a screenshot of this diagnostic panel when reporting the issue.',
'app.startupError': 'Startup error',
'app.serverLogs': 'Server logs',
'app.copyDiagnostics': 'Copy diagnostics',
'app.copiedDiagnostics': 'Copied',
'app.launching': 'Launching local workspace...',
// ─── Error Codes ──────────────────────────────────────
'error.CLI_NOT_RUNNING': 'CLI process is not running. The session may have ended or the process crashed.',
'error.CLI_START_FAILED': 'Failed to start CLI process.',
'error.CLI_AUTH_REQUIRED': 'Authentication is required. Please log in.',
'error.CLI_SESSION_CONFLICT': 'Session is already in use by another process.',
'error.CLI_SPAWN_FAILED': 'Failed to spawn CLI subprocess.',
'error.CLI_ERROR': 'An error occurred during processing.',
'error.WORKDIR_INVALID': 'Working directory is invalid or does not exist.',
'error.PARSE_ERROR': 'Invalid message format.',
'error.UNKNOWN_TYPE': 'Unknown message type.',
'error.BAD_REQUEST': 'Bad request.',
'error.NOT_FOUND': 'Resource not found.',
'error.INTERNAL_ERROR': 'Internal server error.',
// ─── Server Status Verbs ──────────────────────────────────────
'serverVerb.Thinking': 'Thinking',
'serverVerb.Running': 'Running',
'serverVerb.Working': 'Working',
'serverVerb.Creating worktree': 'Creating worktree',
'serverVerb.Task started': 'Task started',
'serverVerb.Task in progress': 'Task in progress',
// ─── Tabs ──────────────────────────────────────
'tabs.close': 'Close',
'tabs.closeOthers': 'Close Others',
'tabs.closeLeft': 'Close to the Left',
'tabs.closeRight': 'Close to the Right',
'tabs.closeAll': 'Close All',
'tabs.closeConfirmTitle': 'Session Running',
'tabs.closeConfirmMessage': 'This session is still running. What would you like to do?',
'tabs.closeConfirmKeep': 'Keep Running',
'tabs.closeConfirmStop': 'Stop & Close',
'tabs.openTerminal': 'Open Terminal',
'tabs.showWorkspace': 'Show Workspace',
'tabs.hideWorkspace': 'Hide Workspace',
} as const
export type TranslationKey = keyof typeof en