export default {
  settings: {
    // ===== Page title =====
    title: '⚙️ Settings',

    // ===== Left nav categories (phase 3 master-detail) =====
    navAppearance: 'Appearance',
    navAiModel: 'AI Models',
    navKnowledge: 'Knowledge',
    navPerformance: 'Performance',
    navSecurity: 'Security',
    navAdvanced: 'Advanced',

    // ===== Settings search (phase 4) =====
    searchPlaceholder: 'Search settings…',
    searchNoResult: 'No results',

    // ===== Instant feedback (phase 5 SettingRow) =====
    savedHint: '✓ Saved',
    nextRoundBadge: 'Next message',

    // ===== Connection mgmt (phase 7: experimental badge, not wired to AI yet) =====
    experimentalBadge: 'Experimental · not wired to AI tools',

    // ===== AI Provider panel =====
    panelAiProvider: '🤖 AI Model Config',
    addProvider: '+ Add Provider',
    editProviderTitle: 'Edit Provider',
    addProviderTitle: 'Add Provider',
    emptyProvider: 'No AI provider. Click above to add.',
    badgeDefault: 'Default',
    actionSetDefault: 'Set as default',
    detailBaseUrl: 'Base URL',
    detailModel: 'Model',
    detailApiKey: 'API Key',
    detailPoolEnabled: 'In load-balance pool',
    detailPoolWeight: 'Pool selection weight',
    badgePoolDisabled: 'Disabled',
    descPoolEnabled: 'When on, participates in main-chain routing/pool selection; off = config retained but never selected',
    descPoolWeight: '0-100, higher weight preferred as primary; equal weights ~ round-robin (backend clamps [0,100])',
    toastPoolUpdateOk: 'Load-balance pool config updated',
    toastPoolUpdateFail: 'Failed to update pool config: {msg}',

    // Provider form
    labelName: 'Name',
    labelPreset: 'Vendor preset',
    presetCustom: 'Custom (manual)',
    labelProviderType: 'Protocol',
    labelBaseUrl: 'Base URL',
    labelApiKey: 'API Key',
    labelDefaultModel: 'Default',
    phProviderName: 'e.g. DeepSeek, GLM-4',
    phBaseUrl: 'https://api.deepseek.com',
    phApiKey: 'sk-...',
    phDefaultModel: 'deepseek-chat',
    // Direction A (lightweight): defaultModel is only a "suggested starting point";
    // guide users to hit "Test connection" to pull the vendor's real model list and overwrite,
    // avoiding stale preset model ids (DeepSeek chat deprecated / Gemini 2.5→3.5 etc.) misleading them.
    defaultModelHint: 'Suggested starting point — hit "Test connection" to pull the vendor’s real model list and overwrite',
    providerTypeOpenaiCompat: 'OpenAI-compatible (DeepSeek / GLM v4 / OpenAI)',
    providerTypeAnthropic: 'Anthropic-compatible (GLM subscription / Claude)',
    saving: 'Saving...',

    // Model fetch (F-01 phase 6)
    testConnection: 'Test connection & fetch models',
    fetchingModels: 'Fetching...',
    fetchHintSaveFirst: 'Save the provider first, then fetch models',
    labelWeight: 'Weight',
    modelListTitle: 'Fetched models ({count})',
    modelListHint: 'After toggling enabled / weight, click "Save" below to write them into the provider config; the next "Test connection" overwrites with fresh probe results',
    saveModels: 'Save model config',
    modelListUnsavedHint: 'Model list has unsaved changes (enabled / weight) — closing or navigating away will discard them',
    toastFetchOk: 'Fetched {count} models',
    toastFetchFail: 'Fetch failed: {msg}',
    fetchFailedTimeout: 'Fetch timed out, check that the Base URL is reachable: {msg}',
    fetchFailedAuth: 'Authentication failed, check your API Key: {msg}',
    fetchFailedNotFound: 'Endpoint not found, this vendor may not support model listing: {msg}',
    toastModelEditLocalOnly: 'Enabled / weight are local edits, overwritten on next fetch',

    // Model trait tags (modality + capability + probe source; cost/intel 去除见 UX-260618-04)
    tagModality: { text: 'Text', vision: 'Vision', audio: 'Audio', video: 'Video' },
    tagCapability: { tool_use: 'Tool use', embedding: 'Embedding', code_gen: 'Code' },
    tagSource: { user_set: 'Manual', preset_table: 'Preset', heuristic: 'Heuristic', default: 'Default' },

    // ===== Connection panel =====
    panelConnection: '🔗 Connections',
    addConnection: '+ Add connection',
    editConnectionTitle: 'Edit connection',
    addConnectionTitle: 'Add connection',
    emptyConnection: 'No connection yet. Click the button above to add one.',
    labelType: 'Type',
    labelHost: 'Host',
    labelPort: 'Port',
    labelUser: 'Username',
    phConnName: 'flux_dev',
    phHost: '127.0.0.1',
    phPort: '3306',
    phUser: 'root',

    // ===== General settings panel =====
    panelGeneral: '🎨 General',
    // 阶段2 UX 重构:GeneralPanel 拆 3 Section 后各 Section 标题
    sectionAppearance: '🎨 Appearance',
    sectionPerformance: '⚡ Performance',
    sectionAdvanced: '⚙️ Advanced',
    labelTheme: 'Theme',
    descTheme: 'Dark / light',
    themeDark: '🌙 Dark',
    themeLight: '☀️ Light',
    themeSystem: '💻 System',

    labelLanguage: 'Language',
    descLanguage: 'Interface language',

    labelAiLanguage: 'AI language',
    descAiLanguage: 'Default AI reply language',
    aiLanguageAuto: '🔄 Follow interface language',
    aiLanguageZh: '🇨🇳 简体中文',
    aiLanguageEn: '🇺🇸 English',

    labelDataDir: 'App Data Directory',
    descDataDir: 'Where DevFlow stores .trash (recycle bin), database, logs and other internal data',

    labelAutoExecute: 'AI auto-execute scope',
    descAutoExecute: 'Control risk level AI auto-executes (low/medium/all-takeover)',
    autoModeLow: 'Low risk (default)',
    autoModeMedium: 'Include medium',
    autoModeAll: 'Full takeover (no approval)',
    autoModeAllConfirmTitle: 'Confirm full AI takeover?',
    autoModeAllConfirmContent: 'All actions (including high-risk) will be auto-executed without approval. AI may directly perform dangerous operations (delete files / run arbitrary commands, etc.). Confirm only if you trust the current conversation AI.',

    labelLogLevel: 'Log level',
    descLogLevel: 'Verbosity of workflow logs',

    // ===== Approval timeout =====
    labelApprovalTimeout: 'Approval timeout',
    descApprovalTimeout: 'Auto-reject threshold when user does not respond to an approval prompt (only affects approvals started after the change)',
    approvalTimeoutUnlimited: 'No limit',
    approvalTimeout5m: '5 minutes',
    approvalTimeout15m: '15 minutes (default)',
    approvalTimeout30m: '30 minutes',
    approvalTimeout60m: '60 minutes',

    labelShowTokenUsage: 'Show token usage',
    descShowTokenUsage: 'Show token consumption of each reply in conversations',

    labelCustomPrompt: 'Custom prompt',
    descCustomPrompt: 'Appended to the AI system prompt to customize AI behavior',
    placeholderCustomPrompt: 'e.g.: You specialize in Rust development questions...',

    labelStreamingMd: 'Streaming Markdown rendering',
    descStreamingMd: 'Render code blocks/lists/headings during streaming (unclosed code blocks degrade to plain text to avoid flicker); when off, only plain text is shown during streaming and full formatting applies after generation completes',

    labelGlobalConcurrency: 'Global max concurrency',
    descGlobalConcurrency: 'Shared cap on simultaneous LLM requests across all conversations',

    labelPerConvConcurrency: 'Per-conversation concurrency',
    descPerConvConcurrency: 'Concurrent LLM calls within one conversation (main loop / title / distill shared)',

    labelAgentMaxIterations: 'Agent max iterations',
    descAgentMaxIterations: 'Max rounds of the agentic loop (stream → tool → feedback) (0=unlimited, 1-50, default 10); changes take effect on the next message',
    labelUnlimited: 'Unlimited',

    labelAgentMaxRetries: 'Stream failure retries',
    descAgentMaxRetries: 'Auto-retry count on stream failure (0-10, default 3); only retries pre-stream failures (no token output yet); mid-stream failures are abandoned',

    // ===== F-260619-03 Phase A: AI tool allowed dirs panel =====
    panelAllowedDirs: '📁 AI Tool Allowed Dirs',
    descAllowedDirs: 'AI file tools (read/write/list/patch/search) can only access the following authorized directories. The project root (devflow itself) is always implicitly authorized and need not be added. Access to directories not in the list will be rejected.',
    allowedDirsLoading: 'Loading…',
    allowedDirsEmpty: 'No extra authorized directories (only project root is authorized by default)',
    allowedDirsInputPlaceholder: 'Enter absolute path, e.g. E:/wk-lab/u-abc',
    allowedDirsSelectDir: 'Select Dir',
    allowedDirsAdd: 'Add',
    allowedDirsSave: 'Save',
    allowedDirsReload: 'Reload',
    allowedDirsLoadFail: 'Failed to load authorized directories',
    allowedDirsDup: 'This directory is already in the authorized list',
    allowedDirsAddFail: 'Failed to add authorized directory',
    allowedDirsRemoveFail: 'Failed to remove authorized directory',

    // ===== ScriptNode command execution safety =====
    panelScriptSafety: '🛡️ Command Execution Safety',
    descScriptSafety: 'Configure ScriptNode command whitelist/blacklist. Command name is the first token (e.g. `rm -rf /` -> `rm`), compared trimmed and lowercase. Blacklist takes precedence over whitelist.',
    labelScriptWhitelist: 'Command whitelist',
    descScriptWhitelist: 'Comma-separated command names (e.g. git,npm,cargo); empty = unrestricted. When non-empty, only listed commands are allowed.',
    labelScriptBlacklist: 'Command blacklist',
    descScriptBlacklist: 'Comma-separated command names (e.g. rm,format,shutdown); any match rejects execution.',
    placeholderScriptWhitelist: 'Leave empty for no restriction, or: git,npm,cargo',
    placeholderScriptBlacklist: 'Leave empty for no blacklist, or: rm,format',
    noteScriptSafety: 'Note: backend ScriptNode currently reads DF_SCRIPT_WHITELIST / DF_SCRIPT_BLACKLIST env vars (same comma-separated semantics). This UI only persists on the frontend; wiring to backend is planned for a later release.',

    // ===== Knowledge base panel =====
    panelKnowledge: '📚 Knowledge base',
    labelAutoExtract: 'Auto-distill knowledge',
    descAutoExtract: 'Automatically distill reusable knowledge from conversations after they finish (AI proposes candidates, manual review required)',
    labelTriggerMode: 'Distill trigger',
    descTriggerMode: 'When auto-distillation is triggered',
    triggerOnComplete: 'On conversation complete',
    triggerManualOnly: 'Manual only',
    labelMinMessages: 'Min message count',
    descMinMessages: 'Distillation triggers only after this many messages (filters out small talk noise)',
    labelAutoInject: 'Auto-inject related knowledge',
    descAutoInject: 'Retrieve related knowledge and inject it into the conversation context during chat',
    labelVectorEnabled: 'Semantic retrieval (vector)',
    descVectorEnabled: 'Use Embedding vectors for semantic matching — close meanings surface even with different wording; when off, pure keyword matching with zero external calls',
    labelEmbeddingProvider: 'Embedding provider',
    descEmbeddingProvider: 'AI provider used for vectorization (OpenAI-compatible only; switching requires re-embedding all knowledge)',
    labelEmbeddingModel: 'Embedding model',
    descEmbeddingModel: 'e.g. embedding-3 (Zhipu) / text-embedding-v4 (Alibaba) / text-embedding-3-small (OpenAI)',
    embeddingProviderNone: 'Not selected',
    phEmbeddingModel: 'embedding-3',

    // ===== Toast =====
    toastLoadProviderFail: 'Failed to load providers',
    toastSaveIncomplete: 'Please fill in all fields (Name / Base URL / API Key / Model)',
    // L19: confirm before discarding an edited form
    confirmDiscardUnsaved: 'The form has unsaved changes. Discard them?',
    toastSaved: 'Saved',
    toastSaveFail: 'Save failed: {msg}',
    // P0-2: save-failure classified guidance (persistent banner, not raw Err text)
    saveErrKeyringTitle: 'Failed to write key to the OS keychain',
    saveErrKeyringDetail: 'Original config left unchanged. Backend reason: {msg}\nSuggestion: check the OS keychain/credential store permissions (Windows Credential Manager / macOS Keychain / Linux secret-service daemon), then click "Save" again to retry.',
    saveErrGenericTitle: 'Failed to save provider config',
    saveErrGenericDetail: 'Backend reason: {msg}\nSuggestion: double-check the form fields (Name / Base URL / Model), then click "Save" again to retry; check the logs if it keeps failing.',
    toastDeleted: 'Deleted',
    toastDeleteFail: 'Delete failed: {msg}',
    toastSetDefaultOk: 'Set as default',
    toastSetDefaultFail: 'Failed to set default: {msg}',
    toastConnIncomplete: 'Please fill in Name and Host',
    toastConnPortInvalid: 'Port must be between 1 and 65535',

    // ===== Import / Export (phase 6) =====
    export: 'Export',
    import: 'Import',
    exportHint: 'Export all preferences (appSettings + knowledge config) as a JSON file',
    importHint: 'Import from a JSON file and overwrite current preferences',
    importConfirm: 'Importing will overwrite all current preferences (appearance / performance / knowledge, etc.). Continue?',
    importSuccess: 'Imported successfully (some items like concurrency / iterations take effect after restart or next message)',
    importFail: 'Import failed: {msg}',
    exportFail: 'Export failed: {msg}',
    importInvalidJson: 'The file is not a valid DevFlow settings backup (wrong format)',
    importScopeNote: 'Scope: appSettings + knowledge config (no provider keys)',

    // ===== Confirm dialogs =====
    confirmDeleteProvider: 'Delete provider "{name}"? This cannot be undone.',
    confirmDeleteConn: 'Delete connection "{name}"?',
  },
}
