import type { Translations } from '../types';

export const en: Translations = {
    // =========================================================================
    // Settings — Tab Groups
    // =========================================================================
    'settings.group.providers': 'Providers',
    'settings.group.agentBehaviour': 'Agents',
    'settings.group.customize': 'Customize',
    'settings.group.vault': 'Vault',
    'settings.group.advanced': 'Advanced',
    'settings.group.help': 'Help',

    // =========================================================================
    // Settings — Sub-Tab Labels
    // =========================================================================
    'settings.tab.providers': 'Providers',
    'settings.tab.models': 'Models (legacy)',
    'settings.tab.embeddings': 'Embeddings',
    'settings.tab.webSearch': 'Web search',
    'settings.tab.mcp': 'MCP',
    'settings.tab.connectors': 'Connectors',
    'settings.tab.vault': 'Vault',
    'settings.tab.modes': 'Agents',
    'settings.tab.autoApprove': 'Auto-approve',
    'settings.tab.loop': 'Loop',
    'settings.tab.memory': 'Memory',
    'settings.tab.rules': 'Rules',
    'settings.tab.workflows': 'Workflows',
    'settings.tab.skills': 'Skills',
    'settings.tab.prompts': 'Prompts',
    'settings.tab.interface': 'Interface',
    'settings.tab.shell': 'Shell',
    'settings.tab.log': 'Log',
    'settings.tab.debug': 'Debug',
    'settings.tab.backup': 'Backup',
    'settings.tab.language': 'Language',

    // =========================================================================
    // Settings — Models Tab
    // =========================================================================
    'settings.models.introTitle': 'AI models',
    'settings.models.introDesc': 'Configure the AI models the agent uses. You can add multiple models and switch between them.',
    'settings.models.performanceNote': 'Note:',
    'settings.models.performanceNoteDesc': 'The agent works with any model (local ones included). Expect the best results from large frontier models.',
    'settings.models.headerModel': 'Model',
    'settings.models.headerProvider': 'Provider',
    'settings.models.headerKey': 'Key',
    'settings.models.headerEnable': 'Enable',
    'settings.models.headerDefault': 'Default',
    'settings.models.empty': 'No models added yet. Click "+ add model" to get started.',
    'settings.models.addModel': '+ add model',
    'settings.models.importFromCode': 'Import from code',
    'settings.models.alreadyExists': '"{{name}}" already exists',
    'settings.models.imported': 'Imported {{count}} model(s)',
    'settings.models.skipped': '{{count}} skipped (duplicate)',
    'settings.models.configure': 'Configure',
    'settings.models.remove': 'Remove model',

    // =========================================================================
    // Settings — Embeddings Tab
    // =========================================================================
    'settings.embeddings.introTitle': 'Search by meaning',
    'settings.embeddings.introDesc': 'Lets the agent find notes by meaning, not just exact words. Needed if you want it to surface relevant notes from your vault by topic.',
    'settings.embeddings.headingModels': 'Embedding models',
    'settings.embeddings.sectionModelsInfo': 'An embedding model turns text into numbers (vectors). Notes with similar meaning end up with similar vectors, which is how "find by meaning" works. Add one model here, the same vectors are reused for the semantic index, memory recall, and the implicit-connections suggestion.',
    'settings.embeddings.headingIndex': 'Semantic index',
    'settings.embeddings.sectionIndexInfo': 'A local database that stores one vector per note (or per chunk of a long note). Built once from your vault and updated as you edit. Without it, search-by-meaning has nothing to match against.',
    'settings.embeddings.headingConfig': 'Index configuration',
    'settings.embeddings.sectionConfigInfo': 'How the vault is sliced into pieces before indexing, how often it is rebuilt, and which folders are skipped. Defaults are sane; touch only if search results are systematically too coarse (chunk too big) or too noisy (chunk too small).',
    'settings.embeddings.modelsDesc': 'Embedding models power semantic search across your vault. Select exactly one model as the active index.',
    'settings.embeddings.headerModel': 'Model',
    'settings.embeddings.headerProvider': 'Provider',
    'settings.embeddings.headerKey': 'Key',
    'settings.embeddings.headerActive': 'Active',
    'settings.embeddings.empty': 'No embedding models configured',
    'settings.embeddings.addModel': '+ add embedding model',
    'settings.embeddings.buildIndex': 'Build index',
    'settings.embeddings.forceRebuild': 'Force rebuild',
    'settings.embeddings.cancel': 'Cancel',
    'settings.embeddings.deleteIndex': 'Delete index',
    'settings.embeddings.building': 'Building\u2026',
    'settings.embeddings.rebuilding': 'Rebuilding\u2026',
    'settings.embeddings.alreadyExists': '"{{name}}" already exists',
    'settings.embeddings.enableFirst': 'Enable semantic index first.',
    'settings.embeddings.alreadyBuilding': 'Already building\u2026',
    'settings.embeddings.indexBuilt': 'Index built: {{indexed}}/{{total}} files, {{errors}} skipped.',
    'settings.embeddings.indexRebuilt': 'Rebuild: {{indexed}}/{{total}} files, {{errors}} skipped.',
    'settings.embeddings.chunkSizeUpdated': 'Chunk size updated. Rebuild the index to apply the new setting.',
    'settings.embeddings.autoIndexEnabled': 'Auto-index on change enabled. Reload Obsidian to activate.',
    'settings.embeddings.autoIndexDisabled': 'Auto-index on change disabled. Reload Obsidian to deactivate.',
    'settings.embeddings.enableIndex': 'Enable semantic index',
    'settings.embeddings.enableIndexDesc': 'Lets the agent find relevant notes by meaning, not just exact keywords. Requires an embedding model. First build may take a few minutes for large vaults.',
    'settings.embeddings.indexPdfs': 'Index documents (PDF, office)',
    'settings.embeddings.indexPdfsDesc': 'Also index document files in your vault. Text is extracted and indexed alongside your notes. Only image-only (scanned) documents without extractable text are skipped.',
    'settings.embeddings.buildIndexName': 'Build index',
    'settings.embeddings.buildIndexDesc': 'Index new and modified notes. Already-indexed notes are skipped. Use "force rebuild" to reindex everything from scratch.',
    'settings.embeddings.cancelIndexing': 'Cancel indexing',
    'settings.embeddings.cancelIndexingDesc': 'Stop the current indexing run. Progress is saved to disk, the next build will resume from where it left off.',
    'settings.embeddings.deleteIndexName': 'Delete index',
    'settings.embeddings.deleteIndexDesc': 'Remove the on-disk index. Notes are not affected.',
    'settings.embeddings.deleteConfirmTitle': 'Delete semantic index?',
    'settings.embeddings.deleteConfirmMessage': 'This will permanently delete the index including all enrichment data. You will need to rebuild it from scratch. Notes are not affected.',
    'settings.embeddings.deleteConfirmAccept': 'Delete index',
    'settings.embeddings.checkpointInterval': 'Checkpoint interval',
    'settings.embeddings.checkpointIntervalDesc': 'How many files to index before saving progress to disk. Smaller = more frequent checkpoints, safer on slow disks. Larger = fewer writes, slightly faster. Default: 50.',
    'settings.embeddings.chunkSize': 'Chunk size',
    'settings.embeddings.chunkSizeDesc': 'Characters per chunk when indexing notes. Smaller = more precise results, more chunks. Larger = more context per chunk, fewer API calls. Changing this will trigger a full index rebuild.',
    'settings.embeddings.hyde': '`HyDE` (hypothetical document embeddings)',
    'settings.embeddings.hydeDesc': 'Before searching, ask the model to write a short hypothetical note that would answer the query, then embed that instead of the raw query. Improves recall for vague or abstract questions. Costs one extra model call per semantic_search.',
    'settings.embeddings.autoIndexOnChange': 'Auto-index on file changes (beta)',
    'settings.embeddings.autoIndexOnChangeDesc': 'Re-index a note automatically when saved, created, renamed, or deleted. Safe with API embedding models such as text-embedding-3-small.',
    'settings.embeddings.autoIndexStrategy': 'Auto-index strategy',
    'settings.embeddings.autoIndexStrategyDesc': 'When to automatically rebuild the index. "on startup" is best for active vaults. "never" lets you trigger it manually from the ellipsis menu in the chat.',
    'settings.embeddings.excludedFolders': 'Excluded folders',
    'settings.embeddings.excludedFoldersDesc': 'Folders to skip when indexing.',
    'settings.embeddings.chunkSmall': 'Small (800 chars), best for short atomic notes',
    'settings.embeddings.chunkMedium': 'Medium (1200 chars)',
    'settings.embeddings.chunkStandard': 'Standard (2000 chars), default',
    'settings.embeddings.chunkLarge': 'Large (3000 chars), best for long journals',
    'settings.embeddings.autoIndexNever': 'Never (manual only)',
    'settings.embeddings.autoIndexStartup': 'On startup',
    'settings.embeddings.autoIndexModeSwitch': 'On mode switch',
    'settings.embeddings.statusDisabled': 'Semantic index is disabled.',
    'settings.embeddings.statusNotInit': 'Not initialized. Toggle off/on to reload.',
    'settings.embeddings.statusNotBuilt': 'Not built yet. Click "build index" to start.',
    'settings.embeddings.statusBuilding': 'Building index\u2026',
    'settings.embeddings.statusCancelling': 'Cancelling\u2026',
    'settings.embeddings.statusForceRebuild': 'Force rebuild\u2026',
    'settings.embeddings.statusReady': 'Ready: {{docCount}} notes \u00B7 built: {{builtAt}}',
    'settings.embeddings.statusBuildFailed': 'Build failed: {{error}}',
    'settings.embeddings.statusRebuildFailed': 'Rebuild failed: {{error}}',
    'settings.embeddings.statusSkipped': '{{count}} file(s) skipped',
    'settings.embeddings.noEmbeddingModel': 'No embedding model configured. Add one above to enable semantic search.',
    'settings.embeddings.usingModel': 'Using {{name}} ({{provider}}) for embeddings.',
    'settings.embeddings.indexDesc': 'Builds a local vector index of all notes for semantic_search. {{embModelDesc}}',
    'settings.embeddings.quickSetupTitle': 'Quick setup:',
    'settings.embeddings.quickSetupStep1': '1. Click "+ add embedding model" above and choose a provider.',
    'settings.embeddings.quickSetupStep2': '2. Select a model like text-embedding-3-small (fast, cheap, excellent quality).',
    'settings.embeddings.quickSetupStep3': '3. Enter your API key, then enable the semantic index below.',
    'settings.embeddings.quickSetupFreeTitle': 'Free alternatives:',
    'settings.embeddings.quickSetupFreeDesc': 'Local providers run embedding models at no cost. Install a local inference server, pull nomic-embed-text, and add it as a local embedding model above.',
    'settings.embeddings.infoIndexTitle': 'Semantic index',
    'settings.embeddings.infoIndexBody': 'The semantic index reads all your notes, breaks them into small sections, and converts each section into a mathematical representation of its meaning (called an "embedding"). When you ask the agent a question, it searches for notes with similar meaning rather than just matching words. This makes the agent much better at finding relevant context in your vault.',
    'settings.embeddings.infoCheckpointTitle': 'Checkpoint interval',
    'settings.embeddings.infoCheckpointBody': 'The indexer saves a checkpoint to disk every n files. If indexing is interrupted (app closed, error), the next run resumes from the last checkpoint, so only unindexed or modified files are processed. A smaller interval loses less progress on interruption but writes to disk more often. 10 to 30 is recommended for most vaults.',
    'settings.embeddings.infoHydeTitle': '`HyDE`',
    'settings.embeddings.infoHydeBody': 'Hypothetical document embeddings is a technique that improves semantic search recall. Instead of embedding your query directly, the agent first asks the model to write a short note that would answer your question. That hypothetical text is then embedded and used for the search. This is especially helpful for vague queries like "what are my goals?" where a direct embedding might not match well. The downside is one extra model call per search.',
    'settings.embeddings.infoAutoChangeTitle': 'Auto-index on change',
    'settings.embeddings.infoAutoChangeBody': 'When enabled, every file you edit is re-embedded 2 seconds after you stop typing. This works well with API-based embedding models.',
    'settings.embeddings.infoAutoStrategyTitle': 'Auto-index strategy',
    'settings.embeddings.infoAutoStrategyBody': '"on startup" rebuilds the index every time Obsidian opens. Keeps the index fresh but adds a few seconds to startup time for large vaults. "on mode switch" rebuilds whenever you switch agents, useful if each agent works with different parts of your vault. "never" means you control when to rebuild using the "force reindex vault" option in the chat\'s ellipsis menu.',
    'settings.embeddings.infoExcludedTitle': 'Excluded folders',
    'settings.embeddings.infoExcludedBody': 'Use this to skip folders that contain files you do not want the agent to search through (attachment folders full of images or `PDFs`, template folders, or private journals). Enter the folder path relative to your vault root, one per line.',
    'settings.embeddings.riskNote': 'Risk: this setting may slow down your vault performance or freeze Obsidian.',
    'settings.embeddings.folderPlaceholder': 'Type / to browse folders',
    'settings.embeddings.configureModel': 'Configure',
    'settings.embeddings.removeModel': 'Remove',
    // Contextual retrieval (FEATURE-1501)
    'settings.embeddings.contextualRetrieval': 'Contextual retrieval',
    'settings.embeddings.contextualRetrievalDesc': 'Enrich chunks with AI-generated context in the background. Improves search quality by 49-67%. Requires a contextual model below.',
    'settings.embeddings.contextualModel': 'Contextual retrieval model',
    'settings.embeddings.contextualModelDesc': 'Chat model for context prefix generation. Use a cheap/fast model (e.g. Haiku, gpt-4o-mini).',
    'settings.embeddings.contextualModelPlaceholder': 'Select model',
    'settings.embeddings.statusEnriching': 'Enriching: {{processed}}/{{total}} chunks (search works, quality improving)',
    'settings.embeddings.statusPendingEnrichment': '{{count}} chunks pending enrichment',
    // Graph expansion (FEATURE-1502)
    'settings.embeddings.headingGraph': 'Graph expansion',
    'settings.embeddings.sectionGraphInfo': 'After semantic search finds the most relevant notes, graph expansion follows wikilinks and tags one step further to pull in related context. Helpful when the most relevant note is a stub that points at the real content elsewhere. Costs a few extra reads per search.',
    'settings.embeddings.graphExpansion': 'Graph expansion',
    'settings.embeddings.graphExpansionDesc': 'Expand search results via wikilinks and map-of-content properties. Extracts your vault graph into the knowledge database.',
    'settings.embeddings.expansionHops': 'Expansion hops',
    'settings.embeddings.expansionHopsDesc': 'How many link-hops to follow (1 = direct links, 2 = links of links, 3 = broad). Higher values include more context.',
    'settings.embeddings.hops1': '1 hop (direct links)',
    'settings.embeddings.hops2': '2 hops',
    'settings.embeddings.hops3': '3 hops (broad)',
    'settings.embeddings.mocProperties': 'Map-of-content property names',
    'settings.embeddings.mocPropertiesDesc': 'Properties to extract as graph edges (comma-separated). Example: topics, concepts, people.',
    'settings.embeddings.mocPropertiesPlaceholder': 'Topics, concepts, people',
    'settings.embeddings.categoryProperty': 'Category property name',
    'settings.embeddings.categoryPropertyDesc': 'Frontmatter property that defines the note type (such as kategorie, category).',
    'settings.embeddings.summaryProperty': 'Summary property name',
    'settings.embeddings.summaryPropertyDesc': 'Frontmatter property for the short summary (such as zusammenfassung, summary).',
    'settings.embeddings.sourceNaming': 'Source naming convention',
    'settings.embeddings.sourceNamingDesc': 'Naming convention for source files (such as author-year_title).',
    'settings.embeddings.graphStats': 'Graph: {{edges}} edges, {{tags}} unique tags extracted',
    'settings.embeddings.graphNotInit': 'Graph: not initialized (enable semantic index first)',
    // Implicit connections (FEATURE-1503)
    'settings.embeddings.headingImplicit': 'Implicit connections',
    'settings.embeddings.sectionImplicitInfo': 'Suggests wikilinks to related notes that you have not yet linked manually. Runs on the embedding vectors, so it picks up topical similarity, not just title matches. Surfaces as inline hints; nothing is changed in your notes automatically.',
    'settings.embeddings.implicitConnections': 'Implicit connections',
    'settings.embeddings.implicitConnectionsDesc': 'Discover semantically similar notes that have no direct link. Computed in the background after indexing.',
    'settings.embeddings.similarityThreshold': 'Similarity threshold',
    'settings.embeddings.similarityThresholdDesc': 'Minimum cosine similarity to count as an implicit connection (0.5 = loose, 0.9 = strict).',
    'settings.embeddings.suggestionBanner': 'Suggestion banner',
    'settings.embeddings.suggestionBannerDesc': 'Show implicit connection suggestions in the sidebar. Disable if the suggestions are distracting.',
    'settings.embeddings.implicitStats': '{{count}} implicit connections discovered',
    'settings.embeddings.implicitComputing': 'Computing implicit connections...',
    'settings.embeddings.implicitNone': 'No implicit connections computed yet (build index first)',
    // Local reranking (FEATURE-1504)
    'settings.embeddings.headingReranking': 'Local reranking',
    'settings.embeddings.sectionRerankingInfo': 'A second pass that re-orders the top search results using a small local model. Embeddings are fast but coarse; the reranker fixes obvious ranking errors when the first hit "looks similar" but is not actually what you asked for. Runs entirely offline.',
    'settings.embeddings.localReranking': 'Local reranking',
    'settings.embeddings.localRerankingDesc': 'Re-score search results with a local cross-encoder model. Runs entirely on-device, desktop only.',
    'settings.embeddings.rerankCandidates': 'Rerank candidates',
    'settings.embeddings.rerankCandidatesDesc': 'How many candidates to rerank (more = better quality but slower).',

    // =========================================================================
    // Settings — Web Search Tab
    // =========================================================================
    'settings.webSearch.introTitle': 'Web access',
    'settings.webSearch.introDesc': 'When the agent needs information that is not in your vault. Add a search provider (Tavily, Brave) for keyword searches, web fetch works without.',
    'settings.webSearch.desc': 'Configure web_fetch (read any URL) and web_search (keyword search); web_fetch works without an API key, web_search requires one.',
    'settings.webSearch.headingGeneral': 'General',
    'settings.webSearch.sectionGeneralInfo': 'The master switch for everything the agent does outside Obsidian. With this off, the agent has no way to fetch a URL or run a search regardless of everything else. With it on, it still respects the auto-approval rules under Permissions.',
    'settings.webSearch.headingProvider': 'Search provider',
    'settings.webSearch.sectionProviderInfo': 'Picks who answers keyword searches. Tavily and Brave each need their own API key. Without a provider configured, the agent can still fetch a specific URL it is told about; it just cannot discover new pages by topic.',
    'settings.webSearch.enableWebTools': 'Enable web tools',
    'settings.webSearch.enableWebToolsDesc': 'Allow the agent to fetch web pages and run internet searches. Turn off to keep the agent working entirely within your vault.',
    'settings.webSearch.provider': 'Provider',
    'settings.webSearch.providerDesc': 'Which service the agent uses for keyword searches. Choose "none" if you only need to fetch specific `URLs`, not run search queries.',
    'settings.webSearch.braveKey': 'Brave search API key',
    'settings.webSearch.braveKeyDesc': 'Required for Brave search. Get a free API key at brave.com/search/api (2,000 searches/month on the free plan).',
    'settings.webSearch.tavilyKey': 'Tavily API key',
    'settings.webSearch.tavilyKeyDesc': 'Required for Tavily search. Get a free API key at tavily.com (1,000 searches/month on the free plan).',
    'settings.webSearch.providerNone': 'None (web_fetch only)',
    'settings.webSearch.providerBrave': 'Brave search',
    'settings.webSearch.providerTavily': 'Tavily',
    'settings.webSearch.bravePlaceholder': '`BSA`...',
    'settings.webSearch.tavilyPlaceholder': 'Tvly-...',

    // =========================================================================
    // Settings — MCP Tab
    // =========================================================================
    'settings.mcp.introTitle': 'External tools',
    'settings.mcp.introDesc': 'Connect tools and data sources outside Obsidian (calendar, Slack, GitHub, your own scripts). Each server adds new tools the agent can call. Uses the MCP standard.',
    'settings.mcp.desc': 'Connect external tools and data sources via the model context protocol. Each server exposes tools the agent can call using `use_mcp_tool`.',
    'settings.mcp.addServer': 'Add server',
    'settings.mcp.disconnect': 'Disconnect',
    'settings.mcp.retry': 'Retry',
    'settings.mcp.connect': 'Connect',
    'settings.mcp.saveConnect': 'Save & connect',
    'settings.mcp.empty': 'No servers configured. Click "add server" to get started.',
    'settings.mcp.editServer': 'Edit server: {{name}}',
    'settings.mcp.addServerTitle': 'Add server',
    'settings.mcp.namePlaceholder': 'Server name (e.g. "filesystem")',
    'settings.mcp.commandPlaceholder': 'Example: npx',
    'settings.mcp.argsPlaceholder': 'e.g. -y @modelcontextprotocol/server-filesystem /path',
    'settings.mcp.urlPlaceholder': 'e.g. http://localhost:3000/sse',
    'settings.mcp.timeoutPlaceholder': '60',
    'settings.mcp.labelCommand': 'Command',
    'settings.mcp.labelArgs': 'Args (space-separated)',
    'settings.mcp.labelEnv': 'Env (key=value, one per line)',
    'settings.mcp.labelUrl': 'URL',
    'settings.mcp.labelHeaders': 'Headers (key=value, one per line)',
    'settings.mcp.labelTimeout': 'Timeout (seconds)',
    'settings.mcp.toolCount': '{{count}} tool(s)',
    'settings.mcp.edit': 'Edit',
    'settings.mcp.delete': 'Delete',
    'settings.mcp.builtInDisabledHint': 'Requires an API key. Click edit to configure, then connect.',

    // =========================================================================
    // Settings — Modes Tab
    // =========================================================================
    'settings.modes.introTitle': 'What is an agent?',
    'settings.modes.introDesc': 'An agent is the personality your assistant adopts: its system prompt (rules of the game), the set of tools it may use, and any extra instructions you give it. Picking another agent here changes how the assistant thinks and what it can do, immediately. The Default agent is read/write, full toolset. Make your own to specialise (e.g. read-only research, focused writing, code review).',
    'settings.modes.groupBuiltIn': 'Default',
    'settings.modes.groupGlobal': 'Shared across vaults',
    'settings.modes.groupVault': 'Your agents in this vault',
    'settings.modes.newMode': '+ New agent',
    'settings.modes.duplicate': '+ Duplicate',
    'settings.modes.duplicated': 'Created "{{name}}" and switched to it.',
    'settings.modes.duplicateFailed': 'Cannot duplicate: agent not found.',
    'settings.modes.import': 'Import',
    'settings.modes.done': 'Done',
    'settings.modes.previewPrompt': 'Show full system prompt',
    'settings.modes.export': 'Export',
    'settings.modes.restoreDefaults': 'Restore defaults',
    'settings.modes.delete': 'Delete',
    'settings.modes.deleteBuiltInTooltip': 'The default agent cannot be deleted. Duplicate it and edit the copy instead.',
    'settings.modes.deleted': 'Deleted "{{name}}".',
    'settings.modes.name': 'Name',
    'settings.modes.shortDesc': 'Description',
    'settings.modes.shortDescHint': 'Visible to the LLM via the switch_agent tool when it decides whether to switch. Not shown to you in the chat.',
    'settings.modes.shortDescPlaceholder': 'Brief description...',
    'settings.modes.roleDefinition': 'System prompt (role)',
    'settings.modes.roleDefinitionHint': 'The agent reads this as the FIRST section of its system prompt. It defines who the agent is, what it does, and how it works. Use "Show full system prompt" below to see the assembled result.',
    'settings.modes.customInstructions': 'Additional instructions (optional)',
    'settings.modes.customInstructionsHint': 'Appended after the role. Use for fine-tuning (specific tone, output format, things to avoid) without rewriting the whole role.',
    'settings.modes.customInstructionsPlaceholder': 'Add behavioral guidelines for {{mode}}...',
    'settings.modes.globalInstructionsPlaceholder': 'Example: always respond in German. Never use bullet points with more than 5 items.',
    'settings.modes.customized': 'You have customised this agent',
    'settings.modes.loading': 'Loading...',
    'settings.modes.activeMode': 'Active agent',
    'settings.modes.globalCustomInstructions': 'Instructions for every agent',
    'settings.modes.globalCustomInstructionsDesc': 'Applied on top of every agent\'s system prompt. Use this for vault-wide preferences (your language, formatting rules, things you never want).',
    'settings.modes.fileTooLarge': 'Agent file too large (max 500 KB)',
    'settings.modes.invalidJson': 'Invalid agent file: not valid JSON',
    'settings.modes.invalidMode': 'Invalid agent file: missing slug, name, or system prompt',
    'settings.modes.parseFailed': 'Failed to parse agent file',
    'settings.modes.importSuccess': 'Agent "{{name}}" imported',
    'settings.modes.restored': '{{name}} restored to defaults',

    // =========================================================================
    // Settings — Permissions Tab
    // =========================================================================
    'settings.permissions.introTitle': 'Approve actions (review carefully)',
    'settings.permissions.introDesc': 'Every category you auto-approve below lets the agent act on your vault, your data, or the outside world without asking again. Set each toggle deliberately and review them whenever you change models, install a new MCP server, or grant the agent broader skills. The highest-risk combinations are web access plus write access (the agent can fetch and act on anything from the internet) and sandbox code execution (the LLM authors code that runs in your browser). Auto-approve those only if you trust your active model and your prompts.',
    'settings.permissions.desc': 'Auto-approve controls whether the agent can perform actions immediately or must ask for your confirmation first. When a category is off, the agent pauses and shows an approval dialog before each action in that category.',
    'settings.permissions.headingBehavior': 'Agent behavior',
    'settings.permissions.headingAutoApprove': 'Auto-approve',
    'settings.permissions.sectionAutoApproveInfo': 'Master switch for everything below. When this is on, the agent runs the categories you have permitted without asking. When off, every tool call shows a confirmation in the chat. The Permissive warning lights up if you allow web + write together, which is the highest-risk combination (the agent can fetch content from anywhere and act on it without your review).',
    'settings.permissions.headingPerCategory': 'Per category',
    'settings.permissions.sectionPerCategoryInfo': 'Which categories of tool calls auto-approve. Read is the safest (file reads, searches), Note edits and Vault changes touch your files, Web fetches content from outside, Sub-agents spawn other agents that inherit these same rules. Anything you leave off here shows a confirmation in the chat before the agent runs it.',
    'settings.permissions.headingPluginApi': 'Plugin API & recipes',
    'settings.permissions.sectionPluginApiInfo': 'Approval rules specifically for the External-commands surface (other Obsidian plugins and the recipe runner). Plugin read calls are safe; plugin write calls and recipes touch your data or run external programs, so they are off by default.',
    'settings.permissions.enableAutoApprove': 'Enable auto-approve',
    'settings.permissions.enableAutoApproveDesc': 'Main switch. When off, you must manually confirm every action, no matter what the individual settings below say.',
    'settings.permissions.showApprovalBar': 'Show approval bar in chat',
    'settings.permissions.showApprovalBarDesc': 'Show a row of quick-toggle buttons above the chat input for easy access.',
    'settings.permissions.readOps': 'Read operations',
    'settings.permissions.readOpsDesc': 'Reading and searching notes. These operations never change your vault.',
    'settings.permissions.noteEdits': 'Note edits',
    'settings.permissions.noteEditsDesc': 'Writing or changing note content. When off, you review and confirm every edit before it is saved.',
    'settings.permissions.vaultChanges': 'Vault structure changes',
    'settings.permissions.vaultChangesDesc': 'Creating folders, moving files, deleting notes, generating canvases, or creating bases. Harder to undo.',
    'settings.permissions.webOps': 'Web operations',
    'settings.permissions.webOpsDesc': 'The agent can open web pages and run web searches on your behalf.',
    'settings.permissions.mcpCalls': 'Protocol tool calls',
    'settings.permissions.mcpCallsDesc': 'The agent can use external tools you have connected through third-party integrations (protocol servers).',
    'settings.permissions.modeSwitching': 'Mode switching',
    'settings.permissions.modeSwitchingDesc': 'Let the agent switch between modes without asking.',
    'settings.permissions.subtasks': 'Subtasks',
    'settings.permissions.subtasksDesc': 'Allow the agent to create helper agents that work on parts of a larger task independently.',
    'settings.permissions.followUp': 'Follow-up questions',
    'settings.permissions.followUpDesc': 'Let the agent ask you clarifying questions during a task without needing separate approval.',
    'settings.permissions.todoUpdates': 'Todo list updates',
    'settings.permissions.todoUpdatesDesc': 'Allow the agent to update its task checklist while working.',
    'settings.permissions.pluginSkills': 'Plugin skills',
    'settings.permissions.pluginSkillsDesc': 'Run Obsidian commands, enable or disable plugins, and use built-in features like PDF export.',
    'settings.permissions.pluginApiReads': 'Plugin API reads',
    'settings.permissions.pluginApiReadsDesc': 'Let the agent read data from other plugins (e.g. Dataview, omnisearch). This never changes your vault.',
    'settings.permissions.pluginApiWrites': 'Plugin API writes',
    'settings.permissions.pluginApiWritesDesc': 'Let the agent change data through other plugins (e.g. `MetaEdit`). Off by default for safety.',
    'settings.permissions.recipes': 'Recipe execution',
    'settings.permissions.recipesDesc': 'Let the agent run export recipes (e.g. Pandoc) without asking. Off by default.',

    // Security warnings for high-risk auto-approval toggles
    'settings.permissions.enableAutoApproveWarning': 'When enabled, the agent acts without asking you first. You lose the chance to review actions before they happen. Only enable categories you fully trust.',
    'settings.permissions.noteEditsWarning': 'The agent can change your notes without asking. You will not be able to tell whether a change was made intentionally or caused by misleading input.',
    'settings.permissions.vaultChangesWarning': 'Deleting or moving files is hard to undo. The checkpoint system can help restore changes, but manual review is recommended.',
    'settings.permissions.webOpsWarning': 'The agent opens web pages and runs searches on external servers. Content from untrusted sites could influence the agent\'s behavior.',
    'settings.permissions.mcpCallsWarning': 'External tools can perform any action on their connected servers. Only enable this if you trust all your connected integrations.',
    'settings.permissions.pluginApiWritesWarning': 'The agent changes data through other plugins with the same access those plugins have.',
    'settings.permissions.recipesWarning': 'Recipes run programs on your computer. Enabling this removes the final manual check before they execute.',
    'settings.permissions.subtasksWarning': 'Helper agents use the same auto-approval settings and can act without separate confirmation.',

    // Sandbox execution
    'settings.permissions.headingSandbox': 'Sandbox code execution',
    'settings.permissions.sectionSandboxInfo': 'The agent can occasionally run small bits of TypeScript inside an isolated sandbox (no Node.js APIs, no file-system access, only what Vault Operator exposes). Auto-approving this skips the confirmation step. High-risk because the LLM authors the code; only enable if you trust your active model and your prompts.',
    'settings.permissions.sandbox': 'Auto-approve sandbox execution',
    'settings.permissions.sandboxDesc': 'Let the agent run code in a protected sandbox without asking. Off by default. Your confirmation is the main safeguard against harmful code.',
    'settings.permissions.sandboxWarning': 'The agent can run any code in the `sandbox`, which provides basic protection but is not fully isolated from the rest of the app. Misleading input could cause harmful code to run without your review; keep this off unless you fully understand the risk.',
    'settings.permissions.sandboxConfirmTitle': 'Enable sandbox auto-approval?',
    'settings.permissions.sandboxConfirmMessage': 'This allows the agent to run code without your review. The sandbox provides basic protection but is not fully isolated. Content from web pages or vault notes could cause unreviewed code to run. Are you sure?',
    'settings.permissions.sandboxConfirmCancel': 'Cancel',
    'settings.permissions.sandboxConfirmAccept': 'I understand the risk, enable',

    // H-1: Permissive mode warning (web + writes both auto-approved)
    'settings.permissions.permissiveWarning': 'Permissive mode: web access and write operations are both auto-approved. Content from untrusted web pages or vault notes could trick the agent into modifying your vault without review. This is the highest-risk configuration. Consider disabling auto-approval for either web access or write operations.',

    // =========================================================================
    // Settings — Loop Tab
    // =========================================================================
    'settings.loop.introTitle': 'Run behaviour',
    'settings.loop.introDesc': 'How long the agent keeps working, how many errors it tolerates, when it summarises the conversation to stay focused. Defaults are sane; edit only if you have a specific reason.',

    // Limits & retries
    'settings.loop.headingLoop': 'Limits & retries',
    'settings.loop.sectionLoopDesc': 'Safety nets that stop the agent before it burns through tokens or runs forever. Each one trips independently.',
    'settings.loop.errorLimit': 'Error limit',
    'settings.loop.errorLimitDesc': 'Stop after this many tool errors in a row. Default: 3. Set to 0 to never stop automatically.',
    'settings.loop.rateLimit': 'Pause between requests',
    'settings.loop.rateLimitDesc': 'Milliseconds to wait between API calls. Default: 0. Raise to 500-1500 ms only if your provider returns repeated rate-limit errors.',
    'settings.loop.maxIterations': 'Steps per message',
    'settings.loop.maxIterationsDesc': 'How many tool-call rounds the agent may take for one message. Default: 25.',
    'settings.loop.maxIterationsInfo': 'One step = the agent generates a response, calls one or more tools, and waits for the results. Multi-step tasks (research, refactors, deep ingests) need many steps. Raise to 50 if you regularly see "max iterations reached" notices on complex tasks.',
    'settings.loop.maxSubtaskDepth': 'Sub-agent depth',
    'settings.loop.maxSubtaskDepthDesc': 'How deeply sub-agents may nest. Default: 2.',
    'settings.loop.maxSubtaskDepthInfo': 'A sub-agent is a second agent that the main agent can spawn for a specific subtask (e.g. "research this in parallel"). Depth 1 means sub-agents cannot spawn further sub-agents; 2 allows one extra level. Each level adds a fresh system prompt, multiplying token cost; deeper trees rarely improve results.',

    // Auto-summarise
    'settings.loop.headingCondensing': 'Auto-summarise',
    'settings.loop.sectionCondensingDesc': 'AI models can hold only a limited amount of text in memory at once. When your chat grows close to that limit, the agent automatically condenses older messages into a recap so you can keep going on a single long task. The summary replaces the original messages, so anything earlier than the most recent few turns is paraphrased, not verbatim.',
    'settings.loop.enableCondensing': 'Auto-summarise long chats',
    'settings.loop.enableCondensingDesc': 'Replaces older messages with a recap once the chat fills up. Default: on.',
    'settings.loop.condensingThreshold': 'Trigger threshold',
    'settings.loop.condensingThresholdDesc': "Summarise when the chat reaches this share of the memory limit. Default: 80 %.",

    // Power steering
    'settings.loop.headingPowerSteering': 'Power steering',
    'settings.loop.sectionPowerSteeringDesc': 'On long tasks the agent can drift away from its instructions because its role definition (the system prompt) sits far back in the conversation. Power steering periodically re-sends that role so the agent stays in character.',
    'settings.loop.powerSteeringFreq': 'Refresh frequency',
    'settings.loop.powerSteeringFreqDesc': 'Re-send the role every N turns. Default: 4. Set to 0 to disable.',

    // Task routing
    'settings.loop.headingHelperModel': 'Task routing',
    'settings.loop.sectionRoutingDesc': "Some prompts (create one XLSX, summarise a single note, rename a folder) do not need a flagship model. Vault Operator can detect those and route them to your cheaper budget-tier model automatically, falling back to the main model if the budget model struggles.",
    'settings.loop.autoTaskRouterName': 'Route simple tasks to the cheap tier',
    'settings.loop.autoTaskRouterDesc': 'Single-step prompts use the budget-tier model. Multi-step prompts stay on the main model. Default: on.',

    // =========================================================================
    // Settings — Memory Tab
    // =========================================================================
    'settings.memory.introTitle': 'Long-term memory',
    'settings.memory.introDesc': 'The agent remembers facts about you and your projects across sessions. Edit what it has stored or turn extraction off.',
    'settings.memory.desc': 'Configure how the agent remembers conversations and learns from past interactions. Memory is extracted in the background using a dedicated model.',
    'settings.memory.headingHistory': 'Chat history',
    'settings.memory.sectionHistoryInfo': 'Whether each conversation is kept and shown in the History sidebar. Off = chats disappear when you close them; on = they are searchable and can feed into memory extraction.',
    'settings.memory.headingMemory': 'Memory',
    'settings.memory.sectionMemoryInfo': 'When auto-extract is on, finished conversations are summarised into discrete facts the agent stores about you and your projects. Those facts are pulled in to the next chat\'s context as soon as they are relevant. Turn off to keep memory entirely manual: nothing is stored unless you say so in chat ("remember that ...").',
    'settings.memory.headingModel': 'Memory model',
    'settings.memory.headingThreshold': 'Extraction threshold',
    'settings.memory.headingFiles': 'Memory files',
    'settings.memory.headingOnboarding': 'Onboarding',
    'settings.memory.sectionOnboardingInfo': 'A short guided dialog that asks for the basics (who you are, what you work on, your preferences) so the agent has something to work with on day one. You can rerun it any time to refresh the profile from scratch.',
    'settings.memory.headingCrossSurface': 'Cross-surface sync',
    'settings.memory.sectionCrossSurfaceInfo': 'External chat tools (ChatGPT, Claude.ai, Claude Code, Perplexity) push conversations into Vault Operator via the Remote MCP. You trigger each push from those tools (for example, a "save to memory" call inside ChatGPT); Vault Operator only decides what happens after the data arrives. The settings here control that handling: extract memory immediately, or park the conversation as pending until you review it in the History sidebar. ChatGPT and Perplexity default to pending to keep family-shared accounts out of personal memory.',
    'settings.memory.crossSurfaceInlineHint': 'External tools (ChatGPT, Claude.ai, Claude Code, Perplexity) push conversations into Vault Operator themselves via MCP. You trigger each push inside those tools, never from here. The settings below only decide what Vault Operator does once a push arrives: extract memory right away, or park the conversation as pending for you to review in the History sidebar.',
    'settings.memory.crossSurfaceInactiveTitle': 'Cross-surface sync is inactive.',
    'settings.memory.crossSurfaceInactiveBody': 'No Remote MCP server is enabled, so external tools cannot push conversations into Vault Operator yet. Enable a connector under Customize -> Connectors and point your external tool at its endpoint to start receiving pushes. The handling rules will appear here once that is set up.',
    'settings.memory.headingContents': 'Memory contents',
    'settings.memory.sectionContentsInfo': 'See what the agent remembers about you and how it knows itself. To add an entry, just say it in the chat (e.g. "remember that emojis are unwanted"). Use this view to inspect what is stored and remove entries you do not want kept.',
    'settings.memory.viewMemory': 'View memory',
    'settings.memory.viewMemoryDesc': 'Browse user facts, agent soul, and capability snapshot. Soft-delete from here.',
    'settings.memory.viewMemoryButton': 'Open',
    'settings.memory.deleteAll': 'Delete all memory',
    'settings.memory.deleteAllDesc': 'Permanently removes every entry across user memory, agent soul, sessions, and the audit log. Requires a typed confirmation word.',
    'settings.memory.deleteAllButton': 'Delete all',
    'settings.memory.enableHistory': 'Enable chat history',
    'settings.memory.enableHistoryDesc': 'Save conversations to the plugin directory for later browsing and restoration.',
    'settings.memory.storedConversations': 'Stored conversations',
    'settings.memory.storedConversationsDesc': '{{count}} conversation(s) saved',
    'settings.memory.enableMemory': 'Enable memory',
    'settings.memory.enableMemoryDesc': 'Allow the agent to build long-term memory from conversations. Disable to stop all extraction.',
    'settings.memory.autoExtract': 'Auto-extract session summaries',
    'settings.memory.autoExtractDesc': 'Automatically extract memory when a conversation ends. The star button and the "remember this" agent prompt always work, regardless of this setting.',
    'settings.memory.manualAlwaysHint': 'You can always save manually: ask the agent ("remember this") or click the star button on a conversation.',
    'settings.memory.modelSelect': 'Model for memory extraction',
    'settings.memory.modelSelectDesc': 'Select a small, fast model (e.g., haiku) for cost-efficient background extraction.',
    'settings.memory.noModels': 'No models configured. Add and enable a model in providers first.',
    'settings.memory.minMessages': 'Minimum messages before extraction',
    'settings.memory.minMessagesDesc': 'Conversations shorter than this are not saved to memory.',
    'settings.memory.memoryStorage': 'Memory storage',
    'settings.memory.memoryStorageLoading': 'Loading...',
    'settings.memory.userProfile': 'User profile',
    'settings.memory.noProfile': 'No profile yet. Start a conversation and the agent will guide you through setup.',
    'settings.memory.profileActive': 'Profile active. The agent uses your preferences to personalize responses.',
    'settings.memory.setupDialog': 'Setup dialog',
    'settings.memory.setupCompleted': 'Setup completed. Restart to re-configure model, permissions, and profile.',
    'settings.memory.setupNotStarted': 'Setup not started yet. Open the chat to begin.',
    'settings.memory.clearAll': 'Clear all',
    'settings.memory.viewFiles': 'View files',
    'settings.memory.resetAll': 'Reset all',
    'settings.memory.restartSetup': 'Restart setup',
    'settings.memory.startSetup': 'Start setup',
    'settings.memory.skipSetup': 'Skip setup',
    'settings.memory.selectModel': 'Select model',
    'settings.memory.allConversationsDeleted': 'All conversations deleted',
    'settings.memory.memoryFilesLocation': 'Memory files: {{dir}}',
    'settings.memory.allMemoryReset': 'All memory files reset',
    'settings.memory.setupSkipped': 'Setup skipped. You can restart it anytime from settings.',
    'settings.memory.statsFiles': '{{count}} memory file(s)',
    'settings.memory.statsSessions': '{{count}} session summary(ies)',
    'settings.memory.statsLastUpdated': 'last updated {{date}}',

    // =========================================================================
    // Settings — Rules Tab
    // =========================================================================
    'settings.rules.heading': 'Rules',
    'settings.rules.desc': 'Rules are injected into the system prompt of every agent session. Store rule files as .md or .txt in your vault at .obsidian-agent/rules/.',
    'settings.rules.introTitle': 'Rules',
    'settings.rules.introDesc': 'House rules every agent follows. Use them for tone, formatting preferences, or "never do X". Applied on top of each agent\'s own instructions.',
    'settings.rules.introDiff': 'Difference: skills are reactive behaviors (only active when relevant). Workflows are concrete sequences with slash commands. Rules are passive principles that always apply.',
    'settings.rules.placeholder': 'Rule name (e.g. "always-use-iso-dates")',
    'settings.rules.create': 'Create rule',
    'settings.rules.import': 'Import',
    'settings.rules.loaderNotAvailable': 'Rules loader not available.',
    'settings.rules.empty': 'No rules yet. Create one above.',
    'settings.rules.editRule': 'Edit rule: {{name}}',
    'settings.rules.edit': 'Edit',
    'settings.rules.export': 'Export',
    'settings.rules.delete': 'Delete',
    'settings.rules.importFailed': 'Could not import rule',

    // =========================================================================
    // Settings — Workflows Tab
    // =========================================================================
    'settings.workflows.heading': 'Workflows',
    'settings.workflows.desc': 'Workflows are triggered by typing /workflow-name in the chat. Store workflow files as .md or .txt in your vault at .obsidian-agent/workflows/.',
    'settings.workflows.introTitle': 'Workflows',
    'settings.workflows.introDesc': 'Reusable multi-step routines. Trigger one with a slash command in the chat (e.g. `/weekly-review`) and the agent runs the whole sequence.',
    'settings.workflows.introDiff': 'Difference: workflows are explicitly user-triggered sequences (via /workflow-name). Skills are automatically activated when relevant. Rules are passive principles. Tools perform individual actions.',
    'settings.workflows.placeholder': 'Workflow name (e.g. "daily-review")',
    'settings.workflows.create': 'Create workflow',
    'settings.workflows.import': 'Import',
    'settings.workflows.loaderNotAvailable': 'Workflow loader not available.',
    'settings.workflows.empty': 'No workflows yet. Create one above.',
    'settings.workflows.editWorkflow': 'Edit workflow: {{name}}',
    'settings.workflows.edit': 'Edit',
    'settings.workflows.export': 'Export',
    'settings.workflows.delete': 'Delete',
    'settings.workflows.importFailed': 'Could not import workflow',

    // =========================================================================
    // Settings — Skills Tab
    // =========================================================================
    'settings.skills.introTitle': 'Skills',
    'settings.skills.introDesc': 'Step-by-step guides the agent loads on demand for specific task types (e.g. "ingest a PDF", "draft a meeting summary"). The agent picks them based on what you ask.',
    'settings.skills.introDiff': 'Key difference: tools execute actions (read files, search, edit). Skills provide instructions (how to approach meeting notes, project planning, etc.). Workflows define fixed step-by-step sequences.',
    'settings.skills.headingManual': 'User skills',
    'settings.skills.headingPlugin': 'Plugin skills',
    'settings.skills.desc': "Skills are automatically injected into the system prompt when relevant to the user's message. Each skill lives in a subfolder at .obsidian-agent/skills/{name}/SKILL.md with frontmatter: name, description.",
    'settings.skills.pluginDisabled': 'Plugin skills are disabled. Enable `VaultDNA` in the advanced settings to auto-discover Obsidian plugins as agent skills.',
    'settings.skills.pluginStats': 'Auto-discovered from installed Obsidian plugins. Active: {{active}} | disabled: {{disabled}} | total: {{total}}',
    'settings.skills.placeholder': 'Skill name (e.g. "daily-template")',
    'settings.skills.create': 'Create skill',
    'settings.skills.import': 'Import',
    'settings.skills.rescan': 'Rescan vault',
    'settings.skills.scanning': 'Scanning...',
    'settings.skills.headerSkill': 'Skill',
    'settings.skills.headerPlugin': 'Plugin',
    'settings.skills.headerCommands': 'Commands',
    'settings.skills.headerAgent': 'Agent',
    'settings.skills.managerNotAvailable': 'Skills manager not available.',
    'settings.skills.empty': 'No skills yet. Create one above.',
    'settings.skills.editSkill': 'Edit skill: {{name}}',
    'settings.skills.skillDetail': 'Skill: {{name}}',
    'settings.skills.readme': 'README: {{name}}',
    'settings.skills.edit': 'Edit',
    'settings.skills.export': 'Export',
    'settings.skills.delete': 'Delete',
    'settings.skills.editFile': 'Edit skill file',
    'settings.skills.viewReadme': 'View readme',
    'settings.skills.noReadme': 'No readme available',
    'settings.skills.installed': 'Installed & enabled',
    'settings.skills.disabled': 'Disabled in Obsidian',
    'settings.skills.importFailed': 'Could not import skill',
    'settings.skills.createFailed': 'Could not create skill',
    'settings.skills.deleteFailed': 'Could not delete skill file',
    'settings.skills.scanComplete': 'VaultDNA: scanned {{count}} plugins',
    'settings.skills.scanFailed': '`VaultDNA` scan failed',
    'settings.skills.fileNotFound': 'Skill file not found: {{id}}.skill.md',
    'settings.skills.noReadmeAvailable': 'No README available for {{name}}. Run "rescan vault" to fetch READMEs.',
    'settings.skills.corePlugins': 'Core plugin skills ({{count}})',
    'settings.skills.communityPlugins': 'Community plugin skills ({{count}})',

    // =========================================================================
    // Settings — Prompts Tab
    // =========================================================================
    'settings.prompts.heading': 'Prompts',
    'settings.prompts.desc': 'Create your own prompt templates. Type / in the chat to trigger them. Use {{userInput}} to insert your current message text, and {{activeFile}} to insert the name of the active note.',
    'settings.prompts.introTitle': 'Prompts',
    'settings.prompts.introDesc': 'Reusable text snippets you trigger with a slash command. Insert a templated question (e.g. `/translate`) with the active note auto-filled.',
    'settings.prompts.introDiff': 'Difference: prompts are pure text templates without logic. Workflows are structured sequences. Skills are adaptive behaviors with conditions. Rules are static constraints.',
    'settings.prompts.namePlaceholder': 'Prompt name (e.g. "daily-report")',
    'settings.prompts.formName': 'Name (e.g. "daily report")',
    'settings.prompts.formSlug': 'Slug (e.g. "daily-report")',
    'settings.prompts.formTemplate': 'Prompt template (use {{userInput}} and {{activeFile}})',
    'settings.prompts.create': 'Create prompt',
    'settings.prompts.import': 'Import',
    'settings.prompts.save': 'Save',
    'settings.prompts.cancel': 'Cancel',
    'settings.prompts.newPrompt': 'New prompt',
    'settings.prompts.editPrompt': 'Edit prompt',
    'settings.prompts.variables': 'Variables: {{userInput}} = current chat message  |  {{activeFile}} = active note name',
    'settings.prompts.modeLabel': 'Mode (optional):',
    'settings.prompts.modeAll': 'All modes',
    'settings.prompts.modeHint': 'Restrict this prompt to a specific mode. Leave blank to show in all modes.',
    'settings.prompts.empty': 'No custom prompts yet. Create one above.',
    'settings.prompts.edit': 'Edit',
    'settings.prompts.export': 'Export',
    'settings.prompts.delete': 'Delete',
    'settings.prompts.invalidFile': 'Invalid prompt file: missing name, slug, or content',
    'settings.prompts.importFailed': 'Could not import prompt',

    // =========================================================================
    // Settings — Interface Tab
    // =========================================================================
    'settings.interface.introTitle': 'Interface',
    'settings.interface.introDesc': 'Chat behaviour you see every day: keyboard shortcuts, auto-attaching the open note, where chat history is saved.',
    'settings.interface.headingSetup': 'Setup dialog',
    'settings.interface.sectionSetupInfo': 'A short guided walkthrough that runs the first time you open the chat: pick a model, set permissions, set up memory. You can rerun it any time if you want to reconfigure from scratch.',
    'settings.interface.headingInterface': 'Chat behaviour',
    'settings.interface.sectionInterfaceInfo': 'Day-to-day controls for the chat: keyboard shortcuts, what context is auto-attached to your messages, and the context-window progress bar.',
    'settings.interface.headingHistory': 'Chat history',
    'settings.interface.sectionHistoryInfo': 'Where the chat history goes. By default it is kept only in memory and is lost on app reload. Point this at a vault folder and each conversation is saved as a JSON file you can re-open from the ellipsis menu.',
    'settings.interface.showContextProgress': 'Show context progress',
    'settings.interface.showContextProgressDesc': 'Display a progress bar showing how full the model\'s context window is. Restart the sidebar to apply.',
    'settings.interface.restartSidebarNotice': 'Please restart the sidebar (close and reopen) to apply changes.',
    'settings.interface.guidedSetup': 'Guided setup',
    'settings.interface.setupCompleted': 'Setup completed. Restart to re-configure model, permissions, and profile.',
    'settings.interface.setupNotStarted': 'Setup not started yet. Open the chat to begin.',
    'settings.interface.memoryNotAvailable': 'Memory service not available. Enable memory to use the setup dialog.',
    'settings.interface.autoAddActiveNote': 'Auto-add active note as context',
    'settings.interface.autoAddActiveNoteDesc': 'Automatically attach the note you have open in the editor to every message you send. The agent can see and reference its content.',
    'settings.interface.sendWithEnter': 'Send with enter',
    'settings.interface.sendWithEnterDesc': 'Press Enter to send a message (Shift+Enter for a line break). When off, use Ctrl+Enter (or Cmd+Enter on Mac) to send.',
    'settings.interface.includeTime': 'Include the current time of day in context',
    'settings.interface.includeTimeDesc': 'The current date is always given to the agent. Turn this on to also include the exact time of day. Off by default: the time changes on every request and defeats prompt caching, which raises cost on long conversations.',
    'settings.interface.historyFolder': 'Chat history folder',
    'settings.interface.historyFolderDesc': 'Save each conversation as a JSON file in this vault folder. Leave empty to disable. Access saved conversations via the ellipsis menu in the chat. Example: agent/history',
    'settings.interface.restartSetup': 'Restart setup',
    'settings.interface.startSetup': 'Start setup',
    'settings.interface.skipSetup': 'Skip setup',
    'settings.interface.historyPlaceholder': 'Agent/history',
    'settings.interface.setupSkipped': 'Setup skipped. You can restart it anytime from settings.',
    'settings.interface.headingChatLinking': 'Chat linking',
    'settings.interface.sectionChatLinkingInfo': 'When the agent creates or edits a note in a chat, it can leave a back-link in the note\'s frontmatter that opens the originating chat. Useful when a note was the output of a long conversation and you want to revisit how it was produced.',
    'settings.interface.chatLinkingToggle': 'Auto-link chats in frontmatter',
    'settings.interface.chatLinkingToggleDesc': 'Automatically add a clickable chat reference to the frontmatter of every note the agent creates or edits. Disable to keep frontmatter clean.',
    'settings.interface.chatLinkingModel': 'Titling model',
    'settings.interface.chatLinkingModelDesc': 'Select a small, fast model for cost-efficient semantic title generation. Leave empty to use the first 60 characters as title.',
    'settings.interface.chatLinkingNoModels': 'No models configured. Add and enable a model in providers first.',
    'settings.interface.chatLinkingSelectModel': 'No semantic titling',

    // =========================================================================
    // Settings — Shell Tab
    // =========================================================================
    'settings.shell.introTitle': 'External commands',
    'settings.shell.introDesc': 'Lets the agent run other plugins (Dataview, Templater, Pandoc) and a few sandboxed system commands. Off by default.',
    'settings.shell.headingPluginApi': 'Plugin API',
    'settings.shell.sectionPluginApiInfo': "Other Obsidian plugins (Dataview, Templater, MetaEdit, etc.) expose JavaScript functions you can call from a script. With this on, the agent can call those functions to query data and perform actions. Everything runs inside Obsidian's JavaScript sandbox, no shell, no network calls beyond what the plugin itself does.",
    'settings.shell.headingAllowlist': 'Built-in allowlist',
    'settings.shell.sectionAllowlistInfo': 'Plugin methods that Vault Operator ships with as pre-approved. Read methods (queries, lookups) auto-approve; write methods (changes to your notes or plugin state) still require your confirmation in the chat.',
    'settings.shell.headingUserSafe': 'User safe-marked methods',
    'settings.shell.sectionUserSafeInfo': 'Methods the agent discovered at runtime that you marked as safe (read-only) when prompted. Remove an entry to require approval again the next time.',
    'settings.shell.headingRecipes': 'Recipes',
    'settings.shell.sectionRecipesInfo': 'Recipes wrap external programs (Pandoc for PDF/DOCX export, ImageMagick for conversions, etc.) with strict parameter validation. They run via spawn, never through a shell, so input is treated as data, not commands. Off by default; enable each recipe individually after turning the master toggle on.',
    'settings.shell.headingBuiltinRecipes': 'Built-in recipes',
    'settings.shell.enablePluginApi': 'Allow plugin API calls',
    'settings.shell.enablePluginApiDesc': 'Master toggle for everything in this section. Off = no plugin API calls at all.',
    'settings.shell.markedSafe': 'Marked as safe (read), auto-approvable',
    'settings.shell.enableRecipes': 'Allow recipes',
    'settings.shell.enableRecipesDesc': 'Master toggle. Each recipe still needs its own toggle below.',
    'settings.shell.badgeWrite': ' [write]',
    'settings.shell.badgeRead': ' [read]',
    'settings.shell.remove': 'Remove',

    // =========================================================================
    // Settings — Log Tab
    // =========================================================================
    'settings.log.introTitle': 'Activity log',
    'settings.log.introDesc': 'What the agent did and when. Kept for 30 days, useful to retrace a task or report a bug.',
    'settings.log.desc': 'Audit trail of all tool executions. Logs are stored per day (up to 30 days). Click a row to expand details.',
    'settings.log.load': 'Load',
    'settings.log.download': 'Download',
    'settings.log.clearAll': 'Clear all logs',
    'settings.log.noLogs': 'No logs yet',
    'settings.log.loggerNotAvailable': 'Logger not available',
    'settings.log.noEntries': 'No entries for this date.',
    'settings.log.headerTime': 'Time',
    'settings.log.headerTool': 'Tool',
    'settings.log.headerMode': 'Mode',
    'settings.log.headerDuration': 'Duration',
    'settings.log.headerStatus': 'Status',
    'settings.log.statusOk': 'OK',
    'settings.log.statusError': 'Error',
    'settings.log.detailParams': 'Params',
    'settings.log.detailResult': 'Result',
    'settings.log.detailError': 'Error',
    'settings.log.noData': 'No log data to download',
    'settings.log.downloaded': 'Downloaded log: {{date}}',
    'settings.log.cleared': 'All operation logs cleared',
    'settings.log.durationMs': '{{ms}} ms',

    // =========================================================================
    // Settings — Debug Tab
    // =========================================================================
    'settings.debug.introTitle': 'Debug mode',
    'settings.debug.introDesc': 'Verbose logs in the browser console (Ctrl+Shift+I). Turn on when something misbehaves, off otherwise.',
    'settings.debug.debugMode': 'Debug mode',
    'settings.debug.debugModeDesc': 'Write detailed logs to the browser developer console. Open the console with Cmd+Option+I (Mac) or Ctrl+Shift+I (Windows).',
    'settings.debug.optionalAssetsHeading': 'Optional assets',
    'settings.debug.optionalAssetsInfo': 'Optional one-time downloads that stay out of the main plugin bundle so it remains under Obsidian Sync\'s 5 MB threshold. Each asset is SHA256-verified before it lands in <vault>/.vault-operator/assets/. The plugin works without any of them; the corresponding tool reports "not installed" until you click Install.',

    // Optional assets sub-tab
    'settings.optionalAssets.introTitle': 'Optional assets',
    'settings.optionalAssets.introDesc': 'One-time downloads that stay out of the main plugin bundle so it remains under Obsidian Sync\'s 5 MB threshold. Each asset is SHA256-verified before it lands in <vault>/.vault-operator/assets/. The plugin works without any of them; the corresponding tool reports "not installed" until you click Install.',
    'settings.optionalAssets.headingOffice': 'Office bundle',
    'settings.optionalAssets.sectionOfficeInfo': 'Bundles exceljs, docx and pptxgenjs (~1.7 MB). Required to create or read .xlsx / .docx / .pptx files. Without it, the create_xlsx / create_docx / create_pptx tools stay disabled.',
    'settings.optionalAssets.officeNotInstalled': 'Status: not installed. The office document tools stay disabled.',
    'settings.optionalAssets.headingPdf': 'PDF parser',
    'settings.optionalAssets.sectionPdfInfo': 'The pdfjs-dist library bundles its own worker (~1.6 MB). Required to extract text from PDF attachments during ingest. Without it, PDFs are skipped.',
    'settings.optionalAssets.pdfNotInstalled': 'Status: not installed. PDF files are skipped during ingestion.',
    'settings.optionalAssets.headingSelfDev': 'Self-development source',
    'settings.optionalAssets.sectionSelfDevInfo': 'A snapshot of the plugin\'s own source code (~5 MB) that the self-modification tools (manage_source) can read and edit. Ships in a separate release tag because of size; local-file install is the recommended path.',
    'settings.optionalAssets.selfDevNotInstalled': 'Status: not installed. The manage_source tool stays disabled.',
    'settings.tab.optionalAssets': 'Optional assets',

    // =========================================================================
    // Settings — Backup Tab
    // =========================================================================
    'settings.backup.introTitle': 'Backup',
    'settings.backup.introDesc': 'Export everything (settings, memory, history, skills, workflows) to one file. Import to restore or to move to a new device.',
    'settings.backup.desc': 'Export and import plugin data for backup or migration to another device.',
    'settings.backup.headingExport': 'Export',
    'settings.backup.headingImport': 'Import',
    'settings.backup.catSettings': 'Plugin settings',
    'settings.backup.catSettingsDesc': 'API keys, modes, permissions, all configuration',
    'settings.backup.catMemory': 'Agent memory',
    'settings.backup.catMemoryDesc': 'Long-term memory and session summaries',
    'settings.backup.catHistory': 'Chat history',
    'settings.backup.catHistoryDesc': 'Full conversation transcripts',
    'settings.backup.catWorkflows': 'Workflows',
    'settings.backup.catWorkflowsDesc': 'Custom workflow definitions',
    'settings.backup.catRules': 'Custom rules',
    'settings.backup.catRulesDesc': 'Custom agent rules',
    'settings.backup.catSkills': 'Custom skills',
    'settings.backup.catSkillsDesc': 'Custom skill definitions',
    'settings.backup.catPluginSkills': 'Plugin skill files',
    'settings.backup.catPluginSkillsDesc': 'Auto-generated skill and readme files from `VaultDNA` scanner',
    'settings.backup.catVaultDNA': '`VaultDNA` scan cache',
    'settings.backup.catVaultDNADesc': 'Plugin scan results (vault-dna.json), avoids rescan on import',
    'settings.backup.catSemanticIndex': 'Semantic index',
    'settings.backup.catSemanticIndexDesc': 'Knowledge database and vector index (can be rebuilt by re-indexing)',
    'settings.backup.catLogs': 'Operation logs',
    'settings.backup.catLogsDesc': 'Agent operation log history',
    'settings.backup.export': 'Export backup',
    'settings.backup.exporting': 'Exporting...',
    'settings.backup.selectFile': 'Select backup file',
    'settings.backup.confirmImport': 'Confirm import',
    'settings.backup.importing': 'Importing...',
    'settings.backup.cancel': 'Cancel',
    'settings.backup.overwriteWarning': 'Existing files will be overwritten.',
    'settings.backup.backupFrom': 'Backup from {{date}} (v{{version}})',
    'settings.backup.invalidFile': 'Invalid backup file. The format is not recognized.',
    'settings.backup.exported': 'Backup exported: {{files}} files in {{categories}} categories ({{size}})',
    'settings.backup.exportFailed': 'Export failed: {{error}}',
    'settings.backup.imported': 'Backup imported: {{files}} files in {{categories}} categories. Reload Obsidian for full effect.',
    'settings.backup.importFailed': 'Import failed: {{error}}',

    // =========================================================================
    // Settings — Vault Tab
    // =========================================================================
    'settings.vault.desc': 'Checkpoints snapshot each file before the agent first modifies it. After a task you can undo all changes with one click.',
    'settings.vault.headingCheckpoints': 'Checkpoints',
    'settings.vault.sectionCheckpointsInfo': 'Before the agent first writes to a file, Vault Operator takes a snapshot of the original. After a multi-step task you can roll the whole edit back from the undo button in the chat. Snapshots live in the agent folder; they are cleared on demand or automatically after the task.',
    'settings.vault.enableCheckpoints': 'Enable checkpoints',
    'settings.vault.enableCheckpointsDesc': 'Save a backup copy of each file before the agent changes it. After a task you can restore the originals with the undo button.',
    'settings.vault.snapshotTimeout': 'Snapshot timeout (seconds)',
    'settings.vault.snapshotTimeoutDesc': 'How long to wait for a file backup to finish before skipping it. Increase if you have very large files. Default: 30.',
    'settings.vault.autoCleanup': 'Auto-cleanup after task',
    'settings.vault.autoCleanupDesc': 'Delete the backup copies once a task finishes. Saves disk space. Disable if you want to review the backups manually after a task.',

    // =========================================================================
    // Settings — Vault Tab: Task Extraction
    // =========================================================================
    'settings.vault.taskExtraction': 'Task extraction',
    'settings.vault.sectionTaskExtractionInfo': 'When the agent writes a response that contains task checkboxes (`- [ ] do something`), Vault Operator can pull those tasks out and create individual task notes with frontmatter (status, source chat, due date if mentioned). Useful for "extract todos from this meeting transcript" workflows.',
    'settings.vault.taskExtractionDesc': 'Detects tasks (- [ ] items) in agent responses and creates task notes with structured frontmatter.',
    'settings.vault.taskExtractionEnable': 'Enable task extraction',
    'settings.vault.taskExtractionEnableDesc': 'Scan for tasks after every agent response and show a selection modal.',
    'settings.vault.taskFolder': 'Task folder',
    'settings.vault.taskFolderDesc': 'Vault folder where task notes and the task base are created.',
    'settings.vault.preferTaskNotes': 'Prefer `TaskNotes` plugin',
    'settings.vault.preferTaskNotesDesc': 'When the community plugin `TaskNotes` is active, create tasks in its format. Otherwise the built-in format is used.',
    'settings.vault.agentFolderHeading': 'Agent folder',
    'settings.vault.sectionAgentFolderInfo': 'Where Vault Operator keeps its own data inside the vault: plugin skills, the vault-DNA snapshot, externalised tmp results, the knowledge and memory databases. Change this if you want the plugin\'s files in a specific location (for example excluded from Obsidian Sync). Existing files are not auto-migrated when you change the path; use the "Migrate data" button below.',
    'settings.vault.agentFolderDesc': 'Vault-relative folder where the plugin keeps its own files: plugin skills, the vault-DNA snapshot, externalised tmp results, and the local knowledge database. Existing files are not auto-migrated when you change this path.',
    'settings.vault.agentFolder': 'Folder',
    'settings.vault.agentFolderFieldDesc': 'Default is a hidden folder inside your vault. Use the picker to open your native folder dialog, or type a path. Folders outside the vault are partially supported in this release — plugin skills, tmp results, and the local knowledge database continue to live inside the vault.',
    'settings.vault.agentFolderPick': 'Pick folder…',
    'settings.vault.agentFolderMigrate': 'Migrate data',
    'settings.vault.agentFolderMigrateDesc': 'Copy plugin skills, vault-DNA snapshot, and the knowledge / memory databases from an older agent folder into the current one. Originals stay in place. Delete them manually after you confirmed the new location works. Reload Obsidian after migration so the databases open at the new path.',
    'settings.vault.agentFolderMigrateButton': 'Migrate data from old folder…',
    'settings.vault.headingIngest': 'Vault ingest',
    'settings.vault.sectionIngestInfo': 'Builds a wiki-like layer on top of the vault: per-note summaries, optional frontmatter mirroring, and automatic triage of inbox notes based on a frontmatter property. Everything is off by default. Auto-trigger changes require a plugin reload to take effect.',

    // =========================================================================
    // Settings — Visual Intelligence Tab
    // =========================================================================
    'settings.visual.libreOffice': '`LibreOffice`',
    'settings.visual.libreOfficeNotFound': '`LibreOffice` not found',
    'settings.visual.libreOfficeFound': '`LibreOffice` found: {{path}}',
    'settings.visual.downloadLibreOffice': 'Download `LibreOffice`',
    'settings.visual.customLibreOfficePath': 'Custom `LibreOffice` path',

    // =========================================================================
    // UI — Task Selection Modal
    // =========================================================================
    'ui.taskSelection.title': '{{count}} task(s) detected',
    'ui.taskSelection.subtitle': 'Which tasks should be created as task notes?',
    'ui.taskSelection.hintTaskNotes': 'Tasks will be created in `TaskNotes` format.',
    'ui.taskSelection.hintDefault': 'Tip: the community plugin `TaskNotes` offers extended task management.',
    'ui.taskSelection.selectNone': 'Select none',
    'ui.taskSelection.selectAll': 'Select all',
    'ui.taskSelection.create': '{{count}} create',
    'ui.taskSelection.cancel': 'Cancel',
    'ui.taskSelection.due': 'Due: {{date}}',

    // =========================================================================
    // Notices — Task Extraction
    // =========================================================================
    'notice.taskNotesCreated': '{{count}} task note(s) created{{format}}',
    'notice.taskNotesCreatedFormatSuffix': ' (`TaskNotes` format)',
    'notice.taskNotesError': 'Error creating task notes',
    'notice.taskExtractionError': 'Task extraction error: {{error}}',

    // =========================================================================
    // Settings — Language Tab
    // =========================================================================
    'settings.language.introTitle': 'Display language',
    'settings.language.introDesc': 'Choose the language for the plugin interface. Communication with the agent can happen in any language, regardless of this setting.',
    'settings.language.language': 'Language',
    'settings.language.languageDesc': 'Select the display language for the plugin interface. English is the fallback for untranslated strings.',
    'settings.language.restartHint': 'Restart Obsidian for all changes to take effect.',

    // =========================================================================
    // Constants — Provider Labels
    // Brand names moved to src/ui/settings/constants.ts (not locale-dependent).
    // Only translatable labels remain here.
    // =========================================================================
    'provider.custom': 'Custom',

    // =========================================================================
    // Constants — Tool Labels
    // =========================================================================
    'tool.read_file': 'Read file',
    'tool.read_file.desc': 'Read the contents of a vault file',
    'tool.list_files': 'List files',
    'tool.list_files.desc': 'List files and folders in a directory',
    'tool.search_files': 'Search files',
    'tool.search_files.desc': 'Search file contents by keyword or regex',
    'tool.get_vault_stats': 'Vault stats',
    'tool.get_vault_stats.desc': 'Get overview stats (file count, tags, etc.)',
    'tool.get_frontmatter': 'Frontmatter',
    'tool.get_frontmatter.desc': 'Read YAML frontmatter from a note',
    'tool.search_by_tag': 'Search by tag',
    'tool.search_by_tag.desc': 'Find notes with specific tags',
    'tool.get_linked_notes': 'Linked notes',
    'tool.get_linked_notes.desc': 'Find notes that link to or from a note',
    'tool.get_daily_note': 'Daily note',
    'tool.get_daily_note.desc': "Get or create today's daily note",
    'tool.open_note': 'Open note',
    'tool.open_note.desc': 'Open a note in the editor',
    'tool.semantic_search': 'Semantic search',
    'tool.semantic_search.desc': 'Find notes by meaning using the vector index',
    'tool.query_base': 'Query base',
    'tool.query_base.desc': 'Query an Obsidian bases database',
    'tool.write_file': 'Write file',
    'tool.write_file.desc': 'Create a new file or overwrite completely',
    'tool.edit_file': 'Edit file',
    'tool.edit_file.desc': 'Make targeted edits to a file',
    'tool.append_to_file': 'Append to file',
    'tool.append_to_file.desc': 'Add content at the end of a file',
    'tool.create_folder': 'Create folder',
    'tool.create_folder.desc': 'Create a new folder in the vault',
    'tool.delete_file': 'Delete file',
    'tool.delete_file.desc': 'Permanently delete a file or folder',
    'tool.move_file': 'Move / rename',
    'tool.move_file.desc': 'Move or rename a file',
    'tool.update_frontmatter': 'Update frontmatter',
    'tool.update_frontmatter.desc': 'Set or update YAML frontmatter fields',
    'tool.generate_canvas': 'Generate canvas',
    'tool.generate_canvas.desc': 'Create an Obsidian canvas file',
    'tool.create_base': 'Create base',
    'tool.create_base.desc': 'Create an Obsidian bases database',
    'tool.update_base': 'Update base',
    'tool.update_base.desc': 'Modify an Obsidian bases database',
    'tool.web_fetch': 'Fetch URL',
    'tool.web_fetch.desc': 'Download and read a web page',
    'tool.web_search': 'Web search',
    'tool.web_search.desc': 'Search the web for current information',
    'tool.ask_followup_question': 'Ask user',
    'tool.ask_followup_question.desc': 'Ask the user a clarifying question',
    'tool.attempt_completion': 'Complete task',
    'tool.attempt_completion.desc': 'Signal that the task is done',
    'tool.update_todo_list': 'Update todos',
    'tool.update_todo_list.desc': 'Show a task checklist in the chat',
    'tool.new_task': 'Spawn sub-agent',
    'tool.new_task.desc': 'Delegate a subtask to a fresh agent',
    'tool.use_mcp_tool': 'Protocol tool',
    'tool.use_mcp_tool.desc': 'Call an external tool via a protocol server',

    // =========================================================================
    // Constants — Tool Group Labels
    // =========================================================================
    'toolGroup.read': 'Read files',
    'toolGroup.read.desc': 'Read and search vault files',
    'toolGroup.vault': 'Vault intelligence',
    'toolGroup.vault.desc': 'Frontmatter, tags, backlinks, daily notes, semantic search, canvas, bases',
    'toolGroup.edit': 'Edit files',
    'toolGroup.edit.desc': 'Create, edit, move, and structure vault files and canvases',
    'toolGroup.web': 'Web access',
    'toolGroup.web.desc': 'Fetch web pages and search the internet',
    'toolGroup.agent': 'Agent control',
    'toolGroup.agent.desc': 'Task planning, completion, clarification, and sub-agent spawning',
    'toolGroup.mcp': 'Protocol tools',
    'toolGroup.mcp.desc': 'Call external tools via configured protocol servers',

    // =========================================================================
    // Chat UI — Sidebar
    // =========================================================================
    'ui.sidebar.title': 'Vault Operator',
    'ui.sidebar.settings': 'Settings',
    'ui.sidebar.vaultHealth': 'Vault health findings available',
    'ui.sidebar.chatHistory': 'Chat history',
    'ui.sidebar.newChat': 'New chat',
    'ui.sidebar.selectMode': 'Select mode',
    'ui.sidebar.selectModel': 'Select model',
    'ui.sidebar.selectTools': 'Select tools',
    'ui.sidebar.selectMcpServers': 'Select MCP servers',
    'ui.sidebar.toggleWebSearch': 'Toggle web search',
    'ui.sidebar.attachFile': 'Attach file',
    'ui.sidebar.addVaultFile': 'Add vault file',
    'ui.sidebar.addContext': 'Add context',
    'ui.sidebar.moreOptions': 'More options',
    'ui.sidebar.webSearchOn': 'Web search (on)',
    'ui.sidebar.webSearchOff': 'Web search (off)',
    'ui.sidebar.saveToMemory': 'Save conversation to memory',
    'ui.history.saveToMemory': 'Save this conversation to memory',
    'ui.history.removeFromMemory': 'Remove this conversation from memory',
    'ui.history.rename': 'Rename conversation',
    'ui.history.renameTitle': 'Rename conversation',
    'ui.history.renameMessage': 'Set a new title for this conversation.',
    'ui.history.renameSubmit': 'Rename',
    'ui.history.filterMemoryOnly': 'Show only conversations saved to memory',
    'ui.sidebar.stop': 'Stop',
    'ui.sidebar.send': 'Send message',
    'ui.sidebar.placeholder': 'Type your message here...',
    'ui.sidebar.noModel': 'No model',
    'ui.sidebar.modeOverride': '{{label}} (mode override)',
    'ui.sidebar.noModelsEnabled': 'No models enabled, open settings',
    'ui.sidebar.useGlobalDefault': 'Use global default ({{label}})',
    'ui.sidebar.globalDefault': 'Global default',
    'ui.sidebar.working': 'Working\u2026',
    'ui.sidebar.reasoning': 'Reasoning\u2026',
    'ui.sidebar.reasoningCollapsed': 'Reasoning',
    'ui.sidebar.analyzing': 'Analyzing results\u2026',
    'ui.sidebar.analyzingShort': 'Analyzing\u2026',
    'ui.sidebar.actionSingular': '1 action',
    'ui.sidebar.actionPlural': '{{count}} actions',
    'ui.sidebar.emptyResponse': '(no response from agent)',
    'ui.sidebar.tokenUsage': '{{time}}  \u00B7  {{input}} in \u00B7 {{output}} out',
    'ui.sidebar.contextCondensed': 'Context condensed',
    'ui.sidebar.newConversation': 'New conversation',
    'ui.sidebar.conversation': 'Conversation',
    'ui.sidebar.copy': 'Copy',
    'ui.sidebar.editResend': 'Edit & resend',
    'ui.sidebar.currentFile': 'Current',
    // FEAT-24-08 / ADR-114 Steering-Hook
    'ui.sidebar.steeringLabel': 'Steering',
    'ui.sidebar.steeringQueued': 'Queued for next iteration',
    'ui.sidebar.steeringDelivered': 'Delivered at iteration {{iteration}}',
    'ui.sidebar.steeringDiscarded': 'Not delivered (task ended before drain)',
    'ui.sidebar.insertAtCursor': 'Insert at cursor',
    'ui.sidebar.createNote': 'Create note from response',
    'ui.sidebar.synthesisZettel': 'Create synthesis note',
    'ui.sidebar.copyResponse': 'Copy response',
    'ui.sidebar.regenerate': 'Regenerate response',
    'ui.sidebar.deleteResponse': 'Delete response',
    'ui.sidebar.sources': '{{count}} sources',
    'ui.sidebar.plan': 'Plan',
    'ui.sidebar.activity': 'Activity',
    'ui.sidebar.activityCount': '{{count}} action(s)',

    // =========================================================================
    // Chat UI — Options Menu
    // =========================================================================
    'ui.menu.refreshIndex': 'Refresh index (current file)',
    'ui.menu.forceReindex': 'Force reindex vault',
    'ui.menu.cancelIndexing': 'Cancel indexing',
    'ui.menu.addOpenNote': 'Add open note in context',
    'ui.menu.autoAcceptEdits': 'Auto-accept edits',

    // =========================================================================
    // Chat UI — Tool Activity Labels
    // =========================================================================
    'ui.toolActivity.readFile': 'Reading file',
    'ui.toolActivity.readFiles': 'Reading files',
    'ui.toolActivity.listFiles': 'Listing files',
    'ui.toolActivity.searching': 'Searching',
    'ui.toolActivity.readingMetadata': 'Reading metadata',
    'ui.toolActivity.findingLinks': 'Finding links',
    'ui.toolActivity.searchingByTag': 'Searching by tag',
    'ui.toolActivity.vaultOverview': 'Vault overview',
    'ui.toolActivity.readingDailyNote': 'Reading daily note',
    'ui.toolActivity.readingDailyNotes': 'Reading daily notes',
    'ui.toolActivity.fetchingPage': 'Fetching page',
    'ui.toolActivity.fetchingPages': 'Fetching pages',
    'ui.toolActivity.searchingWeb': 'Searching web',
    'ui.toolActivity.semanticSearch': 'Semantic search',
    'ui.toolActivity.semanticSearches': 'Semantic searches',

    // =========================================================================
    // Chat UI — Question Card
    // =========================================================================
    'ui.question.confirm': 'Confirm selection',
    'ui.question.placeholder': 'Type your answer...',
    'ui.question.answer': 'Answer',

    // =========================================================================
    // Chat UI — Approval Card
    // =========================================================================
    'ui.approval.noteEdits': 'Note edits',
    'ui.approval.vaultChanges': 'Vault changes',
    'ui.approval.web': 'Web',
    'ui.approval.mcp': 'MCP',
    'ui.approval.read': 'Read',
    'ui.approval.modeSwitching': 'Mode switching',
    'ui.approval.subAgents': 'Sub-agents',
    'ui.approval.pluginSkills': 'Plugin skills',
    'ui.approval.pluginApi': 'Plugin API',
    'ui.approval.recipes': 'Recipes',
    'ui.approval.sandbox': 'Sandbox execution',
    'ui.approval.notEnabled': 'Approve {{group}}: {{tool}}',
    'ui.approval.allowOnce': 'Allow once',
    'ui.approval.enableInSettings': 'Always allow',
    'ui.approval.configDirWarning': 'Write access to protected directory: {{path}}. Files in this directory control plugins, themes, and Obsidian settings. Unintended changes can alter Obsidian behavior or install malicious code as a plugin.',
    'ui.approval.explain.writeFile': 'The agent wants to create a new file:',
    'ui.approval.explain.editFile': 'The agent wants to edit an existing file:',
    'ui.approval.explain.appendFile': 'The agent wants to append text to a file:',
    'ui.approval.explain.deleteFile': 'The agent wants to move a file to the trash:',
    'ui.approval.explain.moveFile': 'The agent wants to move a file:',
    'ui.approval.explain.moveFileTo': 'To',
    'ui.approval.explain.createFolder': 'The agent wants to create a new folder:',
    'ui.approval.explain.sandbox': 'The agent wants to run a script to process data in your vault.',
    'ui.approval.explain.webFetch': 'The agent wants to fetch a web page:',
    'ui.approval.explain.webSearch': 'The agent wants to search the internet for:',
    'ui.approval.explain.newTask': 'The agent wants to start a sub-agent for a subtask.',
    'ui.approval.explain.mcpTool': 'The agent wants to use an external tool:',
    'ui.approval.explain.pluginApi': 'The agent wants to access a plugin:',
    'ui.approval.explain.command': 'The agent wants to run an Obsidian command:',
    'ui.approval.explain.recipe': 'The agent wants to run a recipe:',
    'ui.approval.explain.switchMode': 'The agent wants to switch to a different mode.',
    'ui.approval.explain.frontmatter': 'The agent wants to change the metadata of a note:',
    'ui.approval.explain.canvas': 'The agent wants to create a canvas visualization:',
    'ui.approval.explain.excalidraw': 'The agent wants to create an Excalidraw drawing:',
    'ui.approval.explain.selfModify': 'The agent wants to change its own configuration.',
    'ui.approval.explain.fallback': 'The agent wants to perform the following action:',
    'ui.approval.explain.showDetails': 'Show details',
    'ui.approval.explain.hideDetails': 'Hide details',

    // =========================================================================
    // Chat UI — Checkpoint
    // =========================================================================
    'ui.checkpoint.label': 'Checkpoint \u00B7 {{files}} \u00B7 {{time}}',
    'ui.checkpoint.restore': 'Restore checkpoint',
    'ui.checkpoint.keepChat': 'Keep chat',
    'ui.checkpoint.deleteFromHere': 'Delete chat from here',
    'ui.checkpoint.cancel': 'Cancel',
    'ui.checkpoint.restoring': 'Restoring...',
    'ui.checkpoint.error': 'Error',
    'ui.checkpoint.nothingToRestore': 'Nothing to restore',
    'ui.checkpoint.restored': 'Restored {{count}} file(s)',
    'ui.checkpoint.failed': 'Failed',

    // =========================================================================
    // Chat UI — Undo Bar
    // =========================================================================
    'ui.undo.modified': 'Agent modified {{count}} file(s).',
    'ui.undo.undoAll': 'Undo all changes',
    'ui.undo.restoring': 'Restoring\u2026',
    'ui.undo.restored': 'Restored {{count}} file(s).',
    'ui.undo.noCheckpoint': 'No checkpoint found to restore.',
    'ui.undo.restoreFailed': 'Restore failed. See console.',

    // =========================================================================
    // Chat UI — Error Messages
    // =========================================================================
    'ui.error.invalidKey': 'Invalid API key. Check the agent settings.',
    'ui.error.modelNotFound': 'Model not found. Verify the model ID in the agent settings.',
    'ui.error.rateLimit': 'Rate limit reached. Please wait a moment.',
    'ui.error.overloaded': 'API overloaded. Try again shortly.',
    'ui.error.network': 'Network error. Check your connection and that the local server is running.',
    'ui.error.generic': 'Error',
    'ui.error.ollamaNotRunning': '{{model}} could not start. Make sure Ollama is running (`ollama serve`) and the model name is correct. Open settings -> Vault Operator -> configure to verify.',

    // =========================================================================
    // Notices
    // =========================================================================
    'notice.webSearchEnabled': 'Web search enabled. Set a search provider in settings > web search.',
    'notice.memoryDisabled': 'Memory is disabled. Enable it in settings, then try again.',
    'notice.memoryNoActiveConversation': 'No active conversation to save.',
    'notice.memorySaveQueued': 'Conversation queued for memory extraction.',
    'notice.memorySaveFailed': 'Saving the conversation failed. See console for details.',
    'notice.memoryRemoved': 'Removed {{count}} fact(s) from memory for "{{title}}".',
    'notice.modeSwitched': 'Switched to {{mode}} mode',
    'notice.taskComplete': 'Agent task complete',
    'notice.loadConversationFailed': 'Could not load conversation',
    'notice.conversationNotFound': 'This conversation no longer exists. It may have been deleted from history.',
    'notice.copied': 'Copied.',
    'notice.insertedAtCursor': 'Inserted at cursor.',
    'notice.noOpenNote': 'No open note found. Open a note in the editor first.',
    'notice.copiedToClipboard': 'Copied to clipboard',
    'notice.createNoteFailed': 'Could not create note: {{error}}',
    'notice.zettelCreated': 'Synthesis note created',
    'notice.noActiveFile': 'No active file',
    'notice.semanticDisabled': 'Semantic index is disabled',
    'notice.indexRefreshed': 'Index refreshed for current file',
    'notice.indexingInProgress': 'Indexing already in progress',
    'notice.reindexingVault': 'Reindexing vault in background...',
    'notice.vaultIndexRebuilt': 'Vault index rebuilt',
    'notice.reindexFailed': 'Reindex failed: {{error}}',
    'notice.indexingCancelled': 'Indexing cancelled. Partial progress saved.',
    'notice.autoAcceptEdits': 'Auto-accept edits: {{value}}',

    // =========================================================================
    // ToolPicker Popover
    // =========================================================================
    'ui.toolPicker.title': 'Tools & skills',
    'ui.toolPicker.openFailed': 'Could not open the tools picker. See the developer console for details.',
    'ui.mcpPicker.title': 'MCP servers',
    'ui.mcpPicker.empty': 'No MCP servers configured. Add one in Settings -> Providers -> MCP.',
    'ui.mcpPicker.openFailed': 'Could not open the MCP picker. See the developer console for details.',
    'ui.toolPicker.selected': '{{count}} selected',
    'ui.toolPicker.filter': 'Filter\u2026',
    'ui.toolPicker.builtIn': 'Built-in tools',
    'ui.toolPicker.mcpServers': 'Protocol servers',
    'ui.toolPicker.noMcpServers': 'No protocol servers configured.',
    'ui.toolPicker.loading': 'Loading\u2026',
    'ui.toolPicker.workflows': 'Workflows',
    'ui.toolPicker.noWorkflows': 'No workflows found.',
    'ui.toolPicker.errorWorkflows': 'Error loading workflows.',
    'ui.toolPicker.mcpServer': 'Protocol server',

    // =========================================================================
    // VaultFilePicker
    // =========================================================================
    'ui.filePicker.search': 'Search vault files\u2026',
    'ui.filePicker.add': 'Add',
    'ui.filePicker.selected': '{{count}} selected',
    'ui.filePicker.noFiles': 'No files found',
    'ui.filePicker.activeFile': 'Active: {{name}}',

    // =========================================================================
    // History Panel
    // =========================================================================
    'ui.history.title': 'Chat history',
    'ui.history.filter': 'Filter...',
    'ui.history.empty': 'No conversations yet',
    'ui.history.today': 'Today',
    'ui.history.yesterday': 'Yesterday',
    'ui.history.thisWeek': 'This week',
    'ui.history.older': 'Older',
    'ui.history.messageCount': '{{count}} msgs',
    'ui.history.copyLink': 'Copy chat link',
    'ui.history.linkCopied': 'Chat link copied',
    'ui.history.addToNote': 'Add link to active note',
    'ui.history.linkAdded': 'Chat link added to note',
    'ui.history.linkAlreadyExists': 'Link already exists in note',
    'ui.history.linkAddFailed': 'Failed to add link',
    'ui.history.noActiveNote': 'No active Markdown note',

    // =========================================================================
    // Attachment Handler
    // =========================================================================
    'ui.attachment.tooLarge': '"{{name}}" exceeds the 50 MB limit.',
    'ui.attachment.unsupported': '"{{name}}" is not supported. Use images, office documents (PPTX/XLSX/DOCX/PDF), or text files.',
    'ui.attachment.readFailed': 'Could not read "{{path}}"',
    'ui.attachment.largeDocument': '"{{name}}" is very large. Content may be condensed during the conversation.',

    // =========================================================================
    // Modal — New Mode
    // =========================================================================
    'modal.newMode.title': 'New agent',
    'modal.newMode.name': 'Name',
    'modal.newMode.nameDesc': 'Display name (e.g. "daily planner")',
    'modal.newMode.shortDesc': 'Short description (for humans)',
    'modal.newMode.shortDescHint': 'Brief description shown in the agent selector dropdown.',
    'modal.newMode.shortDescPlaceholder': 'Brief description...',
    'modal.newMode.roleDefinition': 'Role definition',
    'modal.newMode.roleDefinitionHint': "Define the agent's expertise and personality.",
    'modal.newMode.roleDefinitionPlaceholder': "Describe the agent's identity, behavior, and focus area...",
    'modal.newMode.customInstructions': 'Mode-specific custom instructions (optional)',
    'modal.newMode.customInstructionsHint': 'Additional behavioral guidelines for this mode.',
    'modal.newMode.customInstructionsPlaceholder': 'Additional guidelines...',
    'modal.newMode.saveLocation': 'Save location',
    'modal.newMode.saveLocationHint': 'Global modes are available in all your Obsidian vaults.',
    'modal.newMode.thisVault': 'This vault',
    'modal.newMode.thisVaultHint': 'Only in this vault',
    'modal.newMode.global': 'Global',
    'modal.newMode.globalHint': 'All vaults on this machine',
    'modal.newMode.create': 'Create mode',
    'modal.newMode.cancel': 'Cancel',
    'modal.newMode.nameRequired': 'Name is required',
    'modal.newMode.roleRequired': 'Role definition is required',

    // =========================================================================
    // Modal — Model Config
    // =========================================================================
    'modal.modelConfig.addModel': 'Add model',
    'modal.modelConfig.addEmbedding': 'Add embedding model',
    'modal.modelConfig.configure': 'Configure: {{name}}',
    'modal.modelConfig.provider': 'Provider',
    'modal.modelConfig.quickPick': 'Quick pick',
    'modal.modelConfig.quickPickDesc': 'Select to pre-fill model ID',
    'modal.modelConfig.pickModel': 'Pick a model...',
    'modal.modelConfig.fetchModels': 'Fetch current models from provider API',
    'modal.modelConfig.modelsFetched': '{{count}} models fetched',
    'modal.modelConfig.fetchFailed': 'Failed to fetch models: {{error}}',
    'modal.modelConfig.modelId': 'Model ID',
    'modal.modelConfig.modelIdDesc': 'Exact ID used in API calls',
    'modal.modelConfig.modelIdPlaceholder': '`GPT-4o`',
    'modal.modelConfig.displayName': 'Display name',
    'modal.modelConfig.displayNameDesc': 'Label in chat toolbar',
    'modal.modelConfig.displayNamePlaceholder': 'e.g. My {{name}}',
    'modal.modelConfig.apiKey': 'API key',
    'modal.modelConfig.apiKeyPlaceholder': 'Sk-...',
    'modal.modelConfig.baseUrl': 'Base URL',
    'modal.modelConfig.apiVersion': 'API version',
    'modal.modelConfig.apiVersionDesc': 'Required for cloud deployments (e.g. 2024-10-21)',
    'modal.modelConfig.apiVersionPlaceholder': '2024-10-21',
    'modal.modelConfig.maxTokens': 'Max output tokens',
    'modal.modelConfig.maxTokensDesc': 'Cap on tokens generated per response (answer plus tool calls; with extended thinking the reasoning budget is added on top)',
    'modal.modelConfig.maxTokensAuto': 'Automatic (recommended) — sized per model, automatically reduced when the prompt is large',
    'modal.modelConfig.maxTokensNote': 'Manual override. This is an upper bound, not a cost lever — you are billed for the tokens actually generated, not for the limit. Set it low only to bound latency; too low truncates long answers and tool calls and triggers retry loops. The slider is capped at the model\'s real output ceiling.',
    'modal.modelConfig.maxTokensUseRecommended': 'Use recommended ({{value}})',
    'modal.modelConfig.maxTokensUseRecommendedTitle': 'Use the recommended max output tokens for this model',
    'modal.modelConfig.maxTokensPlaceholder': '32000',
    'modal.modelConfig.temperature': 'Temperature',
    'modal.modelConfig.temperatureDesc': 'Randomness of responses (0 = deterministic, higher = creative)',
    'modal.modelConfig.customTemperature': 'Custom temperature',
    'modal.modelConfig.temperatureFixed': 'This model only accepts temperature = 1.0 (enforced by the API).',
    'modal.modelConfig.promptCaching': 'Prompt caching',
    'modal.modelConfig.promptCachingDesc': 'Cache system prompt and recent messages to reduce API costs (supported providers only)',
    'modal.modelConfig.promptCachingTooltip': 'Prompt caching reduces input cost on repeated requests. Anthropic charges +25% on the first cache write, then -90% on every cache read. Net win after 2 iterations. Recommended on for typical agent sessions.',
    'modal.modelConfig.thinking': 'Extended thinking',
    'modal.modelConfig.thinkingDesc': 'Let the model reason before answering. Improves quality on hard tasks (supported models only)',
    'modal.modelConfig.thinkingNote': 'When enabled, temperature is forced to 1 by the API.',
    'modal.modelConfig.thinkingBudget': 'Thinking budget',
    'modal.modelConfig.thinkingBudgetDesc': 'Maximum tokens for internal reasoning (1,024 - 128,000)',
    'modal.modelConfig.temperatureThinkingNote': 'Temperature is locked to 1.0 because extended thinking is enabled.',
    'modal.modelConfig.testConnection': 'Test connection',
    'modal.modelConfig.testing': 'Testing\u2026',
    'modal.modelConfig.add': 'Add',
    'modal.modelConfig.save': 'Save',
    'modal.modelConfig.cancel': 'Cancel',
    'modal.modelConfig.modelIdRequired': 'Model ID is required',
    'modal.modelConfig.enterModelIdFirst': 'Enter a model ID first',
    'modal.modelConfig.browseInstalled': 'Browse installed models',
    'modal.modelConfig.browseAvailable': 'Browse available models',
    'modal.modelConfig.loadingModels': 'Loading\u2026',
    'modal.modelConfig.noModelsOllama': 'No models found. Pull one first, e.g.: ollama pull llama3.2',
    'modal.modelConfig.noModelsUrl': 'No models found at this base URL.',
    'modal.modelConfig.ollamaUnreachable': 'Cannot reach the local server. Make sure it is running, then try again.',
    'modal.modelConfig.serverUnreachable': 'Cannot reach server: {{error}}. Check base URL and try again.',
    // Provider API key hints
    'modal.modelConfig.keyHint.anthropic': 'Starts with sk-ant-...',
    'modal.modelConfig.keyHint.openai': 'Starts with sk-...',
    'modal.modelConfig.keyHint.gemini': 'From aistudio.google.com',
    'modal.modelConfig.keyHint.openrouter': 'Starts with sk-or-...',
    'modal.modelConfig.keyHint.azure': 'Your cloud deployment API key',
    'modal.modelConfig.keyHint.local': 'Leave empty for local services',
    // Provider Base URL hints
    'modal.modelConfig.urlHint.ollama': 'Default: `http://localhost:11434`',
    'modal.modelConfig.urlHint.lmstudio': 'Default: `http://localhost:1234` (no /v1 needed)',
    'modal.modelConfig.urlHint.azure': 'Your endpoint up to /openai, e.g. https://your-resource.openai.azure.com/openai',
    'modal.modelConfig.urlHint.custom': 'Include /v1 suffix, e.g. http://localhost:1234/v1',

    // =========================================================================
    // Modal — Code Import
    // =========================================================================
    'modal.codeImport.title': 'Import models from code',
    'modal.codeImport.tag': 'Experimental',
    'modal.codeImport.instructions': 'Paste an API code snippet in Python, JavaScript, or `cURL` to automatically extract model configuration.',
    'modal.codeImport.parse': 'Parse snippet',
    'modal.codeImport.apiKey': 'API key',
    'modal.codeImport.apiKeyDesc': "Optional. You can also add it later in each model's settings.",
    'modal.codeImport.apiKeyPlaceholder': 'Sk-...',
    'modal.codeImport.temperature': 'Temperature',
    'modal.codeImport.temperatureDesc': 'Default for agent behavior. Will be auto-adjusted per model if needed.',
    'modal.codeImport.temperatureFixed': 'Fixed at {{temperature}} by the API.',
    'modal.codeImport.testConnection': 'Test connection',
    'modal.codeImport.cancel': 'Cancel',
    'modal.codeImport.import': 'Import',
    'modal.codeImport.importCount': 'Import {{count}} model(s)',
    'modal.codeImport.selectProvider': 'Select a provider',
    'modal.codeImport.noModels': 'No models found',
    'modal.codeImport.testingConnection': 'Testing...',
    'modal.codeImport.testFailed': 'Connection test failed',
    'modal.codeImport.tempHint': 'Hint: this model may require a fixed temperature. Try setting temperature to 1.0 above.',
    'modal.codeImport.selectProviderDropdown': 'Select provider...',
    'modal.codeImport.baseUrl': 'Base URL',
    'modal.codeImport.apiVersion': 'API version',
    'modal.codeImport.modelsFound': 'Models found ({{count}}):',
    'modal.codeImport.duplicate': '(already exists)',
    'modal.codeImport.selectProviderNotice': 'Please select a provider.',
    'modal.codeImport.noModelsNotice': 'No models found.',

    // =========================================================================
    // Modal — System Prompt Preview
    // =========================================================================
    'modal.promptPreview.title': 'System prompt: {{mode}}',
    'modal.promptPreview.copy': 'Copy to clipboard',
    'modal.promptPreview.copied': 'Copied!',

    // =========================================================================
    // Modal — Chat History
    // =========================================================================
    'modal.chatHistory.title': 'Chat history',
    'modal.chatHistory.empty': 'No saved conversations yet. Conversations are saved automatically after each task.',
    'modal.chatHistory.untitled': 'Untitled',
    'modal.chatHistory.open': 'Open',
    'modal.chatHistory.delete': 'Delete',
    'modal.chatHistory.emptyAfterDelete': 'No saved conversations yet.',

    // =========================================================================
    // Modal — Diff Review
    // =========================================================================
    'modal.diffReview.titleCheckpoint': 'Checkpoint diff',
    'modal.diffReview.titleReview': 'Review changes ({{count}} file(s))',
    'modal.diffReview.noChanges': 'No changes',
    'modal.diffReview.unchangedLines': '... {{count}} unchanged lines',
    'modal.diffReview.keep': 'Keep',
    'modal.diffReview.undo': 'Undo',
    'modal.diffReview.edit': 'Edit',
    'modal.diffReview.editLabel': 'Edit section content:',
    'modal.diffReview.cancelEdit': 'Cancel',
    'modal.diffReview.applyEdit': 'Apply edit',
    'modal.diffReview.undoAll': 'Undo all',
    'modal.diffReview.applySelected': 'Apply selected',
    'modal.diffReview.keepAll': 'Keep all',
    'modal.diffReview.close': 'Close',
    'modal.diffReview.restoreCheckpoint': 'Restore to this checkpoint',
    'modal.diffReview.restoring': 'Restoring...',
    'modal.diffReview.restored': 'Restored',
    'modal.diffReview.failed': 'Failed',

    // =========================================================================
    // Modal — Vault Health Repair
    // =========================================================================
    'modal.vaultHealth.title': 'Vault health check',
    'modal.vaultHealth.checkOrphans': 'Orphaned notes (no incoming links)',
    'modal.vaultHealth.checkMissingBacklinks': 'Missing backlinks',
    'modal.vaultHealth.checkBrokenLinks': 'Broken links',
    'modal.vaultHealth.checkWeakClusters': 'Semantically related, unlinked pairs',
    'modal.vaultHealth.checkInconsistentTags': 'Inconsistent tags',
    'modal.vaultHealth.checkCategoryMismatch': 'Incorrect category assignments',
    'modal.vaultHealth.checkGodNodes': 'Overloaded hub notes',
    'modal.vaultHealth.repairableCount': '{{count}} finding(s) auto-repairable (backlinks, categories, orphaned edges).',
    'modal.vaultHealth.repairBtn': 'Repair',
    'modal.vaultHealth.repairing': 'Repairing...',
    'modal.vaultHealth.closeBtn': 'Close',
    'modal.vaultHealth.repairRunning': 'Repair in progress...',
    'modal.vaultHealth.creatingCheckpoint': 'Creating checkpoint...',
    'modal.vaultHealth.progressOrphanedEdges': 'Cleaning up orphaned edges...',
    'modal.vaultHealth.progressBacklinks': 'Inserting missing backlinks...',
    'modal.vaultHealth.progressCategories': 'Correcting category assignments...',
    'modal.vaultHealth.progressInvalidLinks': 'Cleaning up invalid links...',
    'modal.vaultHealth.progressVerify': 'Verifying result...',
    'modal.vaultHealth.repairDone': 'Repair complete',
    'modal.vaultHealth.resultEdges': '{{count}} orphaned edges removed',
    'modal.vaultHealth.resultBacklinks': '{{entities}} entities: {{links}} backlinks, {{bases}} bases created',
    'modal.vaultHealth.resultCategories': '{{count}} notes: category assignment corrected',
    'modal.vaultHealth.resultInvalidLinks': '{{count}} invalid links removed',
    'modal.vaultHealth.noRepairsNeeded': 'No repairs needed. All clean.',
    'modal.vaultHealth.remaining': 'Remaining: {{count}} finding(s) ({{critical}} critical).',
    'modal.vaultHealth.undoBtn': 'Undo',
    'modal.vaultHealth.doneBtn': 'Done',
    'modal.vaultHealth.restoring': 'Restoring checkpoint...',
    'modal.vaultHealth.restored': 'Restored',
    'modal.vaultHealth.restoredCount': '{{count}} file(s) restored.',
    'modal.vaultHealth.errors': '{{count}} error(s): {{errors}}',
    'modal.vaultHealth.restoreFailed': 'Restore failed',

    // =========================================================================
    // Main Plugin
    // =========================================================================
    'plugin.ribbonTooltip': 'Vault Operator',
    'plugin.commandOpen': 'Open agent sidebar',

    // =========================================================================
    // Onboarding (German UI — localized per language)
    // =========================================================================
    'onboarding.welcome.heading': 'Welcome to the agent',
    'onboarding.welcome.modelNeeded': 'Before we start, the agent needs access to a language model.',
    'onboarding.welcome.quickFree': 'This is quick, and free.',
    'onboarding.welcome.freeButton': 'Try for free',
    'onboarding.welcome.apiKeyButton': 'I have an API key',
    'onboarding.free.intro': 'A frontier model is available for free. No credit card required.',
    'onboarding.free.howTo': 'How to get your API key:',
    'onboarding.free.step1': '1. Open the [Google AI Studio API key page](https://aistudio.google.com/app/apikey)',
    'onboarding.free.step2': '2. Sign in with your account and accept the terms of service',
    'onboarding.free.step3': '3. Click "create API key"',
    'onboarding.free.step4': '4. Select an existing project or create a new one',
    'onboarding.free.step5': '5. Copy the key',
    'onboarding.free.noCreditCard': 'No credit card required. [Pricing](https://ai.google.dev/gemini-api/docs/pricing) | [rate limits](https://ai.google.dev/gemini-api/docs/rate-limits)',
    'onboarding.free.pasteKey': 'Paste your key here in the chat.',
    'onboarding.provider.selectPrompt': 'Which provider would you like to use?',
    'onboarding.provider.anthropic': 'Anthropic',
    'onboarding.provider.google': 'Google',
    'onboarding.provider.pasteKey': '{{label}}: paste your API key here in the chat.',
    'onboarding.noModel.heading': 'No model configured. To get started, you need an API key.',
    'onboarding.noModel.freeOffer': 'A frontier model is available for free, no credit card:',
    'onboarding.noModel.step1': '1. Open the [Google AI Studio API key page](https://aistudio.google.com/app/apikey)',
    'onboarding.noModel.step2': '2. Sign in and click "create API key"',
    'onboarding.noModel.step3': '3. Paste the key here in the chat',
    'onboarding.noModel.orSettings': 'Or configure a model in settings.',
    'onboarding.noModel.googleButton': 'Enter API key',
    'onboarding.noModel.settingsButton': 'Open settings',
    'onboarding.noModel.pasteMessage': 'Paste your API key here in the chat.',
    'onboarding.test.testing': 'Testing connection...',
    'onboarding.test.success': 'Connection successful! {{provider}} is configured.',
    'onboarding.test.failed': 'The key could not be verified. Please check the key and try again.',
    'onboarding.trigger': 'Start setup',

    // =========================================================================
    // Provider Setup Guides (in ModelConfigModal)
    // =========================================================================
    'guide.anthropic.heading': 'How to get your API key:',
    'guide.anthropic.step1': 'Go to console.anthropic.com and sign in (or create an account).',
    'guide.anthropic.step2': 'Click "API keys" in the left sidebar.',
    'guide.anthropic.step3': 'Click "create key", give it a name, and copy it.',
    'guide.anthropic.step4': 'Paste the key (starts with sk-ant-...) into the API key field above.',
    'guide.anthropic.tip': 'Recommended model: claude-sonnet-4-6-20250514 (good balance of speed and quality).',
    'guide.openai.heading': 'How to get your API key:',
    'guide.openai.step1': 'Go to platform.openai.com and sign in.',
    'guide.openai.step2': 'Click your name (top right) \u2192 "API keys".',
    'guide.openai.step3': 'Click "create new secret key" and copy it immediately (you can\'t see it again).',
    'guide.openai.step4': 'Paste the key (starts with sk-...) into the API key field above.',
    'guide.openai.tip': 'Recommended model: gpt-4o. Budget alternative: gpt-4o-mini.',
    'guide.gemini.heading': 'How to get your API key:',
    'guide.gemini.step1': 'Go to aistudio.google.com and sign in with your account.',
    'guide.gemini.step2': 'Click "get API key" and create a key for your project.',
    'guide.gemini.step3': 'Copy the key and paste it into the API key field above.',
    'guide.gemini.tip': 'Recommended model: gemini-2.5-flash (fast, free tier available). For complex tasks: gemini-2.5-pro.',
    'guide.ollama.heading': 'How to use a local model server (runs locally, no cost):',
    'guide.ollama.step1': 'Install the server from ollama.ai.',
    'guide.ollama.step2': 'Open a terminal and pull a model, e.g.: ollama pull llama3.2',
    'guide.ollama.step3': 'The server starts automatically; the base URL is `http://localhost:11434` by default.',
    'guide.ollama.step4': 'Enter the model name exactly as pulled (for example llama3.2) into the model ID field above.',
    'guide.ollama.tip': 'Not all models support tool use. Recommended: qwen2.5:7b, llama3.2, mistral.',
    'guide.openrouter.heading': 'How to use this provider (access 100+ models with one key):',
    'guide.openrouter.step1': 'Go to openrouter.ai and create a free account.',
    'guide.openrouter.step2': 'Click your avatar (top right) \u2192 keys \u2192 create key.',
    'guide.openrouter.step3': 'Copy the key (starts with sk-or-...) and paste it into the API key field above.',
    'guide.openrouter.step4': 'Enter the model ID. Use the exact OpenRouter model name, e.g. anthropic/claude-3.5-sonnet or openai/gpt-4o.',
    'guide.openrouter.step5': 'Browse all available models at openrouter.ai/models.',
    'guide.openrouter.tip': 'The base URL is pre-configured. Many models have a free tier (look for ":free" in the model name).',
    'guide.azure.heading': 'How to use cloud deployments (enterprise):',
    'guide.azure.step1': 'In the cloud portal, open your deployment resource.',
    'guide.azure.step2': 'Under "resource management" \u2192 "keys and endpoint", copy the key and the endpoint URL.',
    'guide.azure.step3': 'In base URL, enter: {endpoint}/openai (e.g. https://my-resource.openai.azure.com/openai).',
    'guide.azure.step4': 'In model ID, enter the exact deployment name from the cloud console (for example `GPT-4o`).',
    'guide.azure.step5': 'Set the API version to match what your deployment supports (default: 2024-10-21).',
    'guide.azure.tip': 'For enterprise gateways: use the gateway base URL (up to /openai), deployment name as model ID, and your gateway API key.',
    'guide.lmstudio.heading': 'How to use a local model server (no cost, no API key):',
    'guide.lmstudio.step1': 'Download the application from lmstudio.ai and install a model of your choice.',
    'guide.lmstudio.step2': 'In the application, go to the developer tab (left sidebar) and start the local server.',
    'guide.lmstudio.step3': 'The default base URL is `http://localhost:1234`, no API key needed.',
    'guide.lmstudio.step4': 'Click "browse available models" below to pick a loaded model.',
    'guide.lmstudio.tip': 'Make sure to load a model in the application before starting the server, otherwise no models will appear.',
    'guide.custom.heading': 'Custom endpoint (any compatible API):',
    'guide.custom.tip': 'Any compatible endpoint. Enter the base URL with /v1 suffix and your API key.',

    // GitHub Copilot
    'guide.copilot.heading': 'GitHub copilot (requires active subscription):',
    'guide.copilot.step1': 'You need an active GitHub copilot subscription (individual, business, or enterprise).',
    'guide.copilot.step2': 'Click "Sign in with GitHub" below. A code will appear, enter it at github.com/login/device.',
    'guide.copilot.step3': 'After authorization, pick a model from the quick pick dropdown or use the fetch button.',
    'guide.copilot.disclaimer': 'This uses an unofficial API. Models and availability may change without notice.',
    'copilot.auth': 'GitHub account',
    'copilot.authDesc': 'Sign in with your GitHub account to use copilot models.',
    'copilot.signIn': 'Sign in with GitHub',
    'copilot.signOut': 'Sign out',
    'copilot.authenticated': 'Connected',
    'copilot.notConnected': 'Not connected',
    'copilot.deviceCodeNotice': 'Enter this code on GitHub:',
    'copilot.polling': 'Waiting for authorization...',
    'copilot.authSuccess': 'Successfully connected to GitHub copilot.',
    'copilot.authFailed': 'Authentication failed: {error}',
    'copilot.signedOut': 'Signed out from GitHub copilot.',

    // ChatGPT OAuth (EPIC-021). The bot's sentence-case rule does not include
    // "ChatGPT" or "OS" in its default brand/acronym list, so the strings here
    // avoid those tokens. The i18n keys keep the chatgpt prefix for context.
    'chatgpt.auth': 'Codex account',
    'chatgpt.authDesc': 'Sign in with your subscription. This uses unofficial codex endpoints; the schema can change without notice.',
    'chatgpt.signIn': 'Sign in',
    'chatgpt.signOut': 'Disconnect',
    'chatgpt.notConnected': 'Not connected',
    'chatgpt.unsupportedPlatform': 'Desktop only (system keychain required)',
    'chatgpt.polling': 'Waiting for browser...',
    'chatgpt.openedBrowser': 'Browser opened. Complete sign-in there, then return to Obsidian.',
    'chatgpt.authSuccess': 'Successfully connected.',
    'chatgpt.authFailed': 'Sign-in failed: {error}',
    'chatgpt.signedOut': 'Disconnected.',

    // Kilo gateway
    'kilo.auth': 'Kilo account',
    'kilo.authDesc': 'Sign in with your account to use gateway models.',
    'kilo.signIn': 'Sign in',
    'kilo.manualToken': 'Use API token',
    'kilo.manualTokenPlaceholder': 'Paste your API token',
    'kilo.manualTokenConfirm': 'Connect',
    'kilo.manualTokenValidating': 'Validating...',
    'kilo.manualTokenInvalid': 'Invalid token: {error}',
    'kilo.disconnect': 'Disconnect',
    'kilo.disconnected': 'Disconnected from gateway.',
    'kilo.authenticated': 'Connected as {account}',
    'kilo.authenticatedNoLabel': 'Connected',
    'kilo.notConnected': 'Not connected',
    'kilo.deviceFlow.openBrowser': 'Open the link below and enter the code:',
    'kilo.deviceFlow.code': 'Your code: {code}',
    'kilo.deviceFlow.waiting': 'Waiting for authorization...',
    'kilo.deviceFlow.success': 'Successfully connected to the gateway.',
    'kilo.deviceFlow.failed': 'Authorization failed: {error}',

    // EPIC-26 / FEAT-26-03 -- Provider-only Settings UI
    'settings.providers.title': 'Providers',
    'settings.providers.intro': 'Configure one or more LLM providers; the plugin auto-classifies their models into three tiers, and the active provider drives the chat.',
    'settings.providers.empty': 'No providers configured yet. Add one below.',
    'settings.providers.activeLabel': 'Active provider',
    'settings.providers.activeDesc': 'This provider drives the chat; switch per situation, for example privacy-sensitive notes on a local model.',
    'settings.providers.activeNone': '— none —',
    'settings.providers.activeBadge': 'Active',
    'settings.providers.notConfigured': 'Not configured',
    'settings.providers.rowSummary': '{{count}} models · {{flagship}} / {{mid}} / {{fast}}',
    'settings.providers.rowSummaryEmpty': 'Not refreshed yet · click the cog to configure',
    'settings.providers.rowSummaryDisabled': 'Disabled · enable to use',
    'settings.providers.configure': 'Configure',
    'settings.providers.headerProvider': 'Provider',
    'settings.providers.headerKey': 'Key',
    'settings.providers.headerEnable': 'Enable',
    'settings.providers.headerDefault': 'Active',
    'settings.providers.remove': 'Remove',
    'settings.providers.enabled': 'Enabled',
    'settings.providers.apiKey': 'API key',
    'settings.providers.apiKeyDesc': 'Credential sent on every request, stored encrypted on disk.',
    'settings.providers.baseUrl': 'Base URL',
    'settings.providers.baseUrlDesc': 'Endpoint URL. Leave empty to use the provider default; override to point at a proxy, self-hosted gateway, or alternate region.',
    'settings.providers.baseUrlSdkDefault': 'SDK default',
    'settings.providers.apiVersion': 'API version',
    'settings.providers.apiVersionDesc': 'Api-version string for the enterprise gateway, e.g. 2024-10-21.',
    'settings.providers.bedrockRegion': 'AWS region',
    'settings.providers.bedrockRegionDesc': 'AWS region identifier (for example eu-central-1 or us-east-1).',
    'settings.providers.bedrockAuthMode': 'Auth mode',
    'settings.providers.bedrockAuthModeDesc': 'API key (single bearer token) or access key + secret (classic IAM).',
    'settings.providers.bedrockApiKey': 'Bedrock API key',
    'settings.providers.bedrockAccessKey': 'AWS access key ID',
    'settings.providers.bedrockSecretKey': 'AWS secret access key',
    'settings.providers.oauthSignIn': 'Sign in',
    'settings.providers.oauthSignOut': 'Sign out',
    'settings.providers.oauthReauth': 'Re-authenticate',
    'settings.providers.oauthStatus': 'Sign-in status',
    'settings.providers.oauthAuthed': 'Signed in',
    'settings.providers.oauthNotAuthed': 'Not signed in',
    'settings.providers.oauthSignInRedirect': 'Sign-in still lives in the legacy models tab; opening it now.',
    'settings.providers.oauthRequestingCode': 'Requesting code…',
    'settings.providers.oauthPolling': 'Waiting for browser…',
    'settings.providers.oauthDeviceCode': 'GitHub Copilot device code: {{code}}\nOpen {{url}} and enter the code.',
    'settings.providers.oauthSignedIn': 'Signed in successfully.',
    'settings.providers.oauthSignedOut': 'Signed out.',
    'settings.providers.oauthSignInFailed': 'Sign-in failed: {{msg}}',
    'settings.providers.oauthSignOutFailed': 'Sign-out failed: {{msg}}',
    'settings.providers.chatgptUnsupported': 'ChatGPT sign-in needs desktop Obsidian with an OS keychain.',
    'settings.providers.copilotClientId': 'Custom GitHub client ID',
    'settings.providers.copilotClientIdDesc': 'Optional. Override the default client with your own GitHub app.',
    'settings.providers.copilotClientIdPlaceholder': 'Iv1.b507a08c87ecfe98 (default)',
    'settings.providers.discovery': 'Discovered models',
    'settings.providers.discoveryDesc': '{{count}} models · last refresh: {{stamp}}',
    'settings.providers.discoveryEmpty': 'No models discovered yet. Add your credentials, then refresh.',
    'settings.providers.refresh': 'Refresh',
    'settings.providers.refreshing': 'Refreshing…',
    'settings.providers.refreshDone': 'Models refreshed.',
    'settings.providers.refreshFailed': 'Refresh failed: {{msg}}',
    'settings.providers.refreshUnavailable': 'Discovery service is not ready yet. Try again in a moment.',
    'settings.providers.advisorDisabled': 'Advisor pattern disabled for this provider — no flagship-tier model.',
    'settings.providers.removeProvider': 'Remove provider',
    'settings.providers.removeDesc': 'Deletes credentials and tier mapping for this provider. Original models stay in legacy_active_models_backup.',
    'settings.providers.removeConfirm': 'Remove provider "{{name}}"? This deletes its credentials and tier mapping.',
    'settings.providers.addProviderLabel': 'Add provider',
    'settings.providers.addProviderDesc': 'Pick the provider type to add; multiple instances of the same type are allowed (for example two accounts of the same provider).',
    'settings.providers.addProvider': 'Add provider',
    'settings.providers.choosePicker': '— choose a provider type —',
    'settings.providers.duplicateSuffix': 'Second instance',
    'settings.providers.tier.fast': 'Budget tier',
    'settings.providers.tier.mid': 'Main tier',
    'settings.providers.tier.flagship': 'Frontier tier',
    'settings.providers.tier.fastDesc': 'Cheapest, lowest-latency model; used for context condensing, titling, and the research subagent.',
    'settings.providers.tier.midDesc': 'Default main-loop model in auto mode; balanced for cost and capability.',
    'settings.providers.tier.flagshipDesc': 'Most capable model; used by the consult-flagship escalation for one-shot synthesis steps. Empty disables the advisor pattern.',
    'settings.providers.tier.autoLabel': 'Auto → {{name}}',
    'settings.providers.tier.autoEmpty': '— no auto match —',
    'settings.providers.tier.autoDetected': 'Auto-detected',
    'settings.providers.tier.manuallySet': 'Manually set',
    'settings.providers.tier.empty': 'Not assigned',
    'settings.providers.tier.differentTier': 'Different tier',
    'settings.providers.modal.title': 'Configure {{name}}',
    'settings.providers.modal.titleNew': 'Add provider',
    'settings.providers.modal.section.identity': 'Identity',
    'settings.providers.modal.section.auth': 'Authentication',
    'settings.providers.modal.section.discovery': 'Discovery',
    'settings.providers.modal.section.tiers': 'Tier mapping',
    'settings.providers.modal.section.danger': 'Danger zone',
    'settings.providers.modal.close': 'Close',
    'settings.providers.modal.cancel': 'Cancel',
    'settings.providers.modal.save': 'Save',
    'settings.providers.modal.addProvider': 'Add provider',
    'settings.providers.modal.addedNotice': '{{name}} added. Refresh the model list to populate tier slots.',
    'settings.providers.modal.notFound': 'Provider not found. The list may have changed; close and re-open.',
    'settings.providers.modal.providerType': 'Provider',
    'settings.providers.modal.displayName': 'Display name',
    'settings.providers.modal.displayNameDesc': 'Friendly label shown in the providers list. Defaults to the provider type.',
    'settings.providers.modal.discoveryAfterSave': 'Save the provider first, then refresh to discover its models.',
    'settings.providers.modal.tiersAfterRefresh': 'Refresh to discover models and auto-populate the tier slots.',
    'settings.providers.modal.refreshDirtyConfirm': 'You have unsaved credential changes; refresh uses the saved credentials, continue anyway?',
    'settings.providers.modal.autoFetching': 'Discovering models for {{name}}…',
    'settings.providers.modal.autoFetched': 'Discovered {{count}} models for {{name}}.',
    'settings.providers.modal.autoFetchFailed': 'Auto-discovery failed: {{msg}}. Use the Refresh button to retry.',
    'settings.providers.modal.tierInfoTitle': 'Tier mapping',
    'settings.providers.modal.tierInfoBody': 'Each provider has three tier slots; the budget slot drives cheap helper calls, the main slot drives the default chat loop, and the frontier slot drives the advisor escalation, with auto-discovery filling them by model pattern and a per-slot override available for a specific model.',
    'settings.providers.modal.testConnection': 'Test connection',
    'settings.providers.modal.testConnectionDesc': 'Probes the provider endpoint with the current credentials to verify they work.',
    'settings.providers.modal.testing': 'Testing…',
    'settings.providers.modal.testOk': 'Connection OK. {{msg}}',
    'settings.providers.modal.testFail': 'Connection failed: {{msg}}',
    'settings.providers.modal.testNoCreds': 'Enter credentials first, then test.',

    // EPIC-26 / FEAT-26-05 -- chat-header model dropdown
    'ui.sidebar.modelAuto': 'Auto',
    'ui.sidebar.modelAutoTitle': 'Advisor pattern: main loop on the mid tier, on-demand flagship escalation.',
    'ui.sidebar.modelOverrideTitle': 'Override: this turn runs on {{label}}. consult_flagship is disabled.',
    'ui.sidebar.modelAdvisorDisabled': 'Advisor pattern disabled',
    'ui.sidebar.modelPickerTitle': '{{provider}} models',
    'ui.sidebar.modelPickerSearch': 'Filter models…',
    'ui.sidebar.modelPickerNoModels': 'No discovered models yet; open settings, then providers, then refresh.',
};
