// settings

export const settingsEn = {
  settings: {
    title: 'Settings',
    tabs: { ai: 'AI', appearance: 'Appearance', knowledge: 'General', sync: 'Sync', mcp: 'Connections', plugins: 'Plugins', shortcuts: 'Shortcuts', update: 'Update', uninstall: 'Uninstall' },
    ai: {
      provider: 'Model Providers',
      apiKey: 'API Key',
      keyOptionalHint: 'Optional for local providers. Stored in ~/.mindos/config.json',
      envFieldNote: (key: string) => `Env var ${key} is set. Clear this field to fall back to it.`,
      restoreFromEnv: 'Restore from env',
      testKey: 'Test',
      testKeyTesting: 'Testing...',
      testKeyOk: (ms: number) => `\u2713 ${ms}ms`,
      testKeyAuthError: 'Invalid API key',
      testKeyModelNotFound: 'Model not found',
      testKeyEndpointError: 'Endpoint or protocol mismatch',
      testKeyRateLimited: 'Rate limited, try again later',
      testKeyNetworkError: 'Network error',
      testKeyUnknown: 'Test failed',
      listModels: 'Browse',
      noModelsFound: 'No models found',
    },
    agent: {
      title: 'Agent Behavior',
      subtitle: 'Configure how the AI agent operates',
      maxSteps: 'Max Steps',
      maxStepsHint: 'Max tool call rounds per request',
      contextStrategy: 'Context Strategy',
      contextStrategyHint: 'Auto: summarize early messages when context fills up. Off: no summarization (emergency pruning still applies).',
      contextStrategyAuto: 'Auto (compact + prune)',
      contextStrategyOff: 'Off',
      thinking: 'Extended Thinking',
      thinkingHint: "Show Claude's reasoning process (uses more tokens)",
      thinkingBudget: 'Thinking Budget',
      thinkingBudgetHint: 'Max tokens for reasoning (1000-50000)',
      reconnectRetries: 'Auto Reconnect',
      reconnectRetriesHint: 'When connection drops, automatically retry this many times before giving up (0 = disabled)',
    },
    embedding: {
      title: 'Embedding Search',
      description: 'Semantic search with vector embeddings. Finds notes by meaning, not just exact words.',
      enable: 'Enable embedding search',
      enableHint: 'Combines keyword matching (BM25) with semantic similarity.',
      providerLocal: 'Local',
      providerLocalFree: 'Free',
      providerLocalDesc: 'Runs on your machine, no API key needed',
      providerApi: 'API',
      providerApiDesc: 'SiliconFlow (free), OpenAI, DeepSeek, etc.',
      model: 'Model',
      modelHint: 'Choose a model. Smaller models are faster.',
      modelName: 'Embedding model name',
      downloadModel: 'Install Runtime & Download Model',
      downloading: 'Installing runtime / downloading model...',
      starting: 'Starting install...',
      retry: 'Retry',
      modelReady: 'Model ready',
      downloadFailedHint: 'If install or download keeps failing, try API mode or set HF_ENDPOINT=https://hf-mirror.com',
      baseUrl: 'Base URL',
      baseUrlHint: 'OpenAI-compatible embedding endpoint',
      apiKey: 'API Key',
      apiKeyHint: 'Get from your provider. Leave empty for Ollama.',
      apiKeyHintLocal: 'Leave empty for local services',
      indexBuilding: 'Building embedding index...',
      indexReady: (count: number) => `${count} documents indexed`,
      indexPending: 'Index will be built on first search',
    },
    webSearch: {
      title: 'Web Search',
      description: 'Configure search providers for web_search and fetch_content tools.',
      providerAuto: 'Auto',
      providerAutoDesc: 'Automatically select the best available provider',
      providerExa: 'Exa',
      providerExaDesc: 'Neural/semantic search, 1000 free/month',
      providerPerplexity: 'Perplexity',
      providerPerplexityDesc: 'AI-powered search with summaries',
      providerGemini: 'Gemini',
      providerGeminiDesc: 'Google Gemini search via API',
      exaApiKey: 'Exa API Key',
      perplexityApiKey: 'Perplexity API Key',
      geminiApiKey: 'Gemini API Key',
      apiKeyHint: 'Optional. Falls back to next provider if empty.',
      noKeysHint: 'Works without API keys via Exa MCP (zero-config).',
    },
    appearance: {
      readingTitle: 'Reading',
      readingDesc: 'Customize how your notes look',
      readingFont: 'Reading font',
      fontSize: 'Font size',
      fontSizePreview: 'The quick brown fox.',
      contentWidth: 'Content width',
      preferencesTitle: 'Preferences',
      colorTheme: 'Color theme',
      system: 'System',
      dark: 'Dark',
      light: 'Light',
      language: 'Language',
      browserNote: 'Appearance settings are saved in your browser.',
      labsTitle: 'Labs',
      labsDesc: 'Experimental features still in development. May change or be removed.',
      labsEcho: 'Echo',
      labsEchoDesc: 'Reflective journaling powered by your notes.',
      labsWorkflows: 'Flows',
      labsWorkflowsDesc: 'Visual workflow automation for agents.',
      fontPreview: 'The quick brown fox jumps over the lazy dog.',
    },
    knowledge: {
      cardTitle: 'Knowledge Base',
      securityTitle: 'Security',
      passwordPlaceholder: 'Leave empty to disable',
      passwordShow: 'Show',
      passwordHide: 'Hide',
      tokenNotSet: '— not set —',
      mcpUrl: 'MCP URL',
      tokenGenerated: 'New token generated. Copy it now — it won\'t be shown in full again.',
      monitoringTitle: 'System Monitoring',
      monitoringFailed: 'Failed to load monitoring data',
      monitorHeap: 'Heap',
      monitorRss: 'RSS',
      monitorUptime: 'Uptime',
      monitorNode: 'Node',
      monitorRequests: 'Requests',
      monitorToolCalls: 'Tool Calls',
      monitorTokens: 'Tokens',
      monitorFiles: 'Files',
      monitorErrors: 'Errors',
      monitorMcpRunning: (port: number) => `Running :${port}`,
      monitorMcpStopped: 'Stopped',
      cancel: 'Cancel',
      mindRoot: 'Knowledge base root',
      mindRootHint: 'Absolute path to your notes directory. Requires server restart to take effect.',
      mindRootEnvHint: (key: string) => `MIND_ROOT env var is set to "${key}". Fill in above to override it.`,
      envNote: 'MIND_ROOT env var is set. Fill in above to override it — your value takes priority.',
      webPassword: 'Web UI password',
      webPasswordHint: 'Protect the browser UI with a password. Leave empty to disable. Changes take effect on next page load.',
      webPasswordClear: 'Clear password',
      allowNetworkAccess: 'Allow LAN access',
      allowNetworkAccessHint: 'Bind the Web UI to 0.0.0.0 after restart so other devices on your network can connect. Keep off unless you need remote access.',
      authToken: 'MCP / API auth token',
      authTokenHint: 'Bearer token for Agent and MCP clients. Not required for browser access.',
      authTokenNone: 'No token set — API is open to all requests.',
      authTokenCopy: 'Copy',
      authTokenCopied: 'Copied!',
      authTokenReset: 'Regenerate',
      authTokenClear: 'Clear token',
      authTokenResetConfirm: 'Regenerate token? All existing MCP clients will need to update their config.',
      authTokenMcpPort: 'MCP port',
      restartWalkthrough: 'Restart walkthrough',
      showHiddenFiles: 'Show hidden files',
      showHiddenFilesHint: 'Display dot-prefixed folders (.agents, .claude, .mindos, etc.) in the file tree.',
      cleanupExamples: 'Clean up example files',
      cleanupExamplesHint: 'Remove all template example files (🧪_example_*) from your knowledge base.',
      cleanupExamplesButton: 'Clean up',
      cleanupExamplesNone: 'No example files found',
      cleanupExamplesConfirm: (n: number) => `Delete ${n} example file${n > 1 ? 's' : ''}? This cannot be undone.`,
      cleanupExamplesDone: (n: number) => `Removed ${n} example file${n > 1 ? 's' : ''}`,
      cleanupExamplesScanning: 'Scanning...',
    },
    sync: {
      emptyTitle: 'Cross-device Sync',
      emptyDesc: 'Automatically sync your knowledge base across devices via Git.',
      setupIntroTitle: 'Start with a private Git repository',
      setupStepRepo: 'Create an empty private repo',
      setupStepUrl: 'Paste its SSH or HTTPS URL',
      setupStepToken: 'HTTPS can use a token for private repos',
      featureAutoCommit: 'Auto-commit on save',
      featureAutoPull: 'Auto-pull from remote',
      featureConflict: 'Conflict detection',
      featureMultiDevice: 'Works across devices',
      remoteUrl: 'Git Remote URL',
      invalidUrl: 'Invalid Git URL — use HTTPS (https://...) or SSH (git@... / ssh://git@...)',
      sshBrief: 'one-time key setup, no token needed',
      httpsBrief: 'works anywhere; add a token for private repos',
      sshHint: 'Requires SSH key on this machine. Verify with your Git host.',
      sshHintForHost: (host: string) => `Requires SSH key on this machine. Verify with: ssh -T git@${host}`,
      accessToken: 'Access Token',
      requiredForPrivateHttps: '(optional; needed for private HTTPS repos)',
      tokenHint: 'Optional for public repositories or machines that already have Git credentials. Private GitHub/GitLab HTTPS repositories usually need one.',
      tokenLink: 'Create a token (repo scope)',
      showToken: 'Show token',
      hideToken: 'Hide token',
      branchLabel: 'Branch',
      invalidBranch: 'Branch names must be valid Git refs: no spaces, leading/trailing slashes, "..", "@{", ".lock", or Git ref control characters.',
      connectButton: 'Connect & Start Sync',
      connectNeedsUrl: 'Paste a remote URL to continue',
      connectFixUrl: 'Fix the Git URL to continue',
      connectFixBranch: 'Use a valid Git branch name',
      connectingTo: (remote: string) => `Connecting to ${remote}`,
      cancel: 'Cancel',
      stopWaiting: 'Stop waiting',
      hideProgress: 'Hide progress',
      initStillRunningTitle: 'Sync setup is still running',
      initStillRunningDesc: 'MindOS is still configuring the repository in the background. Wait for the result before starting setup again.',
      connecting: 'Connecting...',
      stepConnecting: 'Connecting to remote...',
      stepAuthenticating: 'Authenticating...',
      stepSyncing: 'Syncing data...',
      stepAlmostDone: 'Almost done...',
      stepDone: 'Sync configured successfully!',
      timeoutError: 'Connection timed out. The remote repository may be large or the network is slow. Please try again.',
      gitignoreTitle: 'Excluded files',
      gitignorePlaceholder: '# Files to exclude from sync\n*.tmp\nsecret/',
      gitignoreSave: 'Save',
      gitignoreSaved: 'Saved',
      gitignoreLoadFailed: 'Failed to load .gitignore',
      gitignoreSaveFailed: 'Failed to save .gitignore',
      gitignoreStoppedTracking: (n: number) => `${n} previously synced file${n === 1 ? '' : 's'} will be removed from future syncs.`,
      gitignoreStoppedTrackingHint: 'The file stays on this device. The next sync removes it from the current remote tree; older Git history may still contain prior copies.',
      syncStatusRefreshFailed: 'Saved, but failed to refresh sync status',
      remoteBackupMissing: 'Remote backup unavailable',
      remoteBackupMissingHint: 'The remote version could not be saved for preview, so it cannot be applied from the UI.',
      remoteDeleted: 'Remote deleted',
      localDeleted: 'Local deleted',
      keepRemoteDeletedHint: 'Accept the remote deletion for this file',
      remoteDeletedPreview: '(deleted remotely)',
      conflictExplain: 'These files were changed on both this device and the remote. Choose which version to keep.',
      keepLocal: 'Keep local',
      keepRemote: 'Keep remote',
      confirmKeepLocal: 'Confirm keep local?',
      keepLocalHint: 'Keep this device\'s version',
      keepRemoteHint: 'Replace with the remote version',
      viewDiff: 'Click to compare versions',
      viewDiffFirst: 'View diff first',
      conflictPreviewFailed: 'Failed to load conflict preview',
      conflictResolveFailed: 'Failed to resolve conflict',
      conflictResolvedRefreshFailed: 'Conflict resolution may have been saved, but MindOS could not refresh sync status. Retry status refresh before continuing.',
      previewEmptyState: 'No preview loaded yet.',
      retry: 'Retry',
      localVersion: 'Local (this device)',
      remoteVersion: 'Remote',
      emptyFile: '(empty)',
      sectionTitle: 'Sync',
      repositoryTitle: 'Repository',
      automationTitle: 'Automation',
      automationDesc: 'MindOS keeps syncing in the background while you work.',
      automationPausedDesc: 'Intervals apply when auto-sync is enabled.',
      autoCommitLabel: 'Save changes every',
      autoPullLabel: 'Check for updates every',
      healthSyncedTitle: 'All notes are backed up',
      healthSyncedDesc: (time: string) => `Last sync: ${time}.`,
      healthSyncedNext: 'Next: keep writing',
      healthReadyTitle: 'Sync is ready',
      healthReadyDesc: 'No completed sync has been recorded yet.',
      healthReadyNext: 'Run Sync Now to create the first backup',
      healthUnpushedTitle: (n: number) => `${n} local change${n === 1 ? '' : 's'} waiting to upload`,
      healthUnpushedDesc: 'MindOS will push them automatically, or you can run Sync now.',
      healthUnpushedNext: 'Next: sync now or keep working',
      healthPausedUnpushedTitle: (n: number) => `${n} local change${n === 1 ? '' : 's'} are waiting`,
      healthPausedUnpushedDesc: 'Auto-sync is paused. These changes will not upload until you sync manually or enable auto-sync.',
      healthPausedUnpushedNext: 'Next: run Sync Now or enable auto-sync',
      healthUnknownTitle: 'Sync status unknown',
      healthUnknownDesc: 'MindOS could not confirm whether local changes have been uploaded.',
      healthUnknownNext: 'Next: retry sync or check the remote repository',
      healthPausedUnknownDesc: 'Auto-sync is paused, and MindOS could not confirm whether local changes have been uploaded.',
      healthPausedUnknownNext: 'Next: enable auto-sync or retry the status refresh',
      healthPausedTitle: 'Sync is paused',
      healthPausedDesc: 'Auto-sync is disabled for this repository. Your existing Git configuration is still available.',
      healthPausedNext: 'Next: run Sync Now manually or enable auto-sync for background backups',
      healthConflictsTitle: 'Resolve conflicts to finish sync',
      healthConflictsDesc: (n: number) => `Review ${n} file${n === 1 ? '' : 's'} below, compare the two versions, then choose which one to keep.`,
      healthConflictsNext: 'Next: choose which version to keep',
      healthErrorTitle: 'Sync needs attention',
      healthErrorNext: 'Next: fix the issue, then sync again',
      healthStaleTitle: 'Sync status may be outdated',
      healthStaleNext: 'Next: retry status refresh before trusting this state',
      brokenTitle: 'Sync configuration is broken',
      brokenDesc: 'The git repository or remote is missing. Reset to re-configure.',
      resetFailed: 'Failed to reset sync configuration',
      labelProvider: 'Provider',
      labelRemote: 'Remote',
      labelBranch: 'Branch',
      labelLastSync: 'Last sync',
      labelNoSyncYet: 'Not synced yet',
      labelUnpushed: 'Local changes',
      labelUnknown: 'Unknown',
      labelAutoSync: 'Auto-sync',
      labelEnabled: 'Active',
      labelPaused: 'Paused',
      unpushedCommits: (n: number) => `${n} changes`,
      syncNow: 'Sync Now',
      disableAutoSync: 'Disable Auto-sync',
      enableAutoSync: 'Enable Auto-sync',
      changeRepositoryButton: 'Change repository',
      changeRepositoryConfirm: 'Confirm change repository?',
      changeRepositoryHelp: 'Stops auto-sync and returns to setup so you can connect another remote. Notes and Git history stay on this device.',
      syncComplete: 'Sync complete',
      syncFailed: 'Sync failed',
      syncLocked: 'Sync is already running',
      hintSyncLocked: 'Another sync operation is already running. Wait a moment, then try again.',
      hintSshAuth: 'SSH key may not be configured. Check the SSH key for this Git host.',
      hintSshAuthForHost: (host: string) => `SSH key may not be configured. Run: ssh-keygen -t ed25519 && ssh -T git@${host}`,
      hintSshHost: 'Add this Git host to ~/.ssh/known_hosts with ssh-keyscan.',
      hintSshHostForHost: (host: string) => `Run: ssh-keyscan ${host} >> ~/.ssh/known_hosts`,
      hintHttpsAuth: 'Access token or Git credentials may be expired or missing. Check this Git host\'s credential settings.',
      hintHttpsAuthForHost: (host: string) => {
        if (host.includes('github.com')) return 'Access token may be expired or missing. Check GitHub Developer settings -> Personal access tokens.';
        if (host.includes('gitlab.com')) return 'Access token may be expired or missing. Check GitLab User Settings -> Access Tokens.';
        return `Access token or Git credentials may be expired or missing. Check the credential settings for ${host}.`;
      },
      hintNetwork: 'Check your network connection and try again.',
      hintNotFound: 'Repository not found. Check the URL and ensure the repo exists.',
      hintPushRejected: 'Remote has changes. Click "Sync Now" to pull and retry.',
      hintConflict: 'Merge conflict detected. Check the Conflicts section below.',
      settingsSaving: 'Saving sync settings...',
      settingsSaved: 'Sync settings saved',
      statusRefreshFailed: 'The change may have been saved, but MindOS could not refresh sync status. Retry status refresh before continuing.',
      statusRefreshRequired: 'Sync status is outdated. Retry status refresh before changing sync settings.',
      resolveConflictsBeforeSettings: 'Resolve conflicts before changing sync settings.',
      loadFailedTitle: 'Could not load sync status',
      resetButton: 'Forget local sync settings',
      resetConfirm: 'Confirm forget settings?',
      resetHelp: 'Keeps your notes and Git repository. Clears MindOS sync settings so you can connect again.',
      notConfigured: '(not configured)',
      autoSyncDisabled: 'Auto-sync disabled',
      autoSyncEnabled: 'Auto-sync enabled',
      toggleFailed: 'Failed to toggle sync',
      conflictsTitle: (n: number) => `Conflicts (${n})`,
      conflictSectionDesc: 'Review each file below. Choose which version to keep before syncing again.',
      timeNever: 'never',
      timeUnknown: 'unknown',
      timeJustNow: 'just now',
      timeMinAgo: (m: number) => `${m}m ago`,
      timeHourAgo: (h: number) => `${h}h ago`,
      timeDayAgo: (d: number) => `${d}d ago`,
    },
    plugins: {
      title: 'Installed Renderers',
      builtinBadge: 'built-in',
      coreBadge: 'core',
      enabled: 'Enabled',
      disabled: 'Disabled',
      matchHint: 'Auto-activates on',
      coreHint: 'Core renderer — always enabled',
      noPlugins: 'No renderers installed.',
      comingSoon: 'Plugin marketplace coming soon.',
    },
    mcp: {
      // Connection Mode Card
      modeCardTitle: 'Connection Mode',
      modeCardDesc: 'Choose how agents connect to MindOS.',
      cliLabel: 'CLI',
      cliModeDesc: 'Claude Code, Gemini CLI, Codex, etc.',
      mcpLabel: 'MCP',
      mcpModeDesc: 'Claude Desktop, Cursor, Windsurf, etc.',
      alwaysOn: 'Always On',
      mcpRunning: 'Running',
      mcpStopped: 'Stopped',
      mcpEnabledHint: 'MCP mode enabled. Disable to simplify the interface if you only use CLI agents.',
      mcpDisabledHint: 'Enable MCP to connect Desktop clients like Claude Desktop or Cursor.',
      // Rest of existing MCP section...
      serverTitle: 'MindOS MCP Server',
      status: 'Status',
      running: 'Running',
      stopped: 'Stopped',
      transport: 'Transport',
      endpoint: 'Endpoint',
      tools: 'Tools',
      toolsRegistered: (n: number) => `${n} registered`,
      auth: 'Auth',
      authSet: 'Token set',
      authNotSet: 'No token',
      copyEndpoint: 'Copy Endpoint',
      copyConfig: 'Copy Config',
      copied: 'Copied!',
      agentsTitle: 'Agent Configuration',
      agent: 'Agent',
      scope: 'Scope',
      project: 'Project',
      global: 'Global',
      installed: 'Installed',
      notInstalled: 'Not installed',
      detected: 'Detected',
      notFound: 'Not found',
      connectedGroup: 'Connected',
      detectedGroup: 'Detected',
      notFoundGroup: 'Not Installed',
      tagConnected: 'Connected',
      transportStdio: 'stdio (recommended)',
      transportHttp: 'http',
      transportAuto: 'auto (recommended)',
      httpUrl: 'MCP URL',
      httpToken: 'Auth Token',
      installSelected: 'Install Selected',
      installing: 'Installing...',
      installSuccess: (n: number) => `${n} agent(s) configured`,
      installFailed: 'Install failed',
      portLabel: 'MCP Port',
      portHint: 'Changes require server restart',
      skillsTitle: 'Skills',
      skillsDesc: 'Teach agents how to operate your knowledge base.',
      skillAutoLoaded: 'Auto-loaded on every request',
      skillSource: 'Source',
      skillBuiltin: 'Built-in',
      skillUser: 'Custom',
      addSkill: '+ Add Skill',
      cliInstallHint: 'Install via CLI:',
      skillPathHint: 'Skill files installed at:',
      deleteSkill: 'Delete',
      editSkill: 'Edit',
      saveSkill: 'Save',
      cancelSkill: 'Cancel',
      skillName: 'Name',
      skillDesc: 'Description',
      skillContent: 'Content',
      skillNameConflict: 'A skill with this name already exists',
      skillDeleteConfirm: (name: string) => `Delete skill "${name}"? This cannot be undone.`,
      skillLanguage: 'Skill Language',
      skillLangEn: 'English',
      skillLangZh: '中文',
      searchSkills: 'Search skills...',
      customGroup: 'Custom',
      builtinGroup: 'Built-in',
      noSkillsMatch: (query: string) => `No skills match "${query}"`,
      skillSearchPaths: 'Skill Search Paths',
      skillAgentsDir: 'External agent skills (~/.agents/skills)',
      skillCustomPaths: 'Custom Paths',
      skillAddPath: '+ Add path',
      skillPathSaved: 'Skill paths saved',
      skillPathPlaceholder: 'Enter directory path...',
      skillPathRemove: 'Remove',
      skillTemplate: 'Template',
      skillTemplateGeneral: 'General',
      skillTemplateToolUse: 'Tool-use',
      skillTemplateWorkflow: 'Workflow',
      selectDetected: 'Select Detected',
      clearSelection: 'Clear',
      quickSetup: 'Quick Setup',
      configureFor: 'Configure for',
      configPath: 'Config path',
      transportLocal: 'Local',
      transportRemote: 'Remote',
      transportLocalHint: 'Local — same machine as MindOS server',
      transportRemoteHint: 'Remote — connect from another device via HTTP',
      remoteDetectedHint: 'Using your current remote IP.',
      remoteManualHint: 'Replace 127.0.0.1 with your server\'s public or LAN IP.',
      remoteSteps: 'To connect from another device: ① Open port {port} in firewall/security group ② Use the config below in your Agent ③ For public networks, consider SSH tunnel for encryption.',
      noAuthWarning: '⚠ No auth token — set one in Settings → General before enabling remote access.',
      showJson: 'Show JSON',
      hideJson: 'Hide JSON',
      connectionTitle: 'Connect Agents',
      connectionHint: 'Choose how your AI agents connect to MindOS.',
      tokenCardTitle: 'Auth Token',
      tokenCardDesc: 'Used by CLI remote mode and MCP connections.',
      mcpHint: 'For Claude Desktop, Cursor, and agents that use MCP tool protocol.',
      tokenLabel: 'Auth Token',
      tokenMasked: 'Click Show to reveal the full token',
      tokenShow: 'Show',
      tokenHide: 'Hide',
      tokenCopy: 'Copy',
      tokenCopied: 'Token copied!',
      tokenRevealFailed: 'Failed to reveal token',
      tokenNone: 'No token set — your MCP server is open to all requests.',
      tokenNoneAction: 'Generate a token in Settings → General → Security.',
      serverUrl: 'MCP Server URL',
      serverUrlCopy: 'Copy URL',
      howToConnect: 'How to connect an AI agent',
      howToStep1: 'Open your agent\'s MCP settings (e.g. Claude Code, Cursor)',
      howToStep2: 'Add a new MCP server with the URL above',
      howToStep3: 'Set the Auth Token as the bearer token',
      howToStep4: 'Save and verify the connection',
      // CLI Skill
      cliSkillTitle: 'CLI Skill',
      cliSkillHint: 'For agents with bash (Claude Code, Gemini CLI, Codex) — lower token cost, no MCP needed.',
      cliSkillDesc: 'Lower token cost, Skill included — just install and go.',
      cliLocalDesc: 'MindOS Skill is built-in. Install the CLI and you\'re good to go.',
      cliRemoteDesc: 'Install the CLI on another machine and connect to this MindOS server.',
      cliSkillInstall: 'Install',
      cliSkillInstallCmd: 'npm install -g @geminilight/mindos',
      cliSkillRemote: 'Remote',
      cliSkillVerify: 'Verify',
      cliSkillVerifyCmd: 'mindos file list',
      cliRemoteConfigure: 'Configure',
      cliInstallSkill: 'Install Skill',
      cliAgents: 'Claude Code · Gemini CLI · Codex',
      mcpAgents: 'Claude Desktop · Cursor',
      mcpDesc: 'Requires per-agent MCP config. Install Skill separately via',
      mcpLocalDesc: 'Copy the config snippet and paste into your agent\'s MCP settings.',
      mcpRunningLabel: 'MCP Running',
      mcpServerStatus: 'MCP Server',
      autoInstallAgents: 'Auto-install to detected agents',
      detectedAgentsTitle: 'Detected Agents',
      cliInstallDesc: 'Install the MindOS Skill to your agent so it can operate your knowledge base.',
      mcpInstallDesc: 'Install MCP config + Skill to detected agents on this machine.',
      tokenCopyFullHint: 'Copies full token',
      skillsInstalled: 'skills installed',
      recommended: 'Recommended',
      localTitle: 'Local',
      localReady: 'Ready to use',
      remoteTitle: 'Remote Access',
      remoteSubtitle: 'Connect from another device',
      restarting: 'Restarting...',
      restart: 'Restart',
      // Server Ports Card
      portsCardTitle: 'Server Ports',
      portsCardDesc: 'Web UI and MCP server ports. Changes take effect after restart.',
      webPortLabel: 'Web UI Port',
      webPortHint: 'The port your browser connects to.',
      mcpPortLabel: 'MCP Server Port',
      mcpPortHint: 'The port agents and desktop apps connect to.',
      portChecking: 'Checking…',
      portAvailable: 'Available',
      portSelf: 'Current port',
      portInUse: (p: number) => `Port ${p} is in use`,
      portSuggest: (p: number | null) => `Use ${p}`,
      portConflict: 'Web and MCP ports must be different.',
      portUpdating: 'Saving…',
      portWebRestarting: 'Restarting server…',
      portMcpRestarting: 'Restarting MCP…',
      portUpdateSuccess: 'Ports updated successfully.',
      portUpdateFailed: 'Failed to update ports.',
      portRestartTimeout: 'Restart timed out. Please try again.',
      portRedirecting: 'Redirecting to new address…',
      portUpdateBtn: 'Update Ports',
      externalToolsTitle: 'External MCP Tools',
      externalToolsDesc: 'Configure tool access mode for external MCP servers.',
    },
    save: 'Save',
    saved: 'Saved',
    saveFailed: 'Save failed',
    loadFailed: 'Failed to load settings',
    loadFailedHint: 'Check that the server is running and AUTH_TOKEN is configured correctly.',
    reconfigure: 'Reconfigure',
    askDisplayMode: {
      label: 'Display Mode',
      hint: 'Side panel stays docked on the right. Popup opens a floating dialog.',
      panel: 'Side Panel',
      popup: 'Popup',
    },
    update: {
      checking: 'Checking for updates...',
      upToDate: "You're up to date",
      available: (current: string, latest: string) => `Update available: v${current} → v${latest}`,
      updating: 'Updating MindOS... The server will restart shortly.',
      updatingHint: 'This may take 1–3 minutes. Do not close this page.',
      serverRestarting: 'Server is restarting, please wait...',
      updated: 'Updated successfully! Reloading...',
      timeout: 'Update may still be in progress.',
      timeoutHint: 'The server may need more time to rebuild. Try refreshing.',
      refreshButton: 'Refresh Page',
      retryButton: 'Retry Update',
      error: 'Failed to check for updates. Check your network connection.',
      checkButton: 'Check for Updates',
      updateButton: (version: string) => `Update to v${version}`,
      releaseNotes: 'View release notes',
      hint: 'Updates are installed via npm. Equivalent to running',
      inTerminal: 'in your terminal.',
      desktopDownloading: 'Downloading update...',
      desktopReady: 'Update downloaded. Restart to apply.',
      desktopRestart: 'Restart Now',
      desktopHint: 'Updates are delivered through the Desktop app auto-updater.',
      // Core Hot Update (Desktop only)
      coreTitle: 'MindOS Core',
      coreUpToDate: 'Core is up to date',
      coreAvailable: (size: string) => `Update available (${size})`,
      coreDownloading: 'Downloading...',
      coreCancel: 'Cancel',
      coreReady: 'Ready — restart services to apply',
      coreRestartServices: 'Restart Services',
      coreApplying: 'Applying update...',
      coreApplied: 'Updated! Reloading...',
      coreError: 'Core update failed.',
      coreRetry: 'Retry',
      coreDesktopTooOld: (version: string) => `v${version} requires a newer Desktop version.`,
      coreDesktopTooOldHint: 'Please update MindOS Desktop first.',
      coreHint: 'Core updates only restart services — no app restart needed.',
      shellTitle: 'MindOS Desktop',
      // Update Toast Notification
      updateToast: {
        titleSingle: (type: string, version: string) => `${type} v${version} available`,
        titleMultiple: 'Updates available',
        desktopLabel: 'Desktop',
        coreLabel: 'Core',
        viewDetails: 'View Details',
        skipVersion: 'Skip Version',
        skipAll: 'Skip All',
      },
    },
    uninstall: {
      title: 'Uninstall MindOS',
      descCli: 'Remove MindOS CLI and background services from this machine. Configuration cleanup is optional below.',
      descDesktop: 'Remove MindOS Desktop and background services from this machine. Configuration cleanup is optional below.',
      warning: 'Select what to clean up. Your knowledge base files are always kept safe.',
      stopServices: 'Stop services & remove daemon',
      stopServicesDesc: 'Stop all running MindOS processes and remove the background daemon.',
      removeConfig: 'Remove configuration',
      removeConfigDesc: 'Delete ~/.mindos/ directory (config, logs, PID files).',
      removeNpm: 'Uninstall CLI package',
      removeNpmDesc: 'Run npm uninstall -g @geminilight/mindos.',
      removeApp: 'Move Desktop app to Trash',
      removeAppDesc: 'Move MindOS.app to Trash. You can restore it later if needed.',
      confirmTitle: 'Confirm Uninstall',
      confirmButton: 'Uninstall',
      cancelButton: 'Cancel',
      running: 'Uninstalling...',
      success: 'MindOS has been uninstalled.',
      successDesktop: 'MindOS has been uninstalled. The app will quit now.',
      error: 'Uninstall failed. You can run `mindos uninstall` in terminal manually.',
      nothingSelected: 'Select at least one item to uninstall.',
      kbSafe: 'Your knowledge base files are always safe — they are never deleted by this action.',
    },
  },
} as const;

export const settingsZh = {
  settings: {
    title: '设置',
    tabs: { ai: 'AI', appearance: '外观', knowledge: '通用', sync: '同步', mcp: '连接', plugins: '插件', shortcuts: '快捷键', update: '更新', uninstall: '卸载' },
    ai: {
      provider: '模型服务商',
      apiKey: 'API 密钥',
      keyOptionalHint: '本地服务商可选。存储于 ~/.mindos/config.json',
      envFieldNote: (key: string) => `环境变量 ${key} 已设置。清空此字段将回退到环境变量值。`,
      restoreFromEnv: '从环境变量恢复',
      testKey: '测试',
      testKeyTesting: '测试中...',
      testKeyOk: (ms: number) => `\u2713 ${ms}ms`,
      testKeyAuthError: 'API Key 无效',
      testKeyModelNotFound: '模型不存在',
      testKeyEndpointError: '接口地址或协议不匹配',
      testKeyRateLimited: '请求频率限制，稍后重试',
      testKeyNetworkError: '网络错误',
      testKeyUnknown: '测试失败',
      listModels: '选择模型',
      noModelsFound: '未找到可用模型',
    },
    agent: {
      title: 'Agent 行为',
      subtitle: '配置 AI 代理的运行方式',
      maxSteps: '最大步数',
      maxStepsHint: '每次请求的最大工具调用步数',
      contextStrategy: '上下文策略',
      contextStrategyHint: '自动：上下文填满时摘要早期消息。关闭：不进行摘要（紧急裁剪仍会生效）。',
      contextStrategyAuto: '自动（压缩 + 裁剪）',
      contextStrategyOff: '关闭',
      thinking: '深度思考',
      thinkingHint: '显示 Claude 的推理过程（消耗更多 token）',
      thinkingBudget: '思考预算',
      thinkingBudgetHint: '推理最大 token 数（1000-50000）',
      reconnectRetries: '自动重连',
      reconnectRetriesHint: '连接断开时自动重试次数，重试耗尽后停止（0 = 关闭）',
    },
    embedding: {
      title: '向量搜索',
      description: '基于语义的向量嵌入搜索，按意思查找笔记，不仅限于精确匹配。',
      enable: '启用向量搜索',
      enableHint: '将关键词匹配（BM25）与语义相似度结合使用。',
      providerLocal: '本地',
      providerLocalFree: '免费',
      providerLocalDesc: '在本机运行，无需 API Key',
      providerApi: 'API',
      providerApiDesc: '硅基流动（免费）、OpenAI、DeepSeek 等',
      model: '模型',
      modelHint: '选择模型。较小的模型速度更快。',
      modelName: '嵌入模型名称',
      downloadModel: '安装运行时并下载模型',
      downloading: '正在安装运行时 / 下载模型…',
      starting: '正在启动安装…',
      retry: '重试',
      modelReady: '模型就绪',
      downloadFailedHint: '如果安装或下载持续失败，可切换到 API 模式，或设置环境变量 HF_ENDPOINT=https://hf-mirror.com',
      baseUrl: 'Base URL',
      baseUrlHint: 'OpenAI 兼容的嵌入端点',
      apiKey: 'API Key',
      apiKeyHint: '在服务商网站获取。Ollama 可留空。',
      apiKeyHintLocal: '本地服务可留空',
      indexBuilding: '正在构建嵌入索引…',
      indexReady: (count: number) => `已索引 ${count} 篇文档`,
      indexPending: '索引将在首次搜索时构建',
    },
    webSearch: {
      title: 'Web 搜索',
      description: '配置 web_search 和 fetch_content 工具的搜索服务商。',
      providerAuto: '自动',
      providerAutoDesc: '自动选择最佳可用服务商',
      providerExa: 'Exa',
      providerExaDesc: '神经/语义搜索，每月 1000 次免费',
      providerPerplexity: 'Perplexity',
      providerPerplexityDesc: 'AI 驱动搜索，带摘要',
      providerGemini: 'Gemini',
      providerGeminiDesc: 'Google Gemini 搜索 API',
      exaApiKey: 'Exa API Key',
      perplexityApiKey: 'Perplexity API Key',
      geminiApiKey: 'Gemini API Key',
      apiKeyHint: '可选。留空则自动降级到下一个服务商。',
      noKeysHint: '无需 API Key 也可使用（通过 Exa MCP 零配置）。',
    },
    appearance: {
      readingTitle: '阅读',
      readingDesc: '自定义笔记的阅读体验',
      readingFont: '正文字体',
      fontSize: '字体大小',
      fontSizePreview: '人之初性本善。',
      contentWidth: '内容宽度',
      preferencesTitle: '偏好',
      colorTheme: '颜色主题',
      system: '系统',
      dark: '深色',
      light: '浅色',
      language: '语言',
      browserNote: '外观设置保存在浏览器本地。',
      labsTitle: '实验性功能',
      labsDesc: '仍在开发中的功能，可能会变更或移除。',
      labsEcho: '回响',
      labsEchoDesc: '基于笔记的反思性日记。',
      labsWorkflows: '工作流',
      labsWorkflowsDesc: 'Agent 可视化工作流自动化。',
      fontPreview: '人之初，性本善；性相近，习相远。',
    },
    knowledge: {
      cardTitle: '知识库',
      securityTitle: '安全',
      passwordPlaceholder: '留空可禁用',
      passwordShow: '显示',
      passwordHide: '隐藏',
      tokenNotSet: '— 未设置 —',
      mcpUrl: 'MCP 地址',
      tokenGenerated: '已生成新令牌。请立即复制 — 之后不会再次完整显示。',
      monitoringTitle: '系统监控',
      monitoringFailed: '加载监控数据失败',
      monitorHeap: '堆内存',
      monitorRss: 'RSS',
      monitorUptime: '运行时间',
      monitorNode: 'Node',
      monitorRequests: '请求数',
      monitorToolCalls: '工具调用',
      monitorTokens: 'Token',
      monitorFiles: '文件',
      monitorErrors: '错误',
      monitorMcpRunning: (port: number) => `运行中 :${port}`,
      monitorMcpStopped: '已停止',
      cancel: '取消',
      mindRoot: '知识库根目录',
      mindRootHint: '笔记目录的绝对路径，修改后需要重启服务器。',
      mindRootEnvHint: (key: string) => `MIND_ROOT 环境变量已设置为 "${key}"，填写上方路径可覆盖它。`,
      envNote: 'MIND_ROOT 环境变量已设置。填写上方路径后，你的值优先生效。',
      webPassword: '网页访问密码',
      webPasswordHint: '设置后访问浏览器 UI 需要登录，留空则关闭密码保护。下次刷新页面后生效。',
      webPasswordClear: '清除密码',
      allowNetworkAccess: '允许局域网访问',
      allowNetworkAccessHint: '重启后将 Web UI 绑定到 0.0.0.0，允许同一网络内其他设备连接。不需要远程访问时建议保持关闭。',
      authToken: 'MCP / API 访问令牌',
      authTokenHint: 'Agent 和 MCP 客户端使用的 Bearer Token，浏览器访问无需此项。',
      authTokenNone: '未设置令牌 — API 对所有请求开放。',
      authTokenCopy: '复制',
      authTokenCopied: '已复制！',
      authTokenReset: '重新生成',
      authTokenClear: '清除令牌',
      authTokenResetConfirm: '重新生成令牌？所有 MCP 客户端配置都需要更新。',
      authTokenMcpPort: 'MCP 端口',
      restartWalkthrough: '重新开始引导',
      showHiddenFiles: '显示隐藏文件',
      showHiddenFilesHint: '在文件树中显示以 . 开头的文件夹（.agents、.claude、.mindos 等）。',
      cleanupExamples: '清理示例文件',
      cleanupExamplesHint: '移除知识库中所有模板示例文件（🧪_example_*）。',
      cleanupExamplesButton: '清理',
      cleanupExamplesNone: '没有找到示例文件',
      cleanupExamplesConfirm: (n: number) => `删除 ${n} 个示例文件？此操作不可撤销。`,
      cleanupExamplesDone: (n: number) => `已移除 ${n} 个示例文件`,
      cleanupExamplesScanning: '扫描中...',
    },
    sync: {
      emptyTitle: '跨设备同步',
      emptyDesc: '通过 Git 自动同步知识库到所有设备。',
      setupIntroTitle: '从一个私有 Git 仓库开始',
      setupStepRepo: '先创建一个空的私有仓库',
      setupStepUrl: '粘贴 SSH 或 HTTPS 地址',
      setupStepToken: '私有仓库使用 HTTPS 时可填写令牌',
      featureAutoCommit: '保存时自动提交',
      featureAutoPull: '自动拉取远程更新',
      featureConflict: '冲突检测',
      featureMultiDevice: '多设备同步',
      remoteUrl: 'Git 远程仓库 URL',
      invalidUrl: '无效的 Git URL — 请使用 HTTPS (https://...) 或 SSH (git@... / ssh://git@...) 格式',
      sshBrief: '一次配置，无需令牌',
      httpsBrief: '通用性强；私有仓库可填写令牌',
      sshHint: '需要本机已配置 SSH 密钥。请用对应 Git host 验证。',
      sshHintForHost: (host: string) => `需要本机已配置 SSH 密钥。验证命令：ssh -T git@${host}`,
      accessToken: '访问令牌',
      requiredForPrivateHttps: '（可选；私有 HTTPS 仓库通常需要）',
      tokenHint: '公开仓库或本机已有 Git 凭据时可不填。私有 GitHub/GitLab HTTPS 仓库通常需要令牌。',
      tokenLink: '创建令牌（勾选 repo 权限）',
      showToken: '显示令牌',
      hideToken: '隐藏令牌',
      branchLabel: '分支',
      invalidBranch: '分支名必须是有效 Git ref：不能包含空格、首尾斜杠、".."、"@{"、".lock" 或 Git ref 控制字符。',
      connectButton: '连接并开始同步',
      connectNeedsUrl: '粘贴远程仓库 URL 后继续',
      connectFixUrl: '修正 Git URL 后继续',
      connectFixBranch: '请输入有效的 Git 分支名',
      connectingTo: (remote: string) => `正在连接 ${remote}`,
      cancel: '取消',
      stopWaiting: '停止等待',
      hideProgress: '隐藏进度',
      initStillRunningTitle: '同步配置仍在运行',
      initStillRunningDesc: 'MindOS 正在后台配置仓库。请等待这次操作完成后，再开始新的同步配置。',
      connecting: '连接中...',
      stepConnecting: '正在连接远程仓库...',
      stepAuthenticating: '正在验证身份...',
      stepSyncing: '正在同步数据...',
      stepAlmostDone: '即将完成...',
      stepDone: '同步配置成功！',
      timeoutError: '连接超时。远程仓库可能较大，或当前网络较慢。请稍后重试。',
      gitignoreTitle: '排除文件',
      gitignorePlaceholder: '# 不同步的文件\n*.tmp\nsecret/',
      gitignoreSave: '保存',
      gitignoreSaved: '已保存',
      gitignoreLoadFailed: '加载 .gitignore 失败',
      gitignoreSaveFailed: '保存 .gitignore 失败',
      gitignoreStoppedTracking: (n: number) => `${n} 个已同步文件会从后续同步中移除`,
      gitignoreStoppedTrackingHint: '文件仍保留在本机。下一次同步会把它从远端当前文件树移除；旧的 Git 历史中可能仍有之前的副本。',
      syncStatusRefreshFailed: '已保存，但刷新同步状态失败',
      remoteBackupMissing: '远程备份不可用',
      remoteBackupMissingHint: '远程版本没有成功保存为预览文件，因此不能在界面中直接应用。',
      remoteDeleted: '远程已删除',
      localDeleted: '本地已删除',
      keepRemoteDeletedHint: '接受远程删除这个文件',
      remoteDeletedPreview: '（远程已删除）',
      conflictExplain: '这些文件在本机和远程都被修改了。请选择保留哪个版本。',
      keepLocal: '保留本地',
      keepRemote: '保留远程',
      confirmKeepLocal: '确认保留本地？',
      keepLocalHint: '保留本机的版本',
      keepRemoteHint: '替换为远程版本',
      viewDiff: '点击查看两个版本的差异',
      viewDiffFirst: '先查看差异',
      conflictPreviewFailed: '加载冲突预览失败',
      conflictResolveFailed: '解决冲突失败',
      conflictResolvedRefreshFailed: '冲突解决结果可能已经保存，但 MindOS 无法刷新同步状态。继续操作前请先重试刷新状态。',
      previewEmptyState: '尚未加载预览。',
      retry: '重试',
      localVersion: '本地（本机）',
      remoteVersion: '远程',
      emptyFile: '（空）',
      sectionTitle: '同步',
      repositoryTitle: '仓库',
      automationTitle: '自动同步',
      automationDesc: 'MindOS 会在你工作时后台持续同步。',
      automationPausedDesc: '这些间隔设置会在启用自动同步后生效。',
      autoCommitLabel: '每隔多久保存改动',
      autoPullLabel: '每隔多久检查远程更新',
      healthSyncedTitle: '所有笔记都已备份',
      healthSyncedDesc: (time: string) => `最后同步：${time}。`,
      healthSyncedNext: '下一步：继续写作',
      healthReadyTitle: '同步已就绪',
      healthReadyDesc: '还没有完成过同步。',
      healthReadyNext: '点击立即同步来创建第一次备份',
      healthUnpushedTitle: (n: number) => `${n} 个本地改动待上传`,
      healthUnpushedDesc: 'MindOS 会自动上传，也可以手动立即同步。',
      healthUnpushedNext: '下一步：立即同步或继续工作',
      healthPausedUnpushedTitle: (n: number) => `${n} 个本地改动等待处理`,
      healthPausedUnpushedDesc: '自动同步已暂停。这些改动需要手动同步或重新启用自动同步后才会上传。',
      healthPausedUnpushedNext: '下一步：立即同步或启用自动同步',
      healthUnknownTitle: '同步状态未知',
      healthUnknownDesc: 'MindOS 暂时无法确认本地改动是否已经上传。',
      healthUnknownNext: '下一步：重试同步或检查远程仓库',
      healthPausedUnknownDesc: '自动同步已暂停，且 MindOS 暂时无法确认本地改动是否已经上传。',
      healthPausedUnknownNext: '下一步：启用自动同步或重试刷新状态',
      healthPausedTitle: '同步已暂停',
      healthPausedDesc: '这个仓库已禁用自动同步，但现有 Git 配置仍然保留。',
      healthPausedNext: '下一步：手动立即同步，或启用自动同步来后台备份',
      healthConflictsTitle: '解决冲突后才能完成同步',
      healthConflictsDesc: (n: number) => `下面有 ${n} 个文件需要比较本地和远程版本，然后选择保留哪一个。`,
      healthConflictsNext: '下一步：选择要保留的版本',
      healthErrorTitle: '同步需要处理',
      healthErrorNext: '下一步：修复问题后再次同步',
      healthStaleTitle: '同步状态可能已过期',
      healthStaleNext: '下一步：先重试刷新状态，再判断当前备份状态',
      brokenTitle: '同步配置已损坏',
      brokenDesc: 'Git 仓库或远程地址缺失。请重置后重新配置。',
      resetFailed: '重置同步配置失败',
      labelProvider: '提供商',
      labelRemote: '远程',
      labelBranch: '分支',
      labelLastSync: '最后同步',
      labelNoSyncYet: '尚未同步',
      labelUnpushed: '本地改动',
      labelUnknown: '未知',
      labelAutoSync: '自动同步',
      labelEnabled: '启用中',
      labelPaused: '已暂停',
      unpushedCommits: (n: number) => `${n} 个改动`,
      syncNow: '立即同步',
      disableAutoSync: '禁用自动同步',
      enableAutoSync: '启用自动同步',
      changeRepositoryButton: '更换仓库',
      changeRepositoryConfirm: '确认更换仓库？',
      changeRepositoryHelp: '会停止自动同步并回到配置界面，方便连接另一个远程仓库。本机笔记和 Git 历史都会保留。',
      syncComplete: '同步完成',
      syncFailed: '同步失败',
      syncLocked: '同步正在运行',
      hintSyncLocked: '另一个同步操作正在运行。稍等片刻后再试。',
      hintSshAuth: 'SSH 密钥可能未配置。请检查这个 Git host 对应的 SSH key。',
      hintSshAuthForHost: (host: string) => `SSH 密钥可能未配置。请运行：ssh-keygen -t ed25519 && ssh -T git@${host}`,
      hintSshHost: '请用 ssh-keyscan 把这个 Git host 加入 ~/.ssh/known_hosts。',
      hintSshHostForHost: (host: string) => `请运行：ssh-keyscan ${host} >> ~/.ssh/known_hosts`,
      hintHttpsAuth: '访问令牌或 Git 凭据可能已过期或未填写。请检查这个 Git host 的凭据设置。',
      hintHttpsAuthForHost: (host: string) => {
        if (host.includes('github.com')) return '访问令牌可能已过期或未填写。请检查 GitHub Developer settings -> Personal access tokens。';
        if (host.includes('gitlab.com')) return '访问令牌可能已过期或未填写。请检查 GitLab User Settings -> Access Tokens。';
        return `访问令牌或 Git 凭据可能已过期或未填写。请检查 ${host} 的凭据设置。`;
      },
      hintNetwork: '请检查网络连接后重试。',
      hintNotFound: '未找到仓库。请检查 URL，并确认该仓库存在且你有权限访问。',
      hintPushRejected: '远程已有新改动。点击“立即同步”先拉取并重试。',
      hintConflict: '检测到合并冲突。请查看下面的冲突区域。',
      settingsSaving: '正在保存同步设置...',
      settingsSaved: '同步设置已保存',
      statusRefreshFailed: '改动可能已经保存，但 MindOS 无法刷新同步状态。继续操作前请先重试刷新状态。',
      statusRefreshRequired: '同步状态已过期。修改同步设置前请先重试刷新状态。',
      resolveConflictsBeforeSettings: '解决冲突后才能修改同步设置。',
      loadFailedTitle: '无法加载同步状态',
      resetButton: '忘记本地同步设置',
      resetConfirm: '确认忘记设置？',
      resetHelp: '不会删除笔记或 Git 仓库，只会清空 MindOS 的同步设置，之后可重新连接。',
      notConfigured: '（未配置）',
      autoSyncDisabled: '已禁用自动同步',
      autoSyncEnabled: '已启用自动同步',
      toggleFailed: '切换同步失败',
      conflictsTitle: (n: number) => `冲突 (${n})`,
      conflictSectionDesc: '逐个查看下面的文件。再次同步前，需要选择保留哪个版本。',
      timeNever: '从未',
      timeUnknown: '未知',
      timeJustNow: '刚刚',
      timeMinAgo: (m: number) => `${m} 分钟前`,
      timeHourAgo: (h: number) => `${h} 小时前`,
      timeDayAgo: (d: number) => `${d} 天前`,
    },
    plugins: {
      title: '已安装渲染器',
      builtinBadge: '内置',
      coreBadge: '核心',
      enabled: '已启用',
      disabled: '已禁用',
      matchHint: '自动匹配',
      coreHint: '核心渲染器 — 始终启用',
      noPlugins: '暂无渲染器。',
      comingSoon: '插件市场即将上线。',
    },
    mcp: {
      // 连接模式卡片
      modeCardTitle: '连接模式',
      modeCardDesc: '选择 Agent 如何连接到 MindOS。',
      cliLabel: 'CLI',
      cliModeDesc: 'Claude Code、Gemini CLI、Codex 等。',
      mcpLabel: 'MCP',
      mcpModeDesc: 'Claude Desktop、Cursor、Windsurf 等。',
      alwaysOn: '始终开启',
      mcpRunning: '运行中',
      mcpStopped: '已停止',
      mcpEnabledHint: 'MCP 模式已启用。若仅使用 CLI Agent，可禁用此项以简化界面。',
      mcpDisabledHint: '启用 MCP 以连接 Claude Desktop 或 Cursor 等桌面客户端。',
      // 其余 MCP 配置...
      serverTitle: 'MindOS MCP 服务',
      status: '状态',
      running: '运行中',
      stopped: '已停止',
      transport: '传输方式',
      endpoint: '端点',
      tools: '工具',
      toolsRegistered: (n: number) => `已注册 ${n} 个`,
      auth: '认证',
      authSet: '已设置 Token',
      authNotSet: '未设置',
      copyEndpoint: '复制端点',
      copyConfig: '复制配置',
      copied: '已复制！',
      agentsTitle: 'Agent 配置',
      agent: 'Agent',
      scope: '范围',
      project: '项目',
      global: '全局',
      installed: '已安装',
      notInstalled: '未安装',
      detected: '已检测',
      notFound: '未找到',
      connectedGroup: '已连接',
      detectedGroup: '已检测',
      notFoundGroup: '未安装',
      tagConnected: '已连接',
      transportStdio: 'stdio（推荐）',
      transportHttp: 'http',
      transportAuto: '自动（推荐）',
      httpUrl: 'MCP URL',
      httpToken: '认证 Token',
      installSelected: '安装选中',
      installing: '安装中...',
      installSuccess: (n: number) => `已配置 ${n} 个 agent`,
      installFailed: '安装失败',
      portLabel: 'MCP 端口',
      portHint: '修改后需重启服务',
      skillsTitle: '技能',
      skillsDesc: '教 Agent 如何操作你的知识库。',
      skillAutoLoaded: '每次请求自动加载',
      skillSource: '来源',
      skillBuiltin: '内置',
      skillUser: '自定义',
      addSkill: '+ 添加技能',
      cliInstallHint: '通过命令行安装：',
      skillPathHint: '技能文件安装路径：',
      deleteSkill: '删除',
      editSkill: '编辑',
      saveSkill: '保存',
      cancelSkill: '取消',
      skillName: '名称',
      skillDesc: '描述',
      skillContent: '内容',
      skillNameConflict: '同名技能已存在',
      skillDeleteConfirm: (name: string) => `确定删除「${name}」？此操作不可撤销。`,
      skillLanguage: '技能语言',
      skillLangEn: 'English',
      skillLangZh: '中文',
      searchSkills: '搜索技能...',
      customGroup: '自定义',
      builtinGroup: '内置',
      noSkillsMatch: (query: string) => `没有匹配「${query}」的技能`,
      skillSearchPaths: '技能搜索路径',
      skillAgentsDir: '外部 Agent 技能 (~/.agents/skills)',
      skillCustomPaths: '自定义路径',
      skillAddPath: '+ 添加路径',
      skillPathSaved: '技能路径已保存',
      skillPathPlaceholder: '输入目录路径...',
      skillPathRemove: '移除',
      skillTemplate: '模板',
      skillTemplateGeneral: '通用',
      skillTemplateToolUse: '工具调用',
      skillTemplateWorkflow: '工作流',
      selectDetected: '选择已检测',
      clearSelection: '清除',
      quickSetup: '快速配置',
      configureFor: '配置目标',
      configPath: '配置路径',
      transportLocal: '本地',
      transportRemote: '远程',
      transportLocalHint: '本地 — 与 MindOS 服务在同一台机器上',
      transportRemoteHint: '远程 — 从其他设备通过 HTTP 连接',
      remoteDetectedHint: '使用当前远程 IP。',
      remoteManualHint: '将 127.0.0.1 替换为服务器的公网或局域网 IP。',
      remoteSteps: '从其他设备连接：① 在防火墙/安全组中开放端口 {port} ② 将下方配置粘贴到 Agent 中 ③ 公网环境建议使用 SSH 隧道加密传输。',
      noAuthWarning: '⚠ 未设置认证令牌 — 请先在 设置 → 通用 中配置，再启用远程访问。',
      showJson: '显示 JSON',
      hideJson: '隐藏 JSON',
      connectionTitle: '连接 Agent',
      connectionHint: '选择 AI Agent 连接 MindOS 的方式。',
      tokenCardTitle: '认证令牌',
      tokenCardDesc: '用于 CLI 远程模式和 MCP 连接。',
      mcpHint: '适用于 Claude Desktop、Cursor 等使用 MCP 工具协议的 Agent。',
      tokenLabel: '认证令牌',
      tokenMasked: '点击「显示」查看完整令牌',
      tokenShow: '显示',
      tokenHide: '隐藏',
      tokenCopy: '复制',
      tokenCopied: '令牌已复制！',
      tokenRevealFailed: '无法显示令牌',
      tokenNone: '未设置令牌 — MCP 服务对所有请求开放。',
      tokenNoneAction: '请在 设置 → 通用 → 安全 中生成令牌。',
      serverUrl: 'MCP 服务地址',
      serverUrlCopy: '复制地址',
      howToConnect: '如何连接 AI 助手',
      howToStep1: '打开你的 AI 助手的 MCP 设置（如 Claude Code、Cursor）',
      howToStep2: '添加一个新的 MCP 服务，填入上方地址',
      howToStep3: '将认证令牌设为 Bearer Token',
      howToStep4: '保存并验证连接',
      // CLI Skill
      cliSkillTitle: 'CLI 技能',
      cliSkillHint: '适用于支持 bash 的 Agent（Claude Code、Gemini CLI、Codex）——更省 token，无需 MCP。',
      cliSkillDesc: '更省 token，技能内置——安装即可使用。',
      cliLocalDesc: 'MindOS Skill 已内置，安装 CLI 即可直接使用。',
      cliRemoteDesc: '在其他设备上安装 CLI，远程连接到此 MindOS 服务器。',
      cliSkillInstall: '安装',
      cliSkillInstallCmd: 'npm install -g @geminilight/mindos',
      cliSkillRemote: '远程',
      cliSkillVerify: '验证',
      cliSkillVerifyCmd: 'mindos file list',
      cliRemoteConfigure: '配置',
      cliInstallSkill: '安装技能',
      cliAgents: 'Claude Code · Gemini CLI · Codex',
      mcpAgents: 'Claude Desktop · Cursor',
      mcpDesc: '需要逐个 Agent 配置 MCP，通过以下命令单独安装技能：',
      mcpLocalDesc: '复制下方配置代码，粘贴到你的 Agent 的 MCP 设置中。',
      mcpRunningLabel: 'MCP 运行中',
      mcpServerStatus: 'MCP 服务',
      autoInstallAgents: '自动安装到已检测的 Agent',
      detectedAgentsTitle: '检测到的 Agent',
      cliInstallDesc: '为你的 Agent 安装 MindOS Skill，让它能操作你的知识库。',
      mcpInstallDesc: '为本机检测到的 Agent 安装 MCP 配置和 Skill。',
      tokenCopyFullHint: '复制完整令牌',
      skillsInstalled: '个技能已安装',
      recommended: '推荐',
      localTitle: '本机',
      localReady: '可直接使用',
      remoteTitle: '远程访问',
      remoteSubtitle: '从其他设备连接',
      restarting: '重启中...',
      restart: '重启',
      // Server Ports Card
      portsCardTitle: '服务端口',
      portsCardDesc: 'Web UI 和 MCP 服务端口。更改后重启生效。',
      webPortLabel: 'Web UI 端口',
      webPortHint: '浏览器访问的端口。',
      mcpPortLabel: 'MCP 服务端口',
      mcpPortHint: 'Agent 和桌面客户端连接的端口。',
      portChecking: '检测中…',
      portAvailable: '可用',
      portSelf: '当前端口',
      portInUse: (p: number) => `端口 ${p} 已被占用`,
      portSuggest: (p: number | null) => `使用 ${p}`,
      portConflict: 'Web 和 MCP 端口不能相同。',
      portUpdating: '保存中…',
      portWebRestarting: '正在重启服务…',
      portMcpRestarting: '正在重启 MCP…',
      portUpdateSuccess: '端口更新成功。',
      portUpdateFailed: '端口更新失败。',
      portRestartTimeout: '重启超时，请重试。',
      portRedirecting: '正在跳转到新地址…',
      portUpdateBtn: '更新端口',
      externalToolsTitle: '外部 MCP 工具',
      externalToolsDesc: '配置外部 MCP 服务器的工具访问模式。',
    },
    save: '保存',
    saved: '已保存',
    saveFailed: '保存失败',
    loadFailed: '加载设置失败',
    loadFailedHint: '请确认服务正在运行，且 AUTH_TOKEN 配置正确。',
    reconfigure: '重新配置',
    askDisplayMode: {
      label: '显示模式',
      hint: '侧面板固定在右侧；弹窗以浮动对话框形式打开。',
      panel: '侧面板',
      popup: '弹窗',
    },
    update: {
      checking: '正在检查更新...',
      upToDate: '已是最新版本',
      available: (current: string, latest: string) => `有新版本可用：v${current} → v${latest}`,
      updating: '正在更新 MindOS，服务器即将重启...',
      updatingHint: '预计 1–3 分钟，请勿关闭此页面。',
      serverRestarting: '服务正在重启，请稍候...',
      updated: '更新成功！正在刷新...',
      timeout: '更新可能仍在进行中。',
      timeoutHint: '服务器可能需要更多时间重新构建，请尝试刷新页面。',
      refreshButton: '刷新页面',
      retryButton: '重试更新',
      error: '检查更新失败，请检查网络连接。',
      checkButton: '检查更新',
      updateButton: (version: string) => `更新到 v${version}`,
      releaseNotes: '查看更新日志',
      hint: '更新通过 npm 安装，等同于在终端运行',
      inTerminal: '。',
      desktopDownloading: '正在下载更新...',
      desktopReady: '更新已下载，重启后生效。',
      desktopRestart: '立即重启',
      desktopHint: '更新通过桌面端自动更新推送。',
      // Core Hot Update
      coreTitle: 'MindOS Core',
      coreUpToDate: '核心已是最新',
      coreAvailable: (size: string) => `有新版本可用（${size}）`,
      coreDownloading: '下载中...',
      coreCancel: '取消',
      coreReady: '已就绪 — 重启服务即可生效',
      coreRestartServices: '重启服务',
      coreApplying: '正在应用更新...',
      coreApplied: '更新成功！正在刷新...',
      coreError: '核心更新失败。',
      coreRetry: '重试',
      coreDesktopTooOld: (version: string) => `v${version} 需要更新版本的 Desktop。`,
      coreDesktopTooOldHint: '请先更新 MindOS Desktop。',
      coreHint: '核心更新只需重启服务，无需重启应用。',
      shellTitle: 'MindOS Desktop',
      // Update Toast Notification
      updateToast: {
        titleSingle: (type: string, version: string) => `${type} v${version} 可用`,
        titleMultiple: '有可用更新',
        desktopLabel: '桌面版',
        coreLabel: '运行时',
        viewDetails: '查看详情',
        skipVersion: '跳过此版本',
        skipAll: '全部跳过',
      },
    },
    uninstall: {
      title: '卸载 MindOS',
      descCli: '从本机移除 MindOS CLI 和后台服务。配置清理可在下方单独选择。',
      descDesktop: '从本机移除 MindOS Desktop 和后台服务。配置清理可在下方单独选择。',
      warning: '选择要清理的内容。你的知识库文件始终是安全的。',
      stopServices: '停止服务并移除守护进程',
      stopServicesDesc: '停止所有运行中的 MindOS 进程并移除后台守护进程。',
      removeConfig: '移除配置',
      removeConfigDesc: '删除 ~/.mindos/ 目录（配置、日志、PID 文件）。',
      removeNpm: '卸载 CLI 包',
      removeNpmDesc: '执行 npm uninstall -g @geminilight/mindos。',
      removeApp: '将 Desktop 移入废纸篓',
      removeAppDesc: '将 MindOS.app 移入废纸篓，之后可以恢复。',
      confirmTitle: '确认卸载',
      confirmButton: '卸载',
      cancelButton: '取消',
      running: '正在卸载...',
      success: 'MindOS 已卸载。',
      successDesktop: 'MindOS 已卸载，应用即将退出。',
      error: '卸载失败，可在终端手动运行 `mindos uninstall`。',
      nothingSelected: '请至少选择一项要卸载的内容。',
      kbSafe: '你的知识库文件始终是安全的——此操作绝不会删除它们。',
    },
  },
};
