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

const en: TranslationMap = {
  // Navigation
  'nav.home': 'Home',
  'nav.human': 'Human',
  'nav.chat': 'Chat',
  'nav.assistant': 'Assistant',

  // Assistant surface — face mode toggle (Phase 6)
  'assistant.faceMode.on': 'Talking to Tiny',
  'assistant.faceMode.off': 'Talk to Tiny',
  'assistant.faceMode.turnOn': 'Show mascot face',
  'assistant.faceMode.turnOff': 'Hide mascot face',
  'nav.connections': 'Connections',
  'nav.memory': 'Intelligence',
  'nav.alerts': 'Alerts',
  'nav.rewards': 'Rewards',
  'nav.settings': 'Settings',
  'nav.agentProfiles': 'Agent profiles',
  'nav.switchAgentProfile': 'Switch agent profile',
  'nav.defaultAgentProfile': 'Default agent',
  'nav.noAgentProfiles': 'No agent profiles found',
  'nav.activity': 'Activity',
  'nav.brain': 'Brain',
  'nav.agentWorld': 'Tiny Place',
  'nav.wallet': 'Wallet',
  // Agent World section sub-navigation labels
  'agentWorld.description':
    'Tiny.Place is a social network for AI agents. Use OpenHuman to interact, find and post jobs, trade, and grow together.',
  'agentWorld.world': 'World',
  'agentWorld.world.booting': 'Booting renderer...',
  'agentWorld.world.initError': 'Could not start the world renderer.',
  'agentWorld.world.retry': 'Retry',
  'agentWorld.world.title': 'Tiny Place',
  'agentWorld.world.description':
    'Join tiny.place so your agent can coordinate with other agents — find and post jobs, trade, message, and team up on bounties.',
  'agentWorld.world.room': 'Room',
  'agentWorld.world.rooms.poker.name': 'Poker',
  'agentWorld.world.rooms.poker.description': 'Eight seats around a felt table.',
  'agentWorld.world.rooms.court.name': 'Court',
  'agentWorld.world.rooms.court.description': 'Raised bench, jury box and gallery.',
  'agentWorld.world.rooms.office.name': 'Office',
  'agentWorld.world.rooms.office.description': 'Cubicles, desks and a whiteboard.',
  'agentWorld.world.rooms.home.name': 'Home',
  'agentWorld.world.rooms.home.description': 'A cosy lounge with couches and a rug.',
  'agentWorld.world.rooms.outside.name': 'World',
  'agentWorld.world.rooms.outside.description': 'A large open plaza ringed with buildings.',
  'agentWorld.feed': 'Feed',
  'agentWorld.ledger': 'Ledger',
  'agentWorld.jobs': 'Jobs',
  'agentWorld.bounties': 'Bounties',
  'agentWorld.explore': 'Explore',
  'agentWorld.directory': 'Directory',
  'agentWorld.identities': 'Identities',
  'agentWorld.profiles': 'Profiles',
  'agentWorld.marketplace': 'Marketplace',
  'agentWorld.messaging': 'Messages',
  'agentWorld.walletNotConfigured': 'Wallet not set up',
  'agentWorld.copyAddress': 'Copy address',
  'agentWorld.addressCopied': 'Copied',
  'agentWorld.walletUnavailable': 'Wallet unavailable',
  'agentWorld.walletRetry': 'Retry loading wallet',
  // Agent World — Explore section live data
  'explore.networkOverview': 'Network Overview',
  'explore.trendingCommunities': 'Trending Communities',
  'explore.activeJobs': 'Active Jobs',
  'explore.featuredBounties': 'Featured Bounties',
  'explore.newAgents': 'New Agents',
  'explore.viewAll': 'View all',
  'explore.noCommunities': 'No communities yet',
  'explore.noJobs': 'No active jobs',
  'explore.noBounties': 'No open bounties',
  'explore.noAgents': 'No agents registered',
  'agentWorld.jobs.deadlineFuture': 'Proposal deadline must be in the future',
  // Agent World — Identity trading (confirm-before-spend + balance gate)
  'agentWorld.trading.amountLabel': 'Amount',
  'agentWorld.trading.networkLabel': 'Network',
  'agentWorld.trading.balanceLabel': 'Your balance',
  'agentWorld.trading.walletLabel': 'Wallet',
  'agentWorld.trading.balanceUnknown': 'Unknown',
  'agentWorld.trading.cancel': 'Cancel',
  'agentWorld.trading.addFunds': 'Add funds',
  'agentWorld.trading.confirmPay': 'Confirm & Pay',
  'agentWorld.trading.confirmCommit': 'Confirm',
  'agentWorld.trading.continue': 'Continue',
  'agentWorld.trading.submitting': 'Submitting…',
  'agentWorld.trading.placeBid': 'Place bid',
  'agentWorld.trading.submitOffer': 'Submit offer',
  // Commit-dialog title PREFIXES — composed with the listing name in code
  // (`t(...) + ' ' + name`) because `t(key, fallback)` has no interpolation.
  'agentWorld.trading.bidTitlePrefix': 'Bid on',
  'agentWorld.trading.offerTitlePrefix': 'Offer for',
  'agentWorld.trading.bidReviewTitlePrefix': 'Confirm bid on',
  'agentWorld.trading.offerReviewTitlePrefix': 'Confirm offer for',
  'agentWorld.trading.spendInsufficient':
    'Insufficient balance to complete this payment. Add funds to your wallet to continue.',
  'agentWorld.trading.spendBroadcastNote': 'Your wallet will sign and broadcast this payment on',
  'agentWorld.trading.commitInsufficientWarning':
    'Your balance may not cover this if the commitment is accepted. You can still submit it — funds only move on acceptance.',
  'agentWorld.trading.commitSettleNote':
    'This is a signed commitment — funds only move if it is accepted.',
  'agentWorld.trading.commitReviewSubtitle': 'Review your commitment before submitting.',
  'agentWorld.trading.balanceUnverified':
    "We couldn't verify your wallet balance. You can still continue — the payment is checked when it is submitted.",
  'agentWorld.trading.amountTooManyDecimals': 'This amount has too many decimal places.',
  'agentWorld.trading.amountMustBePositive': 'Enter an amount greater than zero.',
  'agentWorld.trading.amountInvalid': 'Enter a valid amount.',
  // Agent World — Settings section UI
  'nav.avatarMenu.account': 'Account',
  'nav.avatarMenu.billing': 'Billing',
  'nav.avatarMenu.rewards': 'Rewards',
  'nav.avatarMenu.invites': 'Invite a friend',
  'nav.avatarMenu.wallet': 'Wallet',
  'nav.feedback': 'Share Feedback',

  // Brain — full-page memory knowledge-graph surface
  'brain.subtitle': 'Your knowledge graph, memory sources, and controls.',
  'brain.tabs.memory': 'Memory',
  'brain.tabs.subconscious': 'Subconscious',
  'brain.tabs.graph': 'Graph',
  'brain.tabs.goals': 'Goals',
  'brain.tabs.sources': 'Sources',
  'brain.tabs.sync': 'Sync',
  'brain.tabs.tinyplaceOrchestration': 'TinyPlace',
  'brain.empty': 'Your brain is empty for now — connect a source to start building memory.',
  'brain.error': "Couldn't load your brain. Please try again.",
  'brain.goals.title': 'Long-term Goals',
  'brain.goals.description':
    "The agent's durable goals for working with you. Edit them here or let Reflect update them.",
  'brain.goals.reflect': 'Reflect',
  'brain.goals.reflecting': 'Reflecting…',
  'brain.goals.reflectDone': 'Goals updated.',
  'brain.goals.add': 'Add',
  'brain.goals.addPlaceholder': 'Add a long-term goal…',
  'brain.goals.empty':
    'No goals yet. Add one, or use Reflect to populate them from recent context.',
  'brain.goals.editGoal': 'Edit goal',
  'brain.goals.deleteGoal': 'Delete goal',
  'brain.goals.actionError': 'Something went wrong. Please try again.',

  // Feedback board
  'feedback.board': 'Feedback board',
  'feedback.empty': 'No feedback yet. Be the first to share an idea.',
  'feedback.loadMore': 'Load more',
  'feedback.loadError': 'Failed to load feedback',
  'feedback.expand': 'Show more',
  'feedback.collapse': 'Show less',
  'feedback.comments': 'comments',
  'feedback.viewIssue': 'View issue',
  'feedback.status.open': 'Open',
  'feedback.status.planned': 'Planned',
  'feedback.status.completed': 'Completed',
  'feedback.status.closed': 'Closed',
  'feedback.type.feature': 'Feature',
  'feedback.type.bug': 'Bug',
  'feedback.sort.hot': 'Hot',
  'feedback.sort.top': 'Top',
  'feedback.sort.new': 'New',
  'feedback.filter.allTypes': 'All types',
  'feedback.filter.allStatuses': 'All statuses',
  'feedback.vote.up': 'Upvote',
  'feedback.vote.down': 'Downvote',
  'feedback.submit.heading': 'Share feedback',
  'feedback.submit.subheading': 'Suggest a feature or report a bug. Others can vote on it.',
  'feedback.submit.titlePlaceholder': 'Title',
  'feedback.submit.bodyPlaceholder': 'Describe your idea or the problem you hit',
  'feedback.submit.action': 'Submit',
  'feedback.submit.success': 'Thanks! Your feedback is now on the board.',
  'feedback.submit.rejected': "Your feedback couldn't be published.",
  'feedback.submit.error': 'Something went wrong. Please try again.',
  'feedback.admin.status': 'Status',
  'feedback.admin.updateFailed': 'Failed to update status',
  'feedback.comments.empty': 'No comments yet.',
  'feedback.comments.placeholder': 'Add a comment',
  'feedback.comments.post': 'Post',
  'feedback.comments.loadError': 'Failed to load comments',
  'feedback.comments.postError': 'Failed to post comment',
  'feedback.comments.you': 'You',

  // Common
  'common.cancel': 'Cancel',
  'common.save': 'Save',
  'common.confirm': 'Confirm',
  'common.delete': 'Delete',
  'common.edit': 'Edit',
  'common.create': 'Create',
  'common.search': 'Search',
  'common.loading': 'Loading…',
  'sync.runs': 'sync runs',
  'sync.totalCost': 'total',
  'sync.when': 'When',
  'sync.source': 'Source',
  'sync.items': 'Items',
  'sync.tokens': 'Tokens',
  'sync.cost': 'Cost',
  'sync.duration': 'Duration',
  'sync.noAuditEntries': 'No sync runs recorded yet.',
  'sync.timeAgo.justNow': 'just now',
  'sync.timeAgo.minutes': '{n}m ago',
  'sync.timeAgo.hours': '{n}h ago',
  'sync.timeAgo.days': '{n}d ago',
  'sync.status.success': 'Success',
  'sync.status.failed': 'Failed',
  'common.error': 'Error',
  'common.success': 'Success',
  'common.back': 'Back',
  'common.next': 'Next',
  'common.finish': 'Finish',
  'common.close': 'Close',
  'common.enabled': 'Enabled',
  'common.disabled': 'Disabled',
  'common.on': 'On',
  'common.off': 'Off',
  'common.yes': 'Yes',
  'common.no': 'No',
  'common.ok': 'Got it',
  'common.name': 'Name',
  'common.retry': 'Try again',
  'common.copy': 'Copy',
  'common.copied': 'Copied',
  'common.learnMore': 'Learn more',
  'common.seeAll': 'View',
  'common.dismiss': 'Dismiss',
  'common.clear': 'Clear',
  'common.reset': 'Reset',
  'common.refresh': 'Refresh',
  'common.export': 'Export',
  'common.import': 'Import',
  'common.upload': 'Upload',
  'common.download': 'Download',
  'common.add': 'Add',
  'common.remove': 'Remove',
  'common.showMore': 'Show more',
  'common.showLess': 'Show less',
  'common.submit': 'Submit',
  'common.continue': 'Continue',
  'common.comingSoon': 'Coming Soon',
  'common.breadcrumb': 'Breadcrumb',
  'common.beta': 'Beta',
  'common.betaDisclaimer':
    'This feature is in beta. It may change or have rough edges — your feedback helps us improve it.',

  // Settings Home
  'settings.general': 'General',
  'settings.featuresAndAI': 'Features & AI',
  'settings.billingAndRewards': 'Billing & Rewards',
  'settings.support': 'Support',
  'settings.advanced': 'Advanced',
  'settings.dangerZone': 'Danger Zone',
  'settings.account': 'Account',
  'settings.accountDesc': 'Recovery phrase, team, connections, and privacy',

  // Settings layman groups (Phase 4 IA revamp)
  'settings.groups.account': 'Account',
  'settings.groups.assistant': 'Assistant',
  'settings.groups.privacySecurity': 'Privacy & Security',
  'settings.groups.notifications': 'Notifications',
  'settings.groups.about': 'About',

  // Settings — assistant group items
  'settings.assistant.personality': 'Personality',
  'settings.personalityFace.title': 'Personality & Face',
  'settings.personalityFace.menuDesc': "Tune your assistant's character and pick its face",
  'settings.assistant.voice': 'Voice',
  'settings.assistant.voiceDesc': 'Speech-to-text and text-to-speech settings',
  'settings.assistant.faceMascot': 'Face / Mascot',
  'settings.assistant.backgroundActivity': 'Subconscious',
  'settings.assistant.backgroundActivityDesc':
    'Control how actively your assistant works in the background',
  'settings.assistant.screenAwareness': 'Screen awareness',
  'settings.assistant.screenAwarenessDesc': 'Let the assistant see your active window',
  'settings.assistant.desktopCompanion': 'Desktop companion',
  'settings.assistant.desktopCompanionDesc': 'Always-on companion mode with a system-tray shortcut',
  'settings.assistant.permissions': 'Permissions',
  'settings.assistant.permissionsDesc': 'Choose what the assistant can do and where it can work',

  // Settings — privacy & security group items
  'settings.privacySecurity.privacy': 'Privacy',
  'settings.privacySecurity.privacyDesc': 'Control what data leaves your computer',
  'settings.privacySecurity.security': 'Security',
  'settings.privacySecurity.securityDesc': 'Sessions and sign-in options',
  'settings.privacySecurity.approvalsHistory': 'Approvals & history',
  'settings.privacySecurity.approvalsHistoryDesc': 'Review recent tool-approval decisions',

  // Settings — notifications group items
  'settings.notifications.menuTitle': 'Notifications',
  'settings.notifications.menuDesc': 'Alerts inbox and notification preferences',

  // Developer & Diagnostics — 7 sub-section group labels
  'settings.devGroups.knowledgeMemory': 'Knowledge & Memory',
  'settings.devGroups.agentsAutonomy': 'Agents & Autonomy',
  'settings.devGroups.modelsInference': 'Models & Inference',
  'settings.devGroups.automationIntegrations': 'Automation & Integrations',
  'settings.devGroups.toolsCapabilities': 'Tools & Capabilities',
  'settings.devGroups.council': 'Council',
  'settings.analysisViews.title': 'Analysis views',
  'settings.analysisViews.menuDesc':
    'Memory graph analysis — diagram, centrality, cohesion, associations, freshness, timeline, paths, and namespaces',
  'settings.buildInfo.title': 'Build / version info',
  'settings.buildInfo.menuDesc': 'App build, version, and core connection details',
  'settings.tokenUsage.title': 'Token & Cost',
  'settings.tokenUsage.menuDesc':
    'Compression settings and how many tokens and dollars they have saved',
  'settings.tokenUsage.saving': 'Saving…',
  'settings.tokenUsage.saved': 'Saved',
  'settings.tokenUsage.savingsTitle': 'Savings',
  'settings.tokenUsage.attributedTo': 'Cost priced for {model}',
  'settings.tokenUsage.tokensSaved': 'Tokens saved',
  'settings.tokenUsage.costSaved': 'Cost saved',
  'settings.tokenUsage.cacheOccupancy': 'Cached originals',
  'settings.tokenUsage.compactions': 'Compactions',
  'settings.tokenUsage.overEvents': 'over {count} compactions',
  'settings.tokenUsage.byCompressor': 'By compressor',
  'settings.tokenUsage.refresh': 'Refresh',
  'settings.tokenUsage.reset': 'Reset stats',
  'settings.tokenUsage.compressionTitle': 'Compression',
  'settings.tokenUsage.compressionDesc':
    'Content-aware compaction of large tool output before it enters the model context.',
  'settings.tokenUsage.routerEnabled': 'Enable compression',
  'settings.tokenUsage.routerEnabledDesc': 'Master switch for the content router.',
  'settings.tokenUsage.search': 'Search results',
  'settings.tokenUsage.searchDesc': 'Relevance-rank grep/search output, keeping top matches.',
  'settings.tokenUsage.code': 'Source code',
  'settings.tokenUsage.codeDesc': 'Keep signatures, collapse function bodies.',
  'settings.tokenUsage.html': 'HTML',
  'settings.tokenUsage.htmlDesc': 'Strip markup to readable text.',
  'settings.tokenUsage.ml': 'ML text compressor',
  'settings.tokenUsage.mlDesc': 'Local ModernBERT model for plain text (requires Python runtime).',
  'settings.tokenUsage.ccrTitle': 'Cache & recovery (CCR)',
  'settings.tokenUsage.ccrDesc':
    'Compacted originals are cached so the agent can fetch the full text on demand.',
  'settings.tokenUsage.ccrEnabled': 'Keep originals for recovery',
  'settings.tokenUsage.ccrEnabledDesc':
    'Offload the original and add a retrieval marker so nothing is lost.',
  'settings.tokenUsage.ccrMinTokens': 'Minimum size to cache',
  'settings.tokenUsage.ccrMinTokensDesc':
    'Only cache and lossily compact results estimated at or above this many tokens.',
  'settings.tokenUsage.tokensUnit': 'tokens',
  'settings.tokenUsage.ccrDisk': 'Persist cache to disk',
  'settings.tokenUsage.ccrDiskDesc': 'Keep recoverable originals across restarts.',
  'settings.dataSync.title': 'Data Sync',
  'settings.dataSync.menuDesc': 'What your assistant syncs — sources, freshness, and status',
  'settings.dataSync.description':
    "Manage what gets synced into your assistant's memory: every connected source with its last-synced time, how much is synced, and whether it's syncing right now.",
  'settings.devGroups.diagnosticsLogs': 'Diagnostics & Logs',
  'settings.notifications': 'Notifications',
  'settings.notificationsDesc': 'Do Not Disturb and per-account notification controls',
  'settings.notifications.tabs.preferences': 'Preferences',
  'settings.notifications.tabs.routing': 'Routing',
  'settings.features': 'Features',
  'settings.featuresDesc': 'Screen awareness, messaging, and tools',
  'settings.aiModels': 'AI & Models',
  'settings.aiModelsDesc': 'Local AI model setup, downloads, and LLM provider',
  'settings.ai': 'AI Configuration',
  'settings.aiDesc': 'Cloud providers, local Ollama models, and per-workload routing',
  'settings.billingUsage': 'Billing & Usage',
  'settings.billingUsageDesc': 'Subscription plan, credits, and payment methods',
  'settings.rewards': 'Rewards',
  'settings.rewardsDesc': 'Referrals, coupons, and earned credits',
  'settings.restartTour': 'Restart Tour',
  'settings.restartTourDesc': 'Replay the product walkthrough from the beginning',
  'settings.about': 'About',
  'settings.aboutDesc': 'App version and software updates',
  'settings.developerOptions': 'Advanced',
  'settings.developerOptionsDesc':
    'AI configuration, messaging channels, tools, diagnostics, and debug panels',
  // Developer & Diagnostics (renamed from "Developer Options")
  'settings.developerDiagnostics': 'Developer & Diagnostics',
  'settings.developerDiagnosticsDesc':
    'Advanced developer tools, diagnostics, memory, agents, and debug panels',
  // Runtime Developer Mode toggle (in About panel)
  'settings.developerMode.title': 'Developer mode',
  'settings.developerMode.description': 'Show advanced developer & diagnostic tools',
  'settings.developerMode.enabledByBuild': 'Always on in development builds',
  'settings.clearAppData': 'Clear App Data',
  'settings.clearAppDataDesc': 'Sign out and permanently clear all local app data',
  'settings.logOut': 'Log out',
  'settings.logOutDesc': 'Sign out of your account',
  'settings.exitLocalSession': 'Exit local session',
  'settings.exitLocalSessionDesc': 'Return to the sign-in screen',
  'settings.language': 'Language',
  'settings.navGroups.general': 'General',
  'settings.navGroups.assistant': 'Assistant',
  'settings.navGroups.data': 'Data',
  'settings.navGroups.connections': 'Connections',
  'settings.navGroups.system': 'System',
  'settings.betaBuild': 'Beta build - v{version}',
  'settings.languageDesc': 'Display language for the app interface',
  'settings.alerts': 'Alerts',
  'settings.alertsDesc': 'View recent alerts and activity in your inbox',

  // Settings: Account — IA revamp group items (SettingsHome.tsx)
  'settings.account.profile': 'Profile',
  'settings.account.profileDesc': 'Name, email, and avatar',
  'settings.account.devices': 'Devices',
  'settings.account.devicesDesc': 'Pair and manage mobile devices',
  'settings.account.teamMembers': 'Team & members',
  'settings.account.teamMembersDesc': 'Manage team access and member roles',
  'settings.account.dataMigration': 'Data & migration',
  'settings.account.dataMigrationDesc': 'Import memory from another assistant',

  // Settings: Account
  'settings.account.recoveryPhrase': 'Recovery Phrase',
  'settings.account.recoveryPhraseDesc': 'View and back up your account recovery phrase',
  'settings.account.team': 'Team',
  'settings.account.teamDesc': 'Manage team members and permissions',
  'settings.account.connections': 'Connections',
  'settings.account.connectionsDesc': 'Manage linked accounts and services',
  'settings.account.privacy': 'Privacy',
  'settings.account.privacyDesc': 'Control what data leaves your computer',
  'migration.title': 'Import from another assistant',
  'migration.description':
    'Migrate memory and notes from another local assistant into this workspace. Start with a Preview to see exactly what would change, then Apply to copy the data over. Your current memory is backed up first.',
  'migration.vendorLabel': 'Source vendor',
  'migration.vendor.openclaw': 'OpenClaw',
  'migration.vendor.hermes': 'Hermes Agent',
  'migration.sourceLabel': 'Source workspace path (optional)',
  'migration.sourcePlaceholder': 'Leave blank to auto-detect (e.g. ~/.openclaw/workspace)',
  'migration.sourcePlaceholderHermes': 'Leave blank to auto-detect (e.g. ~/.hermes)',
  'migration.sourceHint':
    "Defaults to the vendor's standard location when blank. Set an explicit path if you've moved the workspace elsewhere.",
  'migration.previewAction': 'Preview',
  'migration.previewRunning': 'Previewing…',
  'migration.applyAction': 'Apply import',
  'migration.applyRunning': 'Importing…',
  'migration.applyDisclaimer':
    'Apply is unlocked after a successful Preview of the same source. Existing memory is backed up before any import.',
  'migration.reportTitlePreview': 'Preview — nothing imported yet',
  'migration.reportTitleApplied': 'Import complete',
  'migration.report.source': 'Source workspace',
  'migration.report.target': 'Target workspace',
  'migration.report.fromSqlite': 'From SQLite (brain.db)',
  'migration.report.fromMarkdown': 'From Markdown',
  'migration.report.imported': 'Imported',
  'migration.report.skippedUnchanged': 'Skipped (unchanged)',
  'migration.report.renamedConflicts': 'Renamed on conflict',
  'migration.report.warnings': 'Warnings',
  'migration.report.previewHint':
    'No data has been imported yet. Click Apply import to copy it over.',
  'migration.report.appliedHint':
    'Imported entries are now in your memory. Re-run Preview if you want to compare again.',
  'migration.confirmImport.singular':
    'Import {count} entry into the current workspace?\n\nSource: {source}\nTarget: {target}\n\nExisting memory will be backed up before the import runs.',
  'migration.confirmImport.plural':
    'Import {count} entries into the current workspace?\n\nSource: {source}\nTarget: {target}\n\nExisting memory will be backed up before the import runs.',

  // Settings: Notifications
  'settings.notifications.doNotDisturb': 'Do Not Disturb',
  'settings.notifications.doNotDisturbDesc': 'Pause all notifications for a set period',
  'settings.notifications.channelControls': 'Per-Channel Controls',
  'settings.notifications.channelControlsDesc':
    'Configure notification preferences for each channel',

  // Settings: Features
  'settings.features.screenAwareness': 'Screen Awareness',
  'settings.features.screenAwarenessDesc': 'Let the assistant see your active window',
  'settings.features.messaging': 'Messaging',
  'settings.features.messagingDesc': 'Channel and messaging integration settings',
  'settings.features.tools': 'Tools',
  'settings.features.toolsDesc': 'Manage connected tools and integrations',

  // Settings: AI & Models
  'settings.ai.localSetup': 'Local AI Setup',
  'settings.ai.localSetupDesc': 'Download and configure local AI models',
  'settings.ai.llmProvider': 'LLM Provider',
  'settings.ai.llmProviderDesc': 'Choose and configure your AI provider',

  // Clear App Data modal
  'clearData.title': 'Clear App Data',
  'clearData.warning': 'This will sign you out and permanently delete local app data including:',
  'clearData.bulletSettings': 'App settings and conversations',
  'clearData.bulletCache': 'All local integration cache data',
  'clearData.bulletWorkspace': 'Workspace data',
  'clearData.bulletOther': 'All other local data',
  'clearData.irreversible': 'This action cannot be undone.',
  'clearData.clearing': 'Clearing App Data...',
  'clearData.failed': 'Failed to clear data and logout. Please try again.',
  'clearData.failedLogout': 'Failed to log out. Please try again.',
  'clearData.failedPersist': 'Failed to clear persisted app state. Please try again.',

  // Welcome page
  'welcome.logoAlt': 'OpenHuman',
  'welcome.title': 'Welcome to OpenHuman',
  'welcome.subtitle':
    'Your personal AI super intelligence. Private, simple and extremely powerful.',
  'welcome.connectPrompt': 'Configure RPC URL (Advanced)',
  'welcome.selectRuntime': 'Select a Runtime',
  'welcome.clearingAppData': 'Clearing app data...',
  'welcome.clearAppDataAndRestart': 'Clear app data & restart',
  'welcome.clearAppDataWarning':
    'This wipes locally stored secrets and accounts on this device. Your cloud account is unaffected - you can sign in again right after.',
  'welcome.resetErrorFallback':
    'Could not clear app data. Please quit and reopen OpenHuman, then try again.',
  'welcome.signingIn': 'Signing you in...',
  'welcome.termsIntro': 'By continuing, you agree to the',
  'welcome.termsOfUse': 'Terms',
  'welcome.termsJoiner': 'and',
  'welcome.privacyPolicy': 'Privacy Policy',
  'welcome.termsOutro': '.',
  'welcome.urlPlaceholder': 'http://localhost:8089',
  'welcome.invalidUrl': 'Please enter a valid HTTP or HTTPS URL',
  'welcome.connecting': 'Testing',
  'welcome.connect': 'Test',

  // Home page
  'home.greeting': 'Good morning',
  'home.greetingAfternoon': 'Good afternoon',
  'home.greetingEvening': 'Good evening',
  'home.askAssistant': 'Ask your assistant anything...',
  'home.statusOk': 'Your assistant is ready when you are. Type something below to get started.',
  'home.statusBackendOnly': 'Reconnecting to backend… your agent will be available again shortly.',
  'home.statusCoreUnreachable':
    "The OpenHuman core isn't responding. The background process may have crashed or failed to start.",
  'home.statusInternetOffline':
    'Your device is offline right now. Check your network or restart the app to reconnect.',
  'home.restartCore': 'Restart Core',
  'home.restartingCore': 'Restarting core…',
  'home.themeToggle.toLight': 'Switch to light mode',
  'home.themeToggle.toDark': 'Switch to dark mode',
  'home.usageExhaustedTitle': "You've exhausted your usage",
  'home.usageExhaustedBody':
    "You're out of included usage for now. Start a subscription to unlock more ongoing capacity.",
  'home.usageExhaustedCta': 'Get a subscription',
  'openrouterFree.cta': 'Use OpenRouter free models',
  'openrouterFree.saving': 'Connecting OpenRouter...',
  'openrouterFree.error':
    'Could not switch to OpenRouter free models. Check your OpenRouter sign-in and try again.',
  'home.routinesCard': 'Your Routines',
  'home.routinesActive': '{count} active',

  // Routines
  'routines.title': 'Your Routines',
  'routines.subtitle': 'Things your assistant does automatically',
  'routines.loading': 'Loading routines…',
  'routines.empty': 'No routines yet',
  'routines.emptyHint':
    'Your assistant can run tasks on a schedule — like morning briefings or daily summaries.',
  'routines.refresh': 'Refresh',
  'routines.nextRun': 'Next run',
  'routines.lastRunSuccess': 'Last run succeeded',
  'routines.lastRunFailed': 'Last run failed',
  'routines.notRunYet': 'Not run yet',
  'routines.runNow': 'Run Now',
  'routines.running': 'Running…',
  'routines.runNowTimedOut': 'Run timed out — please refresh and try again.',
  'routines.viewHistory': 'View history',
  'routines.loadingHistory': 'Loading…',
  'routines.noHistory': 'No run history yet.',
  'routines.statusSuccess': 'Success',
  'routines.statusError': 'Error',
  'routines.showOutput': 'Show output',
  'routines.hideOutput': 'Hide output',
  'routines.toggleEnabled': 'Enable or disable this routine',
  'routines.typeAgent': 'Agent',
  'routines.typeCommand': 'Command',
  'nav.routines': 'Routines',

  // Chat / Conversations
  'chat.newThread': 'New thread',
  'chat.newConversation': 'New Conversation',
  'chat.newWindowWelcome1': 'Welcome, {name} 👋',
  'chat.newWindowWelcome2': "Let's cook, {name} 🧑‍🍳.",
  'chat.newWindowWelcome3': 'Time to Zone In 🧘🏻',
  'chat.typeMessage': 'How can I help you today?',
  'chat.send': 'Send message',
  'chat.stopGeneration': 'Stop generating',
  'chat.parallelBranchHint': 'Type a parallel branch — ⌘/Ctrl+Enter to send',
  'chat.followupHint':
    'Queue a follow-up — sent after this reply · ⌘/Ctrl+Enter for a parallel branch',
  'chat.queuedFollowups.label': 'Queued follow-ups',
  'chat.queuedFollowups.clear': 'Clear',
  'chat.queuedFollowups.clearFailed': "Couldn't clear the queue — try again.",
  'chat.parallelBranchLabel': 'Parallel branch',
  'chat.thinking': 'Thinking...',
  'chat.noMessages': 'No messages yet',
  'chat.startConversation': 'Start a conversation',
  'chat.regenerate': 'Regenerate',
  'chat.copyResponse': 'Copy response',
  'chat.citations': 'Citations',
  'chat.toolUsed': 'Tool used',

  // Skills / Connections
  'scope.legacy': 'Legacy',
  'scope.user': 'User',
  'scope.project': 'Project',
  'skills.title': 'Connections',
  'skills.search': 'Search connections...',
  'skills.noResults': 'No connections found',
  'skills.loadingIntegrations': 'Loading integrations…',
  'skills.connect': 'Connect',
  'skills.disconnect': 'Disconnect',
  'skills.configure': 'Manage',
  'skills.connected': 'Connected',
  'skills.available': 'Available',
  'skills.addAccount': 'Add Account',
  'skills.channels': 'Messaging',
  'skills.explorer.emptyCta': 'Install from URL',
  'skills.explorer.emptyDescription':
    'Install a SKILL.md package or place Hermes-style folders under ~/.openhuman/skills.',
  'skills.explorer.emptyTitle': 'No skills found',
  'skills.explorer.installFromUrl': 'Install from URL',
  'skills.explorer.newSkill': 'New skill',
  'skills.explorer.subtitle':
    'Browse SKILL.md packages, including Hermes-style markdown, scripts, references, templates, examples, and prompts.',
  'skills.explorer.title': 'Skills explorer',
  'skills.explorer.searchPlaceholder': 'Search skills...',
  'skills.explorer.scopeUser': 'User',
  'skills.explorer.scopeProject': 'Project',
  'skills.explorer.scopeLegacy': 'Legacy',
  'skills.explorer.noDescription': 'No description provided.',
  'skills.explorer.uninstallSuccess': 'Skill uninstalled successfully.',
  'skills.explorer.registryTab': 'Registry',
  'skills.explorer.installedTab': 'Installed',
  'skills.explorer.allFormats': 'All formats',
  'skills.explorer.refreshRegistry': 'Refresh registry',
  'skills.explorer.registryEmptyTitle': 'No registry entries',
  'skills.explorer.registryEmptyDescription':
    'Could not load the skill registry. Check your connection and try refreshing.',
  'skills.explorer.showingOf':
    'Showing {shown} of {total} results. Refine your search to see more.',
  'skills.explorer.installed': 'Installed',
  'skills.explorer.install': 'Install',
  'skills.explorer.installing': 'Installing…',
  'skills.integrations': 'Composio Integrations',
  'skills.integrationsSubtitle':
    'Cloud-based OAuth connections — sign in with your account and Composio brokers the tokens so agents can read and act on your behalf. No API keys to manage.',
  'skills.composio.noApiKeyTitle': 'No Composio API Key Configured',
  'skills.composio.noApiKeyDescription':
    'Local mode uses your own Composio API key. Open Settings → Advanced → Composio to add one before connecting integrations here.',
  'skills.composio.noApiKeyCta': 'Open in Settings',
  'skills.tabs.composio': 'Composio',
  'skills.tabs.channels': 'Channels',
  'skills.tabs.explorer': 'Skills',
  'skills.tabs.meetings': 'Google Meet',
  'skills.tabs.mcp': 'MCP Servers',
  // Connections page tabs (Phase 2 rename)
  'connections.tabs.composio': 'Composio',
  'connections.tabs.oauth': 'OAuth',
  'connections.tabs.composioKey': 'Composio',
  'connections.tabs.channels': 'Channels',
  'connections.tabs.mcp': 'MCP Servers',
  'connections.tabs.skills': 'Skills',
  'connections.tabs.meetings': 'Meetings',
  'connections.groups.integrations': 'Integrations',
  'connections.groups.intelligence': 'Intelligence',
  'connections.groups.apiKeys': 'API keys',
  // Intelligence / Memory
  'memory.title': 'Memory',
  'memory.search': 'Search memories...',
  'memory.noResults': 'No memories found',
  'memory.empty': 'No memories yet. Memories are created automatically as you interact.',
  'memory.tab.memory': 'Memory',
  'memory.tab.memoryTree': 'Memory Tree',
  'memory.tab.tasks': 'Tasks',
  'memory.tab.tasksDescription':
    'Create and track tasks — your own to-dos plus the boards your agents build across conversations.',
  'memory.tab.subconscious': 'Subconscious',
  'memory.tab.agentWork': 'Agent Work',
  'memory.tab.agentWorkDescription':
    'A command center for every background agent run — grouped by what needs your input, what is working, and what has finished.',
  'memory.tab.worktrees': 'Worktrees',
  'memory.tab.worktreesDescription':
    'Isolated git worktrees from parallel agent workers — inspect changes, open them, or clean them up.',
  'memory.tab.teams': 'Teams',
  'memory.tab.teamsDescription':
    'Coordinated agent teams — who owns each task, what is blocked, and what the teammates are saying to each other.',
  'memory.tab.agents': 'Library',
  'memory.tab.agentsDescription':
    'Browse and run your available agents — each with its own tools, capabilities, and focus area.',
  'memory.tab.workflows': 'Workflows',
  'memory.tab.workflowsDescription':
    'Reusable, runnable procedures — a goal plus the steps to reach it. Create one, install from a URL, or open a workflow to run it.',
  'memory.tab.orchestration': 'Orchestration',
  'memory.tab.orchestrationDescription':
    'Run multi-agent workflows — fan a question out across parallel agents, cross-check their findings, and watch each phase finish into one synthesized answer.',
  'memory.tab.dreams': 'Dreams',
  'memory.tab.calls': 'Calls',
  'memory.tab.diagram': 'Diagram',
  'memory.tab.centrality': 'Centrality',
  'memory.tab.namespaces': 'Namespaces',
  'memory.tab.timeline': 'Timeline',
  'memory.tab.cohesion': 'Cohesion',
  'memory.tab.settings': 'Settings',
  'memory.tab.council': 'Council',

  // Activity surface — Phase 3 renamed tabs
  'activity.tabs.automations': 'Automations',
  'activity.tabs.automationsDescription':
    'Reusable, runnable procedures — a goal plus the steps to reach it. Create one, install from a URL, or open a workflow to run it.',
  'activity.tabs.backgroundActivity': 'Subconscious',
  'activity.tabs.alerts': 'Alerts',

  'intelligence.agents.title': 'Agents Library',
  'intelligence.agents.subtitle':
    'Inspect runnable specialists and send one task to a named agent.',
  'intelligence.agents.refresh': 'Refresh',
  'intelligence.agents.loading': 'Loading agents...',
  'intelligence.agents.failedToLoad': 'Could not load agents',
  'intelligence.agents.empty': 'No runnable agents are available.',
  'intelligence.agents.readOnly': 'Read-only',
  'intelligence.agents.writeCapable': 'Write-capable',
  'intelligence.agents.allTools': 'All tools',
  'intelligence.agents.toolCountOne': '{count} tool',
  'intelligence.agents.toolCountOther': '{count} tools',
  'intelligence.agents.subagentCountOne': '{count} subagent',
  'intelligence.agents.subagentCountOther': '{count} subagents',
  'intelligence.agents.startChat': 'Start chat',
  'intelligence.agents.startChatPrompt':
    'Start a chat with this agent. Introduce your specialty, ask what you need to know, and wait for my task.',
  'intelligence.agents.copyId': 'Copy ID',
  'intelligence.agents.copied': 'Copied',
  'intelligence.agents.taskPlaceholder': 'Task for this agent',
  'intelligence.agents.runTask': 'Run task',
  'intelligence.agents.running': 'Running...',
  'intelligence.agents.runFailed': 'Could not start the selected agent',
  'intelligence.agents.model.inherit': 'Inherit',
  'intelligence.agents.tier.chat': 'Chat',
  'intelligence.agents.tier.reasoning': 'Reasoning',
  'intelligence.agents.tier.worker': 'Worker',
  'modelCouncil.title': 'Model Council',
  'modelCouncil.intro':
    'Ask one question, get independent answers from several models in parallel, then a chair model synthesizes where they agree, where they disagree, and what each uniquely adds.',
  'modelCouncil.listTitle': 'Councils',
  'modelCouncil.listIntro':
    'Choose a saved council, edit its agents and judge, or create a new council for a specific kind of decision.',
  'modelCouncil.addCouncil': 'New council',
  'modelCouncil.openCouncil': 'Open council',
  'modelCouncil.editCouncil': 'Edit council',
  'modelCouncil.editCurrentCouncil': 'Edit current council',
  'modelCouncil.editCouncilAria': 'Edit {name}',
  'modelCouncil.deleteCouncilAria': 'Delete {name}',
  'modelCouncil.backToCouncils': 'Back to councils',
  'modelCouncil.saveCouncil': 'Save council',
  'modelCouncil.savingCouncil': 'Saving…',
  'modelCouncil.cancelEdit': 'Cancel',
  'modelCouncil.loadingCouncils': 'Loading councils…',
  'modelCouncil.noCouncils': 'No councils yet. Add one to get started.',
  'modelCouncil.noCouncilDescription': 'No description',
  'modelCouncil.registryErrorPrefix': 'Council registry failed:',
  'modelCouncil.councilNameLabel': 'Council name',
  'modelCouncil.councilDescriptionLabel': 'Description',
  'modelCouncil.councilDescriptionPlaceholder': 'When to use this council',
  'modelCouncil.selectModel': 'Select',
  'modelCouncil.modelPickerHelp': 'Select a routing hint or pin an exact provider model.',
  'modelCouncil.closeModelPicker': 'Close',
  'modelCouncil.hint.chat': 'Chat',
  'modelCouncil.hint.code': 'Code',
  'modelCouncil.hint.default': 'Default',
  'modelCouncil.hint.reasoning': 'Reasoning',
  'modelCouncil.hint.summarize': 'Summarize',
  'modelCouncil.modelPickerHints': 'Hints',
  'modelCouncil.modelPickerProviderModel': 'Provider + model',
  'modelCouncil.modelProviderLabel': 'Model provider',
  'modelCouncil.modelIdLabel': 'Model id',
  'modelCouncil.useProviderModel': 'Use provider model',
  'modelCouncil.questionLabel': 'Question',
  'modelCouncil.questionPlaceholder': 'Ask the council a question…',
  'modelCouncil.membersLabel': 'Member models',
  'modelCouncil.maxMembersNote': 'up to {max}',
  'modelCouncil.memberPlaceholder': 'e.g. gpt-5.2',
  'modelCouncil.memberAria': 'Member model {n}',
  'modelCouncil.removeMemberAria': 'Remove member model {n}',
  'modelCouncil.addMember': '+ Add model',
  'modelCouncil.settingsTitle': 'Council settings',
  'modelCouncil.settingsSummary': '{count} jurors · judge: {judge}',
  'modelCouncil.juryCountLabel': 'Jury count',
  'modelCouncil.debateRoundsLabel': 'Debate turns',
  'modelCouncil.debateRoundsHelp':
    'Each juror keeps debating across turns before the judge writes the final synthesis.',
  'modelCouncil.judgeAgentLabel': 'Judge agent',
  'modelCouncil.defaultJudge': 'Default judge',
  'modelCouncil.savedProfile': 'Saved profile',
  'modelCouncil.customAgent': 'Custom agent',
  'modelCouncil.judgeProfileLabel': 'Judge profile',
  'modelCouncil.chooseProfile': 'Choose a profile',
  'modelCouncil.judgeNameLabel': 'Judge name',
  'modelCouncil.judgeNamePlaceholder': 'Chief Judge',
  'modelCouncil.rosterHeading': 'Council roster',
  'modelCouncil.rosterHelp':
    'Each juror can inherit the default agent, use a saved profile, or become a custom profile for this run.',
  'modelCouncil.loadingProfiles': 'Loading profiles…',
  'modelCouncil.jurorLabel': 'Juror {n}',
  'modelCouncil.profileModeLabel': 'Profile source',
  'modelCouncil.mode.default': 'Default',
  'modelCouncil.mode.profile': 'Profile',
  'modelCouncil.mode.custom': 'Custom',
  'modelCouncil.memberProfileAria': 'Juror {n} profile',
  'modelCouncil.memberNameAria': 'Juror {n} name',
  'modelCouncil.memberNamePlaceholder': 'Agent name',
  'modelCouncil.profileModelPlaceholder': 'Override profile model',
  'modelCouncil.memberBriefAria': 'Juror {n} brief',
  'modelCouncil.memberBriefPlaceholder': 'Perspective for this juror',
  'modelCouncil.jurorFallback': 'Juror',
  'modelCouncil.sharedReasoningLabel': 'Shared reasoning file',
  'modelCouncil.sharedReasoningHelp':
    'The council works against this shared scratchpad before the judge writes the synthesis.',
  'modelCouncil.liveScratchpadHelp':
    'Juror updates are appended here after each round, then fed into the next round.',
  'modelCouncil.liveScratchpadBadge': 'Live',
  'modelCouncil.scratchpadRoundHeading': 'Round {round} updates',
  'modelCouncil.scratchpadNoResponse': 'No response',
  'modelCouncil.chairLabel': 'Chair model',
  'modelCouncil.chairPlaceholder': 'e.g. claude-opus-4-8',
  'modelCouncil.chairHelp': 'The chair reads every member answer and writes the synthesis.',
  'modelCouncil.run': 'Convene council',
  'modelCouncil.running': 'Convening…',
  'modelCouncil.runningHint': 'Querying members in parallel, then synthesizing…',
  'modelCouncil.deliberationHeading': 'Council deliberation',
  'modelCouncil.deliberationHelp':
    'Mascots show each agent thinking while the shared reasoning file is in play.',
  'modelCouncil.debateRoundInstruction':
    'Respond to the other jurors so far. Preserve disagreements, revise your view when warranted, and keep your current conclusion explicit.',
  'modelCouncil.debateFinalInstruction':
    'This is your final juror turn. Converge where the evidence supports it, call out remaining disagreement, and hand the judge a clear conclusion.',
  'modelCouncil.roundLabel': 'Round {round}',
  'modelCouncil.currentRoundThinking': 'Continuing the next turn…',
  'modelCouncil.thinkingBadge': 'Thinking',
  'modelCouncil.thinkingWithBrief': 'Working from this perspective: {brief}',
  'modelCouncil.thought.evidence':
    'Checking evidence, assumptions, and what the shared reasoning file already captures.',
  'modelCouncil.thought.plan': 'Sketching the practical path and where execution could get stuck.',
  'modelCouncil.thought.risk':
    'Looking for failure modes, missing context, and brittle conclusions.',
  'modelCouncil.thought.tradeoffs':
    'Comparing tradeoffs before handing the judge a concise position.',
  'modelCouncil.thought.synthesis':
    'Preparing a distinct view so the judge can compare real disagreement.',
  'modelCouncil.judgeWaitingBadge': 'Judge',
  'modelCouncil.judgeWaitingThought':
    'Waiting for juror answers, then reading the shared reasoning file to synthesize.',
  'modelCouncil.judgeSynthesizingBadge': 'Synthesizing',
  'modelCouncil.judgeSynthesizingThought':
    'Reading the live juror thoughts and writing the final council synthesis.',
  'modelCouncil.errorPrefix': 'Council failed:',
  'modelCouncil.resultsHeading': 'Council results',
  'modelCouncil.memberAnswered': 'Answered',
  'modelCouncil.memberFailed': 'Failed',
  'modelCouncil.synthesisHeading': 'Synthesis',
  'modelCouncil.synthesisBy': 'by {model}',
  'modelCouncil.usageHeading': 'Debate usage',
  'modelCouncil.usageEstimated':
    'Estimated token counts from debate prompts and responses. Real pricing requires provider usage from the council RPC.',
  'modelCouncil.usageEstimatedBadge': 'Estimated tokens',
  'modelCouncil.usageInputTokens': 'Input',
  'modelCouncil.usageOutputTokens': 'Output',
  'modelCouncil.usageTotalTokens': 'Total',
  'memory.analyzeNow': 'Analyze Now',
  'namespaceOverview.title': 'Namespace Overview',
  'namespaceOverview.intro':
    'How your knowledge is distributed across contexts — the number of facts and distinct entities recorded in each namespace.',
  'namespaceOverview.loading': 'Aggregating namespaces…',
  'namespaceOverview.errorPrefix': 'Could not load the graph:',
  'namespaceOverview.retry': 'Retry',
  'namespaceOverview.empty': 'No knowledge graph yet.',
  'namespaceOverview.emptyHint':
    'As the assistant records facts across contexts, each namespace will appear here.',
  'namespaceOverview.metricNamespaces': 'Namespaces',
  'namespaceOverview.metricFacts': 'Facts',
  'namespaceOverview.metricEntities': 'Entities',
  'namespaceOverview.heading': 'By namespace',
  'namespaceOverview.unnamespaced': '(un-namespaced)',
  'namespaceOverview.factsLabel': '{count} facts',
  'namespaceOverview.entitiesLabel': '{count} entities',
  'namespaceOverview.entitiesShort': '{count} ent.',
  'namespaceOverview.truncated': 'Showing the top {shown} of {total} namespaces.',
  'memoryTimeline.title': 'Memory Timeline',
  'memoryTimeline.intro':
    'When the assistant learned about you — facts grouped by the month they were last reinforced. Surfaces growth, bursts of activity, and quiet stretches.',
  'memoryTimeline.loading': 'Building the timeline…',
  'memoryTimeline.errorPrefix': 'Could not load the graph:',
  'memoryTimeline.retry': 'Retry',
  'memoryTimeline.namespaceLabel': 'Namespace',
  'memoryTimeline.namespaceAll': 'All namespaces',
  'memoryTimeline.empty': 'No knowledge graph yet.',
  'memoryTimeline.emptyHint':
    'As the assistant records facts about you, their timeline will appear here.',
  'memoryTimeline.metricTotal': 'Facts',
  'memoryTimeline.metricMonths': 'Active months',
  'memoryTimeline.metricRecent': 'Last 30 days',
  'memoryTimeline.heading': 'Facts learned per month',
  'memoryTimeline.busiestCaption': 'Busiest: {period} ({count})',
  'memoryTimeline.undatedNote': '{count} fact(s) have no recorded date.',
  'memoryTimeline.truncated': 'Showing the {shown} most recent of {total} months.',
  'graphCentrality.title': 'Knowledge Graph Centrality',
  'graphCentrality.intro':
    'PageRank over your memory graph surfaces the load-bearing hubs — and the connector entities that link otherwise-separate clusters, which a raw frequency count cannot reveal.',
  'graphCentrality.loading': 'Computing centrality…',
  'graphCentrality.errorPrefix': 'Could not load the graph:',
  'graphCentrality.retry': 'Retry',
  'graphCentrality.empty': 'No knowledge graph yet.',
  'graphCentrality.emptyHint':
    'As the assistant records facts about you, the most connected entities will surface here.',
  'graphCentrality.namespaceLabel': 'Namespace',
  'graphCentrality.namespaceAll': 'All namespaces',
  'graphCentrality.metricEntities': 'Entities',
  'graphCentrality.metricConnections': 'Connections',
  'graphCentrality.metricClusters': 'Clusters',
  'graphCentrality.clustersCaption': '{components} clusters · largest holds {largest}',
  'graphCentrality.approximateBadge': 'approximate',
  'graphCentrality.approximateTitle': 'Stopped at the iteration cap before fully converging',
  'graphCentrality.rankedHeading': 'Top entities by influence',
  'graphCentrality.colRank': '#',
  'graphCentrality.colEntity': 'Entity',
  'graphCentrality.colInfluence': 'Influence',
  'graphCentrality.colLinks': 'Links',
  'graphCentrality.bridgeBadge': 'connector',
  'graphCentrality.bridgeTitle': 'Connector — more influential than its link count suggests',
  'graphCentrality.degreeTitle': '{in} in · {out} out',
  'memory.tab.associations': 'Associations',
  'entityAssociations.title': 'Entity Associations',
  'entityAssociations.intro':
    'Entities that share many of the same connections are associated — even when no single fact links them directly. Jaccard similarity surfaces these hidden pairings.',
  'entityAssociations.loading': 'Scoring associations…',
  'entityAssociations.errorPrefix': 'Could not load the graph:',
  'entityAssociations.retry': 'Retry',
  'entityAssociations.empty': 'No associations yet.',
  'entityAssociations.emptyHint':
    'When entities start sharing connections, the strongest pairings will surface here.',
  'entityAssociations.namespaceLabel': 'Namespace',
  'entityAssociations.namespaceAll': 'All namespaces',
  'entityAssociations.metricEntities': 'Entities',
  'entityAssociations.metricPairs': 'Associations',
  'entityAssociations.rankedHeading': 'Strongest associations',
  'entityAssociations.linkedBadge': 'linked',
  'entityAssociations.inferredBadge': 'inferred',
  'entityAssociations.linkedTitle': 'These entities are directly connected.',
  'entityAssociations.inferredTitle':
    'No direct link — associated only through shared connections.',
  'entityAssociations.sharedLabel': '{shared} shared',
  'entityAssociations.pairTitle': '{jaccard}% similar · {shared} of {union} connections shared',
  'entityAssociations.truncated': 'Showing {shown} of {total} — strongest first.',
  'memory.tab.freshness': 'Freshness',
  'memoryFreshness.title': 'Knowledge Freshness',
  'memoryFreshness.intro':
    'Facts the assistant has not reconfirmed lately decay along a forgetting curve. This surfaces what is going stale and worth re-checking, so old facts are not treated as still-certain.',
  'memoryFreshness.loading': 'Scoring freshness…',
  'memoryFreshness.errorPrefix': 'Could not load the graph:',
  'memoryFreshness.retry': 'Retry',
  'memoryFreshness.empty': 'No knowledge graph yet.',
  'memoryFreshness.emptyHint':
    'As the assistant records facts about you, their freshness will be tracked here.',
  'memoryFreshness.namespaceLabel': 'Namespace',
  'memoryFreshness.namespaceAll': 'All namespaces',
  'memoryFreshness.metricFresh': 'Fresh',
  'memoryFreshness.metricFading': 'Fading',
  'memoryFreshness.metricStale': 'Stale',
  'memoryFreshness.recallCaption': 'Average recall {recall}% across {total} facts',
  'memoryFreshness.queueHeading': 'Re-confirm queue',
  'memoryFreshness.queueTruncated': 'Showing {shown} of {total} — address these first.',
  'memoryFreshness.allFresh': 'Every fact is still fresh — nothing to re-confirm.',
  'memoryFreshness.statusFading': 'fading',
  'memoryFreshness.statusStale': 'stale',
  'memoryFreshness.ageLabel': '{days}d old',
  'memoryFreshness.recallTitle': '{recall}% recall · half-life {halfLife}d',
  'memory.tab.path': 'Paths',
  'connectionPath.title': 'Connection Path',
  'connectionPath.intro':
    'Trace the shortest chain of relations linking any two entities — how the graph connects them, even across several hops.',
  'connectionPath.loading': 'Loading the graph…',
  'connectionPath.errorPrefix': 'Could not load the graph:',
  'connectionPath.retry': 'Retry',
  'connectionPath.namespaceLabel': 'Namespace',
  'connectionPath.namespaceAll': 'All namespaces',
  'connectionPath.sourceLabel': 'From',
  'connectionPath.targetLabel': 'To',
  'connectionPath.sourcePlaceholder': 'Start entity',
  'connectionPath.targetPlaceholder': 'End entity',
  'connectionPath.prompt': 'Pick two entities to trace how they are connected.',
  'connectionPath.empty': 'No knowledge graph yet.',
  'connectionPath.emptyHint':
    'Once the assistant records related facts, you can trace connections here.',
  'connectionPath.resultHeading': 'Shortest path',
  'connectionPath.pathSummary': '{length} hop(s) apart',
  'connectionPath.sameMessage': 'Pick two different entities.',
  'connectionPath.missingSource': '"{entity}" is not in the graph.',
  'connectionPath.missingTarget': '"{entity}" is not in the graph.',
  'connectionPath.noPath': 'No connection found between "{source}" and "{target}".',

  'graphCohesion.title': 'Graph Cohesion',
  'graphCohesion.intro':
    "How tightly knit the neighbourhood is around each entity. Brokers — entities whose neighbours aren't linked to each other — are the single points holding otherwise-separate clusters together, which a frequency or PageRank sort cannot reveal.",
  'graphCohesion.loading': 'Computing cohesion…',
  'graphCohesion.errorPrefix': 'Could not load the graph:',
  'graphCohesion.retry': 'Retry',
  'graphCohesion.empty': 'No knowledge graph yet.',
  'graphCohesion.emptyHint':
    'As the assistant records connected facts about you, their clustering structure will surface here.',
  'graphCohesion.namespaceLabel': 'Namespace',
  'graphCohesion.namespaceAll': 'All namespaces',
  'graphCohesion.metricEntities': 'Entities',
  'graphCohesion.metricConnections': 'Connections',
  'graphCohesion.metricTriangles': 'Triangles',
  'graphCohesion.summaryCaption': 'Average clustering {avg} · transitivity {transitivity}',
  'graphCohesion.noBrokers': 'No entities with two or more connections yet.',
  'graphCohesion.rankedHeading': 'Brokers — loosest neighbourhoods',
  'graphCohesion.colRank': '#',
  'graphCohesion.colEntity': 'Entity',
  'graphCohesion.colCohesion': 'Cohesion',
  'graphCohesion.colLinks': 'Links',
  'graphCohesion.brokerBadge': 'broker',
  'graphCohesion.brokerTitle':
    "Structural hole: this entity's neighbours aren't connected to each other — it's the sole link between them.",

  // Memory Tree status panel (#1856 Part 1)
  'memoryTree.status.title': 'Memory Tree',
  'memoryTree.status.autoSyncLabel': 'Auto-sync',
  'memoryTree.status.autoSyncDescription':
    'Pause to stop new ingestion. Existing wiki stays queryable.',
  'memoryTree.status.statusTile': 'Status',
  'memoryTree.status.lastSyncTile': 'Last sync',
  'memoryTree.status.totalChunksTile': 'Total chunks',
  'memoryTree.status.wikiSizeTile': 'Wiki size',
  'memoryTree.status.statusRunning': 'Running',
  'memoryTree.status.statusPaused': 'Paused',
  'memoryTree.status.statusSyncing': 'Syncing',
  'memoryTree.status.statusError': 'Error',
  'memoryTree.status.statusIdle': 'Idle',
  'memoryTree.status.statusDegraded': 'Degraded',
  'memoryTree.status.never': 'Never',
  // #002: degraded badges + typed remediation strings. The Rust core sends a
  // `remediation_key` (one of memory.health.remediation.*) which the status
  // panel resolves verbatim, so the cause + fix come from one source of truth.
  'memoryTree.status.degradedRecall': 'Semantic recall disabled',
  'memoryTree.status.degradedStructure': 'Wiki structure incomplete',
  'memoryTree.status.extractionCoverage': 'Extraction coverage: {pct}% of chunks have structure',
  'memory.health.remediation.budget_exhausted':
    'Memory embeddings hit the managed budget. Set up local Ollama embeddings (Settings → AI → Embeddings) or add your own embeddings API key to keep building memory.',
  'memory.health.remediation.auth_missing':
    'No embeddings credentials found. Log in to OpenHuman, or set up local Ollama embeddings in Settings → AI → Embeddings.',
  'memory.health.remediation.auth_invalid':
    'Your embeddings credentials were rejected. Re-authenticate, or switch to local Ollama embeddings in Settings → AI → Embeddings.',
  'memory.health.remediation.embeddings_unconfigured':
    'No embeddings provider is configured, so semantic recall is off. Set up local Ollama embeddings (recommended) or add an embeddings key in Settings → AI → Embeddings.',
  'memory.health.remediation.embedding_dim_mismatch':
    'The embedding model returns the wrong vector size (memory expects 1024 dimensions). Pick a 1024-dim model, or request 1024 dimensions for your provider.',
  'memory.health.remediation.local_model_unavailable':
    'A required local model is not available. Install/run Ollama and pull the model, or switch this workload to a cloud provider in Settings → AI.',
  'memory.health.remediation.extraction_timeout':
    'The memory extraction model is timing out, so the wiki has little structure. Switch the Memory extraction model to a faster one in Settings → AI.',
  'memory.health.remediation.summarizer_unavailable':
    'No summarization provider is available for Build Summary Trees. Enable local AI (Ollama), or enable cloud summarization in Settings → AI → Memory.',
  'memory.health.remediation.empty_input_refused':
    'A memory item was skipped because its text was empty. No action needed — newer items continue to embed normally.',
  'memory.health.remediation.storage_unavailable':
    "OpenHuman can't write to its memory storage — the disk or SD card appears to be failing, full, or read-only. Check the drive and free up space; memory processing resumes automatically once storage is writable again.",
  'memory.health.remediation.transient':
    'A temporary error interrupted memory processing. It will retry automatically.',
  'memory.health.remediation.unknown':
    'Memory processing encountered an issue. Check Settings → AI for configuration.',
  'memoryTree.status.fetchError': "Couldn't fetch Memory Tree status",
  'memoryTree.status.retry': 'Retry',
  'memoryTree.status.toggleFailed': "Couldn't toggle auto-sync",
  // Relative-time buckets surfaced by the last-sync tile. `{count}` is
  // replaced client-side at the call site (the runtime `t()` does not
  // interpolate — see I18nContext.tsx).
  'memoryTree.status.justNow': 'just now',
  'memoryTree.status.secondsAgo': '{count}s ago',
  'memoryTree.status.minuteAgo': '1 min ago',
  'memoryTree.status.minutesAgo': '{count} min ago',
  'memoryTree.status.hourAgo': '1 hr ago',
  'memoryTree.status.hoursAgo': '{count} hr ago',
  'memoryTree.status.dayAgo': '1 day ago',
  'memoryTree.status.daysAgo': '{count} days ago',
  // Per-integration health strip (#2763) — rendered between the 4-tile grid
  // and the auto-sync toggle in MemoryTreeStatusPanel.
  'memoryTree.status.integrationsTitle': 'Per-integration health',
  'memoryTree.status.integrationsEmpty': 'No integrations connected',
  'memoryTree.status.integrationActive': 'Active',
  'memoryTree.status.integrationStale': 'Stale',
  'memoryTree.status.integrationChunks': 'Chunks: {count}',

  // Notifications / Alerts
  'alerts.title': 'Alerts',
  'alerts.empty': 'No alerts yet',
  'alerts.markAllRead': 'Mark all as read',
  'alerts.unread': 'unread',

  // Rewards
  'rewards.title': 'Rewards',
  'rewards.referrals': 'Referrals',
  'rewards.coupons': 'Redeem',
  'rewards.localUnavailable':
    'Local login does not earn rewards, coupons, or referral credit. To earn rewards, log out and continue by signing in with an OpenHuman account.',
  'rewards.localUnavailableCta': 'Open Account Settings',
  'rewards.credits': 'Credits',
  'rewards.referralCode': 'Your referral code',
  'rewards.copyCode': 'Copy code',
  'rewards.share': 'Share',

  // Onboarding
  'onboarding.welcome': "Hi. I'm OpenHuman.",
  'onboarding.welcomeDesc':
    'Your super-intelligent AI assistant that runs on your computer. Private, simple, and extremely powerful.',
  'onboarding.context': 'Context Gathering',
  'onboarding.contextDesc': 'Connect the tools and services you use every day.',
  'onboarding.localAI': 'Local AI',
  'onboarding.localAIDesc': 'Set up a local AI model that runs on your machine.',
  'onboarding.chatProvider': 'Chat Provider',
  'onboarding.chatProviderDesc': 'Choose how you want to interact with your assistant.',
  'onboarding.referral': 'Referral',
  'onboarding.referralDesc': 'Apply a referral code if you have one.',
  'onboarding.finish': 'Finish Setup',
  'onboarding.finishDesc': "You're all set! Start using OpenHuman.",
  'onboarding.skip': 'Skip',
  'onboarding.getStarted': 'Get Started',

  // Onboarding: runtime-choice step (Cloud vs Custom)
  'onboarding.runtimeChoice.title': 'How would you like to run OpenHuman?',
  'onboarding.runtimeChoice.subtitle':
    'Pick how much OpenHuman manages for you. You can change this later in Settings.',
  'onboarding.runtimeChoice.cloud.title': 'Simple',
  'onboarding.runtimeChoice.cloud.tagline':
    'Use OpenHuman-hosted sign-in, model routing, search, and managed integrations.',
  'onboarding.runtimeChoice.cloud.f1': 'Backend-brokered OAuth and model routing',
  'onboarding.runtimeChoice.cloud.f2': 'Token compression to stretch your usage further',
  'onboarding.runtimeChoice.cloud.f3': 'One subscription, every model included',
  'onboarding.runtimeChoice.cloud.f4': 'No model, search, or Composio keys to manage',
  'onboarding.runtimeChoice.cloud.f5': 'Local Memory Tree, managed network services',
  'onboarding.runtimeChoice.custom.title': 'Run Custom',
  'onboarding.runtimeChoice.custom.tagline':
    'Bring your own keys. Choose which services OpenHuman should call.',
  'onboarding.runtimeChoice.custom.f1': "You'll need API keys for almost everything",
  'onboarding.runtimeChoice.custom.f2': 'Reuses services you already pay for',
  'onboarding.runtimeChoice.custom.f3': 'Keep supported workloads on your machine',
  'onboarding.runtimeChoice.custom.f4': 'More setup, more knobs',
  'onboarding.runtimeChoice.custom.f5': 'Best for power users and developers',
  'onboarding.runtimeChoice.cloud.creditHighlight': 'Free credits when you sign up',
  'onboarding.runtimeChoice.continueCloud': 'Continue with Simple',
  'onboarding.runtimeChoice.continueCustom': 'Continue with Custom',
  'onboarding.runtimeChoice.recommended': 'Recommended',
  'onboarding.runtimeChoice.exitError': 'Could not finish onboarding. Please try again.',

  // Onboarding: API keys step (only when Custom is picked)
  'onboarding.apiKeys.title': "Let's Add Your API Keys",
  'onboarding.apiKeys.subtitle':
    'You can paste them now or skip and add them later in Settings › AI. Keys are stored on this device, encrypted at rest.',
  'onboarding.apiKeys.openaiLabel': 'OpenAI API key',
  'onboarding.apiKeys.openaiPlaceholder': 'sk-...',
  'onboarding.apiKeys.openaiOauthHint':
    'Use ChatGPT Plus/Pro (subscription) or an OpenAI API key — not both required.',
  'onboarding.apiKeys.openaiOauthOpening': 'Opening sign-in…',
  'onboarding.apiKeys.openaiOauthConnect': 'Sign in with ChatGPT',
  'onboarding.apiKeys.openaiOauthConnected': 'Connected with ChatGPT',
  'onboarding.apiKeys.openaiOauthCallbackHint':
    'After signing in, paste the full redirect URL from your browser (starts with {url}).',
  'onboarding.apiKeys.oauthDesktopOnly': 'ChatGPT sign-in is only available in the desktop app.',
  'onboarding.apiKeys.oauthStartFailed':
    'Could not start ChatGPT sign-in. Try again or use an API key.',
  'onboarding.apiKeys.oauthPasteRedirect':
    'Paste the redirect URL from your browser after signing in.',
  'onboarding.apiKeys.oauthCompleteFailed':
    'ChatGPT sign-in did not complete. Check the redirect URL and try again.',
  'onboarding.apiKeys.finishSignIn': 'Finish ChatGPT sign-in',
  'onboarding.apiKeys.orApiKey': 'or API key',
  'onboarding.apiKeys.anthropicLabel': 'Anthropic API key',
  'onboarding.apiKeys.anthropicPlaceholder': 'sk-ant-...',
  'onboarding.apiKeys.saveError': "Couldn't save that key. Please double-check it and try again.",
  'onboarding.apiKeys.skipForNow': 'Skip for now',
  'onboarding.apiKeys.continue': 'Save and continue',
  'onboarding.apiKeys.saving': 'Saving…',

  // Onboarding: Custom wizard (Inference / Voice / OAuth / Search / Activity / Vault / Memory)
  'onboarding.custom.stepperInference': 'Inference',
  'onboarding.custom.stepperVoice': 'Voice',
  'onboarding.custom.stepperOAuth': 'OAuth',
  'onboarding.custom.stepperSearch': 'Search',
  'onboarding.custom.stepperEmbeddings': 'Embeddings',
  'onboarding.custom.stepperActivity': 'Activity',
  'onboarding.custom.stepperVault': 'Vault',
  'onboarding.custom.stepperMemory': 'Memory',
  'onboarding.custom.stepCounter': 'Step {n} of {total}',
  'onboarding.custom.defaultTitle': 'Default',
  'onboarding.custom.defaultSubtitle': 'Let OpenHuman manage it for you.',
  'onboarding.custom.configureTitle': 'Configure',
  'onboarding.custom.configureSubtitle': "I'll pick what to use.",
  'onboarding.custom.progressAriaLabel': 'Onboarding progress',
  'onboarding.custom.continue': 'Continue',
  'onboarding.custom.back': 'Back',
  'onboarding.custom.finish': 'Finish Setup',
  'onboarding.custom.configureLater':
    "You can finish wiring this up after onboarding. We'll drop you on the matching Settings page once you're done.",
  'onboarding.custom.openSettings': 'Open in Settings',

  // Onboarding: Custom > Inference (text)
  'onboarding.custom.inference.title': 'Inference (Text)',
  'onboarding.custom.inference.subtitle':
    'Which language model should answer your questions and run your agents?',
  'onboarding.custom.inference.defaultDesc':
    'OpenHuman routes workloads through its managed backend by default. No keys, no setup.',
  'onboarding.custom.inference.configureDesc':
    'Bring your own OpenAI or Anthropic key. We use it for every text-based workload.',

  // Onboarding: Custom > Voice
  'onboarding.custom.voice.title': 'Voice',
  'onboarding.custom.voice.subtitle': 'Speech-to-text and text-to-speech for voice mode.',
  'onboarding.custom.voice.defaultDesc':
    'OpenHuman ships with managed STT/TTS providers that may send audio/text to hosted services.',
  'onboarding.custom.voice.configureDesc':
    'Use your own ElevenLabs / OpenAI Whisper / etc. Configure in Settings › Voice.',

  // Onboarding: Custom > OAuth (Composio)
  'onboarding.custom.oauth.title': 'Connections (OAuth)',
  'onboarding.custom.oauth.subtitle':
    'Gmail, Slack, Notion, and other connected services that need OAuth.',
  'onboarding.custom.oauth.defaultDesc':
    'OpenHuman brokers OAuth and tool calls through a managed Composio workspace.',
  'onboarding.custom.oauth.configureDesc':
    'Bring your own Composio account / API key. Configure in Settings › Connections.',

  // Onboarding: Custom > Search
  'onboarding.custom.search.title': 'Web Search',
  'onboarding.custom.search.subtitle': 'How OpenHuman searches the web on your behalf.',
  'onboarding.custom.search.defaultDesc':
    'OpenHuman uses a managed search proxy by default. No search API key needed.',
  'onboarding.custom.search.configureDesc':
    'Bring your own search provider key (Tavily, Brave, etc.). Configure in Settings › Tools.',

  // Onboarding: Custom > Embeddings
  'onboarding.custom.embeddings.title': 'Embeddings',
  'onboarding.custom.embeddings.subtitle':
    'How OpenHuman generates vector embeddings for semantic memory search.',
  'onboarding.custom.embeddings.defaultDesc':
    'OpenHuman uses a managed embedding service. No API key needed.',
  'onboarding.custom.embeddings.configureDesc':
    'Bring your own embedding provider (OpenAI, Voyage, Ollama, etc.).',

  // Onboarding: Custom > Activity
  'onboarding.custom.activity.title': 'Agent Activity',
  'onboarding.custom.activity.subtitle':
    'How proactively your agent monitors and acts in the background.',
  'onboarding.custom.activity.defaultDesc':
    'Moderate activity — syncs every hour, sends a daily digest. Balanced cost and responsiveness.',
  'onboarding.custom.activity.configureDesc':
    'Pick your own activity level. Configure in Settings › Agent activity level.',

  // Onboarding: Custom > Vault
  'onboarding.custom.vault.title': 'Memory & Vault Setup',
  'onboarding.custom.vault.subtitle':
    'Confirm where memory notes are written, how source data is read, and whether your vault pipeline is healthy.',
  'onboarding.custom.vault.defaultDesc':
    'Use OpenHuman-managed memory defaults. Vault path and sync health can still be reviewed later.',
  'onboarding.custom.vault.configureDesc':
    'Review vault ownership, run health checks, and tune memory controls now.',
  'onboarding.custom.vault.localDisabledReason':
    'Managed setup requires OpenHuman sign-in and is unavailable in local mode.',
  'onboarding.custom.vault.exitError': 'Could not finish onboarding. Please try again.',

  // Onboarding: Custom > Memory
  'onboarding.custom.memory.title': 'Memory',
  'onboarding.custom.memory.subtitle':
    'How OpenHuman remembers your context, preferences, and prior conversations.',
  'onboarding.custom.memory.defaultDesc':
    'OpenHuman manages memory storage and retrieval automatically. Nothing to set up.',
  'onboarding.custom.memory.configureDesc':
    'Inspect, export, or wipe memory yourself. Configure in Settings › Memory.',

  // Agent activity level
  'activityLevel.title': 'Agent activity level',
  'activityLevel.description':
    'Control how proactive your agent is. Higher levels use more tokens.',
  'activityLevel.off': 'Off',
  'activityLevel.offDesc': 'No background processing. Syncs only when you press the button.',
  'activityLevel.minimal': 'Minimal',
  'activityLevel.minimalDesc': 'Sync sources once per day. No proactive messages.',
  'activityLevel.moderate': 'Moderate',
  'activityLevel.moderateDesc': 'Sync every hour. Daily digest. Suggests actions.',
  'activityLevel.active': 'Active',
  'activityLevel.activeDesc': 'Sync every 10 min. Monitors channels, triages, drafts replies.',
  'activityLevel.alwaysOn': 'Always-on',
  'activityLevel.alwaysOnDesc': 'Real-time sync. Full autonomy within guardrails.',
  'activityLevel.currentMonth': 'This month: ${amount}',
  'activityLevel.saved': 'Activity level updated.',
  'activityLevel.default': 'default',
  'activityLevel.costFree': '$0',
  'activityLevel.costRange': '~${min}–${max}/mo',

  // Accounts
  'accounts.addAccount': 'Add Account',
  'accounts.addApps': 'Add apps',
  'accounts.manageAccounts': 'Manage Accounts',
  'accounts.noAccounts': 'No accounts connected',
  'accounts.connectAccount': 'Connect an account to get started',
  'accounts.agent': 'Agent',
  'accounts.respondQueue': 'Respond Queue',
  'accounts.disconnect': 'Disconnect',
  'accounts.disconnectConfirm': 'Are you sure you want to disconnect this account?',
  'accounts.disconnectClearMemory': 'Also delete memory from this source',
  'accounts.disconnectClearMemoryHint':
    'Permanently removes local memory chunks linked to this connection.',
  'accounts.searchAccounts': 'Search accounts...',

  // Channels
  'channels.title': 'Channels',
  'channels.configure': 'Configure Channel',
  'channels.setup': 'Setup',
  'channels.noChannels': 'No channels configured',
  'channels.localManagedUnavailable': 'Managed channels are not available for local users.',
  'channels.addChannel': 'Add Channel',
  'channels.status.connected': 'Connected',
  'channels.status.disconnected': 'Disconnected',
  'channels.status.error': 'Error',
  'channels.status.configuring': 'Configuring',
  'channels.defaultMessaging': 'Default Messaging Channel',
  'channels.setAsDefault': 'Set as default',
  'channels.defaultBadge': 'Default',

  // Webhooks
  'webhooks.title': 'Webhooks',
  'webhooks.create': 'Create Webhook',
  'webhooks.noWebhooks': 'No webhooks configured',
  'webhooks.url': 'URL',
  'webhooks.secret': 'Secret',
  'webhooks.events': 'Events',
  'webhooks.archiveDirectory': 'Archive Directory',
  'webhooks.todayFile': "Today's File",

  // Invites
  'invites.title': 'Invites',
  'invites.create': 'Create Invite',
  'invites.noInvites': 'No pending invites',
  'invites.code': 'Invite Code',
  'invites.copyLink': 'Copy Link',
  'invites.generate': 'Generate Invite',
  'invites.generating': 'Generating...',
  'invites.refreshing': 'Refreshing invites...',
  'invites.loading': 'Loading invites...',
  'invites.copyCodeAria': 'Copy invite code',
  'invites.revokeAria': 'Revoke invite',
  'invites.usedUp': 'Used Up',
  'invites.uses': 'Uses: {current}{max}',
  'invites.expiresOn': 'Expires {date}',
  'invites.empty': 'No invites yet',
  'invites.emptyHint': 'Generate an invite code to share with others',
  'invites.revokeTitle': 'Revoke Invite Code',
  'invites.revokePromptPrefix': 'Are you sure you want to revoke the invite code',
  'invites.revokeWarning':
    'This invite code will no longer be valid and cannot be used to join the team.',
  'invites.revoking': 'Revoking...',
  'invites.revokeAction': 'Revoke Invite',
  'invites.failedGenerate': 'Failed to generate invite',
  'invites.failedRevoke': 'Failed to revoke invite',
  'team.refreshingMembers': 'Refreshing members...',
  'team.loadingMembers': 'Loading members...',
  'team.memberCount': '{count} member',
  'team.memberCountPlural': '{count} members',
  'team.you': '(You)',
  'team.removeAria': 'Remove {name}',
  'team.noMembers': 'No members found',
  'team.removeTitle': 'Remove Team Member',
  'team.removePromptPrefix': 'Are you sure you want to remove',
  'team.removePromptSuffix': 'from the team?',
  'team.removeWarning': 'They will lose access to the team and all team resources.',
  'team.removing': 'Removing...',
  'team.removeAction': 'Remove Member',
  'team.changeRoleTitle': 'Change Member Role',
  'team.changeRolePrompt': "Change {name}'s role from {oldRole} to {newRole}?",
  'team.changeRoleAdminGrant':
    'This will grant them full admin permissions including the ability to manage team members.',
  'team.changeRoleAdminRemove':
    'This will remove their admin permissions and they will no longer be able to manage the team.',
  'team.changing': 'Changing...',
  'team.changeRoleAction': 'Change Role',
  'team.failedChangeRole': 'Failed to change role',
  'team.failedRemoveMember': 'Failed to remove member',

  // Developer Options / Developer & Diagnostics
  'devOptions.title': 'Advanced',
  'devOptions.titleDiagnostics': 'Developer & Diagnostics',
  'devOptions.diagnostics': 'Diagnostics',
  'devOptions.diagnosticsDesc': 'System health, logs, and performance metrics',
  'devOptions.toolPolicyDiagnosticsDesc':
    'Tool inventory, policy posture, MCP allowlists, and recent blocks',
  'devOptions.toolPolicyDiagnostics.loading': 'Loading…',
  'devOptions.toolPolicyDiagnostics.unavailable': 'Diagnostics unavailable',
  'devOptions.toolPolicyDiagnostics.posture.title': 'Policy posture',
  'devOptions.toolPolicyDiagnostics.posture.autonomy': 'Autonomy:',
  'devOptions.toolPolicyDiagnostics.posture.workspaceOnly': 'Workspace only:',
  'devOptions.toolPolicyDiagnostics.posture.maxActionsPerHour': 'Max actions/hr:',
  'devOptions.toolPolicyDiagnostics.posture.approvalMediumRisk': 'Approval (medium risk):',
  'devOptions.toolPolicyDiagnostics.posture.blockHighRisk': 'Block high risk:',
  'devOptions.toolPolicyDiagnostics.inventory.title': 'Inventory',
  'devOptions.toolPolicyDiagnostics.inventory.totalTools': 'Total tools',
  'devOptions.toolPolicyDiagnostics.inventory.enabledTools': 'Enabled tools',
  'devOptions.toolPolicyDiagnostics.inventory.mcpStdioTools': 'MCP stdio tools',
  'devOptions.toolPolicyDiagnostics.inventory.jsonRpcTools': 'JSON-RPC tools',
  'devOptions.toolPolicyDiagnostics.mcpAllowlists.title': 'MCP allowlists',
  'devOptions.toolPolicyDiagnostics.mcpAllowlists.summary':
    'Enabled: {enabled} · Servers: {enabledCount}/{totalCount}',
  'devOptions.toolPolicyDiagnostics.mcpAllowlists.unnamed': '<unnamed>',
  'devOptions.toolPolicyDiagnostics.mcpAllowlists.allowDeny': 'allow={allowCount} deny={denyCount}',
  'devOptions.toolPolicyDiagnostics.mcpWriteAudit.title': 'MCP write audit',
  'devOptions.toolPolicyDiagnostics.mcpWriteAudit.summary':
    'Enabled: {enabled} · Recent (24h): {recentRows}',
  'devOptions.toolPolicyDiagnostics.recentBlocked.title': 'Recent blocked calls',
  'devOptions.toolPolicyDiagnostics.recentBlocked.empty': 'No blocked calls recorded.',
  'devOptions.toolPolicyDiagnostics.redactedSurfaces.title': 'Redacted surfaces',
  'devOptions.toolPolicyDiagnostics.redactedSurfaces.summary':
    'Write-capable: {writeCount} · Policy surfaces: {policyCount}',
  'devOptions.debugPanels': 'Debug Panels',
  'devOptions.debugPanelsDesc': 'Feature flags, state inspection, and debugging tools',
  'devOptions.webhooks': 'Webhooks',
  'devOptions.webhooksDesc': 'Configure and test webhook integrations',
  'devOptions.memoryInspection': 'Memory Inspection',
  'devOptions.memoryInspectionDesc': 'Browse, query, and manage memory entries',

  // Voice / Dictation
  'voice.pushToTalk': 'Push to Talk',
  'voice.recording': 'Recording...',
  'voice.processing': 'Processing...',
  'voice.languageHint': 'Language',

  // Misc
  'misc.rehydrating': 'Loading your data...',
  'misc.checkingServices': 'Checking services...',
  'misc.serviceUnavailable': 'Service Unavailable',
  'misc.somethingWentWrong': 'Something went wrong',
  'misc.tryAgainLater': 'Please try again later.',
  'misc.restartApp': 'Restart App',
  'misc.updateAvailable': 'Update Available',
  'misc.updateNow': 'Update Now',
  'misc.updateLater': 'Later',
  'misc.downloading': 'Downloading...',
  'misc.installing': 'Installing...',
  'misc.beta':
    'OpenHuman is in early beta. Feel free to share feedback or report any bugs you run into — every report helps us ship faster.',
  'misc.betaFeedback': 'Send feedback',

  // Mnemonic / Recovery
  'mnemonic.title': 'Recovery Phrase',
  'mnemonic.warning': 'Write down these words in order and store them somewhere safe.',
  'mnemonic.copyWarning':
    'Never share your recovery phrase. Anyone with these words can access your account.',
  'mnemonic.copied': 'Recovery phrase copied to clipboard',
  'mnemonic.reveal': 'Reveal phrase',
  'mnemonic.revealPhrase': 'Reveal recovery phrase',
  'mnemonic.hidden': 'Recovery phrase is hidden',

  // What Leaves My Computer
  'privacy.title': 'Privacy & Security',
  'privacy.description': 'Transparency report of data sent to external services.',
  'privacy.empty': 'No external data transfers detected.',
  'privacy.whatLeavesComputer': 'What leaves your computer',
  'privacy.loading': 'Loading privacy details...',
  'privacy.loadError': 'Could not load the live privacy list. Analytics controls below still work.',
  'privacy.noCapabilities': 'No capabilities currently disclose data movement.',
  'privacy.sentTo': 'Sent to',
  'privacy.leavesDevice': 'Leaves device',
  'privacy.staysLocal': 'Stays local',
  'privacy.anonymizedAnalytics': 'Product Analytics',
  'privacy.shareAnonymizedData': 'Share Product Analytics and Diagnostics',
  'privacy.shareAnonymizedDataDesc':
    'Help improve OpenHuman by sharing privacy-limited crash reports and usage events, including a stable account ID and app version metadata. Messages, wallet keys, API keys, and session tokens are never collected.',
  'privacy.meetingFollowUps': 'Meeting follow-ups',
  'privacy.autoHandoffMeet': 'Auto-handoff Google Meet transcripts to the orchestrator',
  'privacy.autoHandoffMeetDesc':
    "When a Google Meet call ends, OpenHuman's orchestrator can read the transcript and may take actions like drafting messages, scheduling follow-ups, or posting summaries to your connected Slack workspace. Off by default.",
  'privacy.analyticsDisclaimer':
    'When enabled, Product Analytics and Diagnostics may include privacy-limited crash reports and usage events, a stable account ID, and app version metadata. Messages, wallet keys, API keys, and session tokens are never collected. You can change this setting at any time.',

  // Settings: About
  'settings.about.version': 'Version',
  'settings.about.updateAvailable': 'is available',
  'settings.about.softwareUpdates': 'Software updates',
  'settings.about.lastChecked': 'Last checked',
  'settings.about.checking': 'Checking...',
  'settings.about.checkForUpdates': 'Check for updates',
  'settings.about.releases': 'Releases',
  'settings.about.releasesDesc': 'Browse release notes and earlier builds on GitHub.',
  'settings.about.openReleases': 'Open GitHub releases',
  'settings.about.connection': 'Connection',
  'settings.about.connectionMode': 'Mode',
  'settings.about.connectionModeLocal': 'Local',
  'settings.about.connectionModeCloud': 'Cloud',
  'settings.about.connectionModeUnset': 'Not selected',
  'settings.about.serverUrl': 'Server URL',
  'settings.about.serverUrlUnavailable': 'Unavailable',
  'settings.about.connectionHelperLocal':
    'Spawned in-process by the Tauri shell on app launch. The port is chosen at startup, so this URL changes between launches.',
  'settings.about.connectionHelperCloud':
    'Connected to a remote core. Change this in BootCheck or the cloud mode picker.',
  'settings.heartbeat.title': 'Heartbeat & loops',
  'settings.usage.title': 'Usage & Limits',
  'settings.usage.menuDesc': 'Costs, token usage, budgets, and background activity',
  'settings.costDashboard.title': 'Cost dashboard',
  'settings.costDashboard.sevenDayCost': '7-day daily cost',
  'settings.costDashboard.sevenDayTokens': '7-day token usage',
  'settings.costDashboard.totalSpend': '7-day total',
  'settings.costDashboard.monthlyPace': 'Monthly pace',
  'settings.costDashboard.budgetLimit': 'Budget limit',
  'settings.costDashboard.utilization': 'Utilisation',
  'settings.costDashboard.modelBreakdown': 'Per-model breakdown',
  'settings.costDashboard.model': 'Model',
  'settings.costDashboard.provider': 'Provider',
  'settings.costDashboard.cost': 'Cost',
  'settings.costDashboard.tokens': 'Tokens',
  'settings.costDashboard.requests': 'Requests',
  'settings.costDashboard.percentOfTotal': '% of total',
  'settings.costDashboard.inputTokens': 'Input',
  'settings.costDashboard.outputTokens': 'Output',
  'settings.costDashboard.budgetNormal': 'On track',
  'settings.costDashboard.budgetWarning': 'Warning',
  'settings.costDashboard.budgetExceeded': 'Over budget',
  'settings.costDashboard.noBudget': 'No limit set',
  'settings.costDashboard.noData': 'No cost recorded yet for the last 7 days.',
  'settings.costDashboard.noModels': 'No model activity in the last 7 days.',
  'settings.costDashboard.loading': 'Loading cost dashboard…',
  'settings.costDashboard.disabledHint':
    'Cost dashboard is disabled in config. Set [cost.dashboard] enabled = true in config.toml to re-enable.',
  'settings.costDashboard.subtitle':
    'Live spend and token burn across the swarm. Bars auto-refresh every few seconds — no page reload needed.',
  'settings.costDashboard.summaryAriaLabel': 'Cost summary metrics',
  'settings.costDashboard.lastSevenDays': 'last 7 days',
  'settings.costDashboard.utilizationOf': 'of',
  'settings.costDashboard.thisMonth': 'this month',
  'settings.costDashboard.monthlyPaceHint':
    'Projected monthly spend at the current daily run-rate (avg × 30).',
  'settings.costDashboard.budgetLimitHint':
    'Monthly budget read from cost.monthly_limit_usd in config.toml.',
  'settings.costDashboard.dailyTarget': 'Daily target',
  'settings.costDashboard.today': 'Today',
  'settings.costDashboard.todayBadge': 'TODAY',
  'settings.costDashboard.unknownProvider': '—',
  'settings.costDashboard.justNow': 'Just now',
  'settings.costDashboard.secondsAgo': '{value}s ago',
  'settings.costDashboard.minutesAgo': '{value}m ago',
  'settings.costDashboard.hoursAgo': '{value}h ago',
  'settings.costDashboard.daysAgo': '{value}d ago',
  'settings.costDashboard.updated': 'Updated',
  'settings.costDashboard.refresh': 'Refresh',
  'settings.costDashboard.utcNote': 'Days bucketed in UTC',
  'settings.costDashboard.stackedNote': 'Input + output stacked',
  'settings.costDashboard.modelBreakdownHint': 'Aggregated across the last 7 days.',
  'settings.costDashboard.categoryDistribution': 'Spend by category',
  'settings.costDashboard.categoryDistributionHint':
    'Inferred from recent usage records across chat, embeddings, voice, image, and reranking calls.',
  'settings.costDashboard.noCategories': 'No category spend recorded yet.',
  'settings.costDashboard.categoryMeta': '{requests} requests • {tokens} tokens',
  'settings.costDashboard.usageLog': 'Usage log',
  'settings.costDashboard.usageLogHint':
    'Newest records from the last {days} days, capped at {limit} rows.',
  'settings.costDashboard.logTotal': '{requests} requests • {cost}',
  'settings.costDashboard.noUsageLog': 'No usage records found for this period.',
  'settings.costDashboard.when': 'When',
  'settings.costDashboard.category': 'Category',
  'settings.costDashboard.session': 'Session',
  'settings.costDashboard.noDataHint':
    'Send an agent message — token usage from the next provider call will populate the chart within ~10 seconds.',
  'settings.search.title': 'Search engine',
  'settings.search.menuDesc':
    'Default to OpenHuman-managed search or wire up your own provider with an API key.',
  'settings.search.description':
    "Pick the search engine the agent uses, or disable search tools entirely. Managed uses OpenHuman's backend (no setup). Parallel, Brave, and Querit run direct from your machine using your API key.",
  'settings.search.engineAria': 'Search engine',
  'settings.search.engineDisabledLabel': 'Disabled',
  'settings.search.engineDisabledDesc':
    'Remove search tools from the agent context and available tool list.',
  'settings.search.engineManagedLabel': 'OpenHuman Managed',
  'settings.search.engineManagedDesc':
    'Default. Routed through the OpenHuman backend — no API key required.',
  'settings.search.localManagedUnavailable':
    'OpenHuman Managed search is not available for local users. Add your own Parallel, Brave, or Querit API key to enable web search.',
  'settings.search.engineParallelLabel': 'Parallel',
  'settings.search.engineParallelDesc':
    'Direct Parallel API: search, extract, chat, research, enrich, dataset tools.',
  'settings.search.engineBraveLabel': 'Brave Search',
  'settings.search.engineBraveDesc': 'Direct Brave Search API: web, news, image, and video tools.',
  'settings.search.engineQueritLabel': 'Querit',
  'settings.search.engineQueritDesc':
    'Direct Querit API: web search with site, time range, country, and language filters.',
  'settings.search.statusConfigured': 'Configured',
  'settings.search.statusNeedsKey': 'Needs API key',
  'settings.search.fallbackToManaged':
    'No key configured — search will fall back to Managed until a key is saved.',
  'settings.search.getApiKey': 'Get API key',
  'settings.search.save': 'Save',
  'settings.search.clear': 'Clear',
  'settings.search.show': 'Show',
  'settings.search.hide': 'Hide',
  'settings.search.statusSaving': 'Saving…',
  'settings.search.statusSaved': 'Saved.',
  'settings.search.statusError': 'Failed',
  'settings.search.parallelKeyLabel': 'Parallel API key',
  'settings.search.braveKeyLabel': 'Brave Search API key',
  'settings.search.queritKeyLabel': 'Querit API key',
  'settings.search.placeholderStored': '•••••••• (stored)',
  'settings.search.placeholderParallel': 'pk_...',
  'settings.search.placeholderBrave': 'BSA...',
  'settings.search.placeholderQuerit': 'Querit API key',
  'settings.search.allowedSitesLabel': 'Allowed websites',
  'settings.search.allowedSitesHint':
    'Hosts the assistant may open and read — via web fetch and the browser tool — one per line, e.g. reuters.com. A host also covers its subdomains. Web search itself is not restricted by this list.',
  'settings.search.allowedSitesAllOn':
    'The assistant can open any public website. Local and private addresses stay blocked.',
  'settings.search.allowedSitesPlaceholder': 'reuters.com\napnews.com\ngithub.com',
  'settings.search.allowedSitesSave': 'Save websites',
  'settings.search.accessModeAria': 'Web access mode',
  'settings.search.accessAllowAll': 'Allow all',
  'settings.search.accessCustom': 'Custom',
  'settings.search.accessBlockAll': 'Block all',
  'settings.search.accessBlockAllHint':
    'All web access is blocked — the assistant cannot open or read any website.',
  // ─── Settings global search bar ────────────────────────────
  'settings.settingsSearch.placeholder': 'Search settings…',
  'settings.settingsSearch.ariaLabel': 'Search settings',
  'settings.settingsSearch.clear': 'Clear search',
  'settings.settingsSearch.resultsLabel': 'Search results',
  'settings.settingsSearch.noResults': 'No settings found for “{query}”',
  // ─── Embeddings settings ───────────────────────────────────
  'settings.embeddings.title': 'Embeddings',
  'settings.embeddings.description':
    'Choose which embedding provider converts memory into vectors for semantic search. Changing the provider, model, or dimensions invalidates stored vectors and requires a full memory reset.',
  'settings.embeddings.providerAria': 'Embedding provider',
  'settings.embeddings.statusConfigured': 'Configured',
  'settings.embeddings.statusNeedsKey': 'Needs API key',
  'settings.embeddings.requiresSignIn': 'Requires OpenHuman sign-in',
  'settings.embeddings.managedLoginRequired':
    'Managed embeddings require OpenHuman sign-in. Sign in to use the OpenHuman backend.',
  'settings.embeddings.managedBannerIntro':
    'Managed embeddings route through the OpenHuman backend and require an OpenHuman account session.',
  'settings.embeddings.managedBannerLocalSession':
    'Exit local session and sign in to use this provider, or switch to a local or bring-your-own embeddings provider.',
  'settings.embeddings.managedBannerRemoteSession':
    'Sign in again to refresh your OpenHuman session, or switch to a local or bring-your-own embeddings provider.',
  'settings.embeddings.signInAgain': 'Sign in again',
  'settings.embeddings.apiKeyLabel': '{provider} API key',
  'settings.embeddings.placeholderStored': '•••••••• (stored)',
  'settings.embeddings.placeholderKey': 'Paste your API key…',
  'settings.embeddings.keyStoredEncrypted': 'Your API key is stored encrypted on this device.',
  'settings.embeddings.show': 'Show',
  'settings.embeddings.hide': 'Hide',
  'settings.embeddings.save': 'Save',
  'settings.embeddings.clear': 'Clear',
  'settings.embeddings.model': 'Model',
  'settings.embeddings.dimensions': 'Dimensions',
  'settings.embeddings.customEndpoint': 'Custom endpoint',
  'settings.embeddings.customModelPlaceholder': 'Model name',
  'settings.embeddings.customDimsPlaceholder': 'Dims',
  'settings.embeddings.applyCustom': 'Apply',
  'settings.embeddings.testConnection': 'Test connection',
  'settings.embeddings.testing': 'Testing…',
  'settings.embeddings.testSuccess': 'Connected — {dims} dimensions',
  'settings.embeddings.connectionTestFailed': 'Test failed',
  'settings.embeddings.verifyFallback':
    "Couldn't verify the embeddings endpoint. Make sure it's running and serving an embedding model, then save again.",
  'settings.embeddings.testFailed': 'Failed: {error}',
  'settings.embeddings.saving': 'Saving…',
  'settings.embeddings.saved': 'Saved.',
  'settings.embeddings.errorPrefix': 'Failed',
  'settings.embeddings.wipeTitle': 'Reset memory vectors?',
  'settings.embeddings.wipeBody':
    'Switching embedding provider, model, or dimensions will erase all stored memory vectors. Memory must be rebuilt before recall works again. This cannot be undone.',
  'settings.embeddings.cancel': 'Cancel',
  'settings.embeddings.confirmWipe': 'Wipe & apply',
  'settings.embeddings.setupTitle': 'Set up {provider}',
  'settings.embeddings.saveAndSwitch': 'Save & switch',
  'settings.embeddings.optional': 'optional',
  'settings.embeddings.vectorSearchDisabled':
    'Vector search is disabled. Memory recall will use keyword matching and recency only — no semantic ranking.',
  'settings.embeddings.clearKey': 'Clear API key',
  'pages.settings.ai.embeddings': 'Embeddings',
  'pages.settings.ai.embeddingsDesc': 'Vector encoding model for memory retrieval',

  'mcp.alphaBadge': 'Alpha',
  'mcp.alphaBannerText':
    'MCP server support is in early alpha. The registry, install flow, and tool wiring may change between releases.',
  'mcp.toolList.noTools': 'No tools available.',
  'mcp.setup.secretDialog.title': 'MCP Setup — Enter Secret',
  'mcp.setup.secretDialog.bodyPrefix': 'The MCP setup agent needs',
  'mcp.setup.secretDialog.bodySuffix':
    '. Your value is sent directly to the core process and never enters the AI conversation.',
  'mcp.setup.secretDialog.inputLabel': 'Value',
  'mcp.setup.secretDialog.inputPlaceholder': 'Paste here',
  'mcp.setup.secretDialog.show': 'Show',
  'mcp.setup.secretDialog.hide': 'Hide',
  'mcp.setup.secretDialog.submit': 'Submit',
  'mcp.setup.secretDialog.cancel': 'Cancel',
  'mcp.setup.secretDialog.submitting': 'Submitting…',
  'mcp.setup.secretDialog.errorPrefix': 'Failed to submit:',
  'mcp.setup.secretDialog.privacyNote':
    'Stored encrypted in the local MCP secrets table. Never logged or sent to a model.',
  'devices.betaBadge': 'Beta',
  'devices.betaText':
    'This feature is currently in beta. Pair iOS phones with this OpenHuman to use them as a remote client.',
  'devices.comingSoonDescription':
    'Device pairing is coming soon. This page will be the home for pairing iPhones and managing connected devices.',
  'devices.title': 'Devices',
  'devices.pairIphone': 'Pair iPhone',
  'devices.noPaired': 'No paired devices',
  'devices.emptyState': 'Scan a QR code on your iPhone to connect it to this OpenHuman session.',
  'devices.devicePairedTitle': 'Device paired',
  'devices.devicePairedMessage': 'iPhone connected successfully.',
  'devices.deviceRevokedTitle': 'Device revoked',
  'devices.deviceRevokedMessage': '{label} removed.',
  'devices.revokeFailedTitle': 'Revoke failed',
  'devices.online': 'Online',
  'devices.offline': 'Offline',
  'devices.lastSeenNever': 'Never',
  'devices.lastSeenNow': 'Just now',
  'devices.lastSeenMinutes': '{count}m ago',
  'devices.lastSeenHours': '{count}h ago',
  'devices.lastSeenDays': '{count}d ago',
  'devices.revoke': 'Revoke',
  'devices.revokeAria': 'Revoke {label}',
  'devices.confirmRevokeTitle': 'Revoke device?',
  'devices.confirmRevokeBody': '{label} will no longer be able to connect. This cannot be undone.',
  'devices.loadFailed': 'Failed to load devices: {message}',
  'devices.pairModal.title': 'Pair iPhone',
  'devices.pairModal.loading': 'Generating pairing code…',
  'devices.pairModal.instructions': 'Open the OpenHuman app on your iPhone and scan this code.',
  'devices.pairModal.expiresIn': 'Code expires in ~{count} minute',
  'devices.pairModal.expiresInPlural': 'Code expires in ~{count} minutes',
  'devices.pairModal.showDetails': 'Show details',
  'devices.pairModal.hideDetails': 'Hide details',
  'devices.pairModal.channelId': 'Channel ID',
  'devices.pairModal.pairingUrl': 'Pairing URL',
  'devices.pairModal.expiredTitle': 'QR code expired',
  'devices.pairModal.expiredBody': 'Generate a new code to continue pairing.',
  'devices.pairModal.generateNewCode': 'Generate new code',
  'devices.pairModal.successTitle': 'Paired with iPhone',
  'devices.pairModal.autoClose': 'Closing automatically…',
  'devices.pairModal.errorPrefix': 'Failed to create pairing: {message}',
  'devices.pairModal.errorTitle': 'Something went wrong',
  'devices.pairModal.copyUrl': 'Copy',
  'mcp.catalog.searchAria': 'Search MCP server catalog',
  'mcp.catalog.searchPlaceholder': 'Search MCP servers...',
  'mcp.catalog.loadFailed': 'Failed to load catalog',
  'mcp.catalog.noResults': 'No servers found.',
  'mcp.catalog.noResultsFor': 'No servers found for "{query}".',
  'mcp.catalog.loadMore': 'Load more',
  'mcp.configAssistant.title': 'Configuration assistant',
  'mcp.configAssistant.empty': 'Ask about configuration, required env vars, or setup steps.',
  'mcp.configAssistant.autoPromptCta': 'Get step-by-step setup help',
  'mcp.configAssistant.suggestedValues': 'Suggested values:',
  'mcp.configAssistant.valueHidden': '(value hidden)',
  'mcp.configAssistant.applySuggested': 'Apply suggested values',
  'mcp.configAssistant.reinstallHint': 'Re-install with these values to apply them.',
  'mcp.configAssistant.thinking': 'Thinking...',
  'mcp.configAssistant.inputPlaceholder': 'Ask a question (Enter to send, Shift+Enter for newline)',
  'mcp.configAssistant.send': 'Send',
  'mcp.configAssistant.failedResponse': 'Failed to get response',
  'mcp.toolList.availableSingular': '{count} tool available',
  'mcp.toolList.availablePlural': '{count} tools available',
  'mcp.toolList.tryTool': 'Try',
  'mcp.toolList.tryToolAria': 'Open execution playground for {name}',
  'mcp.playground.title': 'Run {name}',
  'mcp.playground.close': 'Close playground',
  'mcp.playground.inputSchema': 'Input schema',
  'mcp.playground.argsLabel': 'Arguments (JSON)',
  'mcp.playground.argsHelp': 'Type JSON matching the input schema. Empty input is treated as {}.',
  'mcp.playground.runShortcut': '⌘/Ctrl + Enter to run',
  'mcp.playground.format': 'Format',
  'mcp.playground.invalidJson': 'Invalid JSON',
  'mcp.playground.run': 'Run tool',
  'mcp.playground.running': 'Running…',
  'mcp.playground.result': 'Result',
  'mcp.playground.resultError': 'Tool returned an error',
  'mcp.playground.copyResult': 'Copy result',
  'mcp.playground.copied': 'Copied',
  'mcp.playground.history': 'History',
  'mcp.playground.historyEmpty': 'No invocations yet in this session.',
  'mcp.playground.historyLoad': 'Load',
  'mcp.playground.unexpectedError': 'Unexpected error invoking tool.',
  'mcp.catalog.deployed': 'Deployed',
  'mcp.catalog.installCount': '{count} installs',
  'app.update.dismissNotification': 'Dismiss update notification',
  'bootCheck.rpcAuthSuffix': 'on every RPC.',
  'app.localAiDownload.expandAria': 'Expand download progress',
  'app.localAiDownload.collapseAria': 'Collapse download progress',
  'app.localAiDownload.dismissAria': 'Dismiss download notification',
  'mobile.nav.ariaLabel': 'Mobile navigation',
  'progress.stepsAria': 'Progress steps',
  'progress.stepAria': 'Step {current} of {total}',
  'workspace.vaultsTitle': 'Knowledge vaults',
  'workspace.vaultsDesc': 'Point at a local folder; files are chunked and mirrored into memory.',
  'calls.title': 'Calls',
  'calls.comingSoonBody': 'AI-assisted calls are coming soon. Stay tuned.',
  'art.rotatingTetrahedronAria': 'Rotating inverted tetrahedron spacecraft',
  'mcp.installed.title': 'Installed',
  'mcp.installed.browseCatalog': 'Browse catalog',
  'mcp.installed.empty': 'No MCP servers installed yet.',
  'mcp.installed.toolSingular': '{count} tool',
  'mcp.installed.toolPlural': '{count} tools',
  'mcp.health.title': 'Health',
  'mcp.health.summaryAria': 'MCP connection health summary',
  'mcp.health.connectedCount': '{count} connected',
  'mcp.health.connectingCount': '{count} connecting',
  'mcp.health.errorCount': '{count} error',
  'mcp.health.disconnectedCount': '{count} idle',
  'mcp.health.retryAll': 'Retry all ({count})',
  'mcp.health.retryAllAria': 'Retry all {count} errored MCP servers',
  'mcp.health.disconnectAll': 'Disconnect all ({count})',
  'mcp.health.disconnectAllAria': 'Disconnect all {count} connected MCP servers',
  'mcp.health.disconnectConfirm.title': 'Disconnect all MCP servers?',
  'mcp.health.disconnectConfirm.body':
    'This will disconnect {count} currently-connected MCP servers. Installed configurations and secrets are kept; you can reconnect any server later.',
  'mcp.health.disconnectConfirm.cancel': 'Cancel',
  'mcp.health.disconnectConfirm.confirm': 'Disconnect all',
  'mcp.health.opErrorGeneric': 'Bulk operation failed. See logs.',
  'mcp.health.bulkPartialFailure': '{failed} of {total} servers failed. See logs.',
  'mcp.installed.search.landmarkAria': 'Search installed MCP servers',
  'mcp.installed.search.inputAria': 'Filter installed MCP servers by name',
  'mcp.installed.search.placeholder': 'Filter servers…',
  'mcp.installed.search.clearAria': 'Clear filter',
  'mcp.installed.search.countMatches': '{shown} of {total} servers',
  'mcp.installed.search.noMatches': 'No servers match "{query}".',
  'mcp.inventory.openButton': 'Inventory',
  'mcp.inventory.openAria': 'Open the sharable MCP inventory panel',
  'mcp.inventory.title': 'Sharable MCP Inventory',
  'mcp.inventory.subtitle':
    'Export your installed MCP servers as a portable, secret-free manifest, or import one from a teammate. Secret env values are never included or imported.',
  'mcp.inventory.close': 'Close inventory panel',
  'mcp.inventory.tablistAria': 'Inventory sections',
  'mcp.inventory.tab.export': 'Export',
  'mcp.inventory.tab.import': 'Import',
  'mcp.inventory.export.empty':
    'No MCP servers installed yet — nothing to export. Install one from the catalog first.',
  'mcp.inventory.export.privacyTitle': 'What is in this manifest',
  'mcp.inventory.export.privacyBody':
    'Server names, qualified names, env-variable KEY NAMES, and non-secret config only. Secret values, your machine identifiers, and per-install timestamps are intentionally stripped.',
  'mcp.inventory.export.serverCount': '{count} servers in this manifest',
  'mcp.inventory.export.copy': 'Copy',
  'mcp.inventory.export.copied': 'Copied',
  'mcp.inventory.export.copyAria': 'Copy the manifest JSON to the clipboard',
  'mcp.inventory.export.download': 'Download',
  'mcp.inventory.export.downloadAria': 'Download the manifest as a JSON file',
  'mcp.inventory.import.trustTitle': 'Treat imported manifests as untrusted code',
  'mcp.inventory.import.trustBody':
    'An MCP server is a tool you grant your agent. Only import manifests from sources you trust. Each install requires your explicit click; nothing is auto-installed.',
  'mcp.inventory.import.pasteLabel': 'Paste manifest JSON',
  'mcp.inventory.import.pastePlaceholder': 'Paste a manifest here, or upload a .json file below.',
  'mcp.inventory.import.preview': 'Preview',
  'mcp.inventory.import.clear': 'Clear',
  'mcp.inventory.import.uploadFile': 'or upload a .json file',
  'mcp.inventory.import.uploadFileAria': 'Upload a manifest .json file',
  'mcp.inventory.import.fileTooLarge': 'File is too large (over 1 MB). Refusing to load.',
  'mcp.inventory.import.fileReadFailed': 'Could not read file.',
  'mcp.inventory.import.parseErrorPrefix': 'Could not parse manifest:',
  'mcp.inventory.import.previewHeading': 'Preview',
  'mcp.inventory.import.previewCounts':
    '{total} servers — {newly} new, {already} already installed',
  'mcp.inventory.import.previewEmpty': 'Manifest contains no servers.',
  'mcp.inventory.import.exportedFrom': 'Exported from {exporter}',
  'mcp.inventory.import.exportedAt': 'at {when}',
  'mcp.inventory.import.statusNew': 'New',
  'mcp.inventory.import.statusAlreadyInstalled': 'Already installed',
  'mcp.inventory.import.envKeysLabel': 'Env keys',
  'mcp.inventory.import.install': 'Install',
  'mcp.inventory.import.installAria': 'Install {name} from this manifest',
  'mcp.inventory.import.skipped': 'skipped',
  'mcp.inventory.parseError.empty': 'Manifest is empty.',
  'mcp.inventory.parseError.invalidJson': 'Invalid JSON.',
  'mcp.inventory.parseError.rootNotObject': 'Manifest must be a JSON object at the root.',
  'mcp.inventory.parseError.unsupportedSchema':
    'Unsupported manifest schema — this file was not produced by a compatible exporter.',
  'mcp.inventory.parseError.missingExportedAt': 'Missing or invalid `exported_at` field.',
  'mcp.inventory.parseError.missingExportedBy': 'Missing or invalid `exported_by` field.',
  'mcp.inventory.parseError.invalidServers': 'Missing or invalid `servers` array.',
  'mcp.inventory.parseError.serverNotObject': 'A server entry is not an object.',
  'mcp.inventory.parseError.serverMissingQualifiedName':
    'A server entry is missing its qualified_name.',
  'mcp.inventory.parseError.serverMissingDisplayName':
    'A server entry is missing its display_name.',
  'mcp.inventory.parseError.serverEnvKeysNotArray':
    'A server entry has an env_keys field that is not an array of strings.',
  'mcp.inventory.parseError.serverContainsEnv':
    'A server entry contains an `env` value map. Refusing to import — manifests must only carry env_keys (names), never secret values.',
  'mcp.inventory.parseError.duplicateQualifiedName':
    'Duplicate qualified_name found in manifest. Each server must appear at most once.',
  'mcp.tab.loading': 'Loading MCP servers...',
  'mcp.tab.emptyDetail': 'Select a server or browse the catalog.',
  'mcp.tab.filter.all': 'All',
  'mcp.tab.filter.installed': 'Installed ({count})',
  'mcp.tab.filter.registry': 'Registry',
  'mcp.tab.column.name': 'Name',
  'mcp.tab.column.description': 'Description',
  'mcp.tab.column.type': 'Type',
  'mcp.tab.column.author': 'Author',
  'mcp.tab.column.action': 'Action',
  'mcp.tab.transport.hosted': 'Hosted',
  'mcp.tab.transport.local': 'Stdio',
  'mcp.tab.transport.hostedHint':
    'Runs on a remote server — sign-in or token is set up when you install',
  'mcp.tab.transport.localHint': 'Runs on your device — may need a token when you install',
  'mcp.tab.transportFilter.label': 'Type',
  'mcp.tab.transportFilter.aria': 'Filter servers by transport',
  'mcp.tab.link.website': 'Website',
  'mcp.tab.link.repo': 'Repository',
  'mcp.tab.officialBadge': 'Official',
  'mcp.tab.officialHint': 'Official server from the vendor',
  'mcp.tab.badge.installed': 'Installed',
  'mcp.tab.badge.registry': 'Registry',
  'mcp.tab.action.manage': 'Manage',
  'mcp.tab.aria.viewDetails': 'View details for {name}',
  'mcp.tab.aria.installServer': 'Install {name}',
  'mcp.install.loadingDetail': 'Loading server details...',
  'mcp.install.back': 'Go back',
  'mcp.install.title': 'Install {name}',
  'mcp.install.requiredEnv': 'Required environment variables',
  'mcp.install.enterValue': 'Enter {key}',
  'mcp.install.show': 'Show',
  'mcp.install.hide': 'Hide',
  'mcp.install.configLabel': 'Config (optional JSON)',
  'mcp.install.configPlaceholder': '{"key": "value"}',
  'mcp.install.missingRequired': '"{key}" is required',
  'mcp.install.invalidJson': 'Config JSON is not valid JSON',
  'mcp.install.failedDetail': 'Failed to load server details',
  'mcp.install.failedInstall': 'Install failed',
  'mcp.install.button': 'Install',
  'mcp.install.installing': 'Installing...',
  'mcp.install.by': 'by',
  'mcp.install.useCount': '{count} installs',
  'mcp.install.connections': 'Available connections',
  'mcp.install.published': 'published',
  'mcp.install.configureAndInstall': 'Configure & install',
  'mcp.install.configureTitle': 'Configure {name}',
  'mcp.install.advancedConfig': 'Advanced configuration',
  'mcp.detail.suggestedEnvReady': 'Suggested environment values ready',
  'mcp.detail.suggestedEnvBody':
    'Re-install this server with the suggested values to apply them: {keys}',
  'mcp.detail.connect': 'Connect',
  'mcp.detail.connecting': 'Connecting...',
  'mcp.detail.authenticate': 'Sign in',
  'mcp.detail.authRequired':
    'This server needs you to sign in or add an access token before it can connect. Click “Sign in” to authenticate.',
  'mcp.detail.disconnect': 'Disconnect',
  'mcp.detail.hideAssistant': 'Hide assistant',
  'mcp.detail.helpConfigure': 'Help me configure',
  'mcp.detail.confirmUninstall': 'Confirm uninstall?',
  'mcp.detail.confirmUninstallAction': 'Yes, uninstall',
  'mcp.detail.uninstall': 'Uninstall',
  'mcp.detail.envVars': 'Environment variables',
  'mcp.detail.reconfigure': 'Reconfigure',
  'mcp.detail.reconfigureHint':
    'Enter new values for every variable, then reconnect. This replaces the stored values.',
  'mcp.detail.saveReconnect': 'Save & reconnect',
  'mcp.detail.reconfigureSaving': 'Saving…',
  'mcp.detail.reconfigureSuccess': 'Environment updated and reconnected.',
  'mcp.detail.reconfigureReconnectFailed': 'Saved, but reconnecting with the new values failed.',
  'mcp.connectAuth.title': 'Connect {name}',
  'mcp.connectAuth.hint':
    'Add any authentication this server needs, then connect. Tokens are stored encrypted. Leave blank for servers that need no auth.',
  'mcp.connectAuth.requiredLabel': 'Required',
  'mcp.connectAuth.customHeadersLabel': 'Custom headers',
  'mcp.connectAuth.customHeadersEmpty':
    'No custom headers. Add one if this server needs an auth header the registry did not declare.',
  'mcp.connectAuth.addHeader': '+ Add header',
  'mcp.connectAuth.headerName': 'Header name',
  'mcp.connectAuth.headerValue': 'Value',
  'mcp.connectAuth.removeHeader': 'Remove header',
  'mcp.connectAuth.howToGetToken': 'Help & configure',
  'mcp.connectAuth.tokenProvider': 'Get your token from:',
  'mcp.connectAuth.findToken': 'Where do I get the token?',
  'mcp.connectAuth.hideHelp': 'Hide help',
  'mcp.connectAuth.schemeLabel': 'How to send the value',
  'mcp.connectAuth.schemeBearer': 'Bearer',
  'mcp.connectAuth.schemeRaw': 'None',
  'mcp.connectAuth.reconnectFailed': 'Saved the credentials, but connecting failed.',
  'mcp.connectAuth.oauthHint':
    'This server uses OAuth. Sign in through your browser to authorize OpenHuman.',
  'mcp.connectAuth.signIn': 'Sign in with browser',
  'mcp.connectAuth.oauthWaiting': 'Waiting for sign-in…',
  'mcp.connectAuth.oauthOrToken':
    'Already have an access token? Paste it as an Authorization header below instead.',
  'mcp.connectAuth.oauthTimeout': 'Timed out waiting for browser sign-in. Try again.',
  'mcp.connectAuth.authError.oauthRequired':
    'This server uses OAuth. Use “Sign in with browser” — a pasted token will not be accepted.',
  'mcp.connectAuth.authError.tokenRejected':
    'The server rejected this token. Check that it is correct and has not expired.',
  'mcp.connectAuth.authError.credentialRequired':
    'This server requires authentication. Add a token, or sign in.',
  'mcp.detail.enable': 'Enable',
  'mcp.detail.disable': 'Disable',
  'mcp.status.disabled': 'Disabled',
  'mcp.status.unauthorized': 'Sign in needed',
  'mcp.detail.tools': 'Tools',
  'onboarding.skipForNow': 'Skip for Now',
  'onboarding.localAI.continueWithCloud': 'Continue with Cloud',
  'onboarding.localAI.useLocalAnyway': 'Use local AI anyway (not recommended for your device)',
  'onboarding.localAI.useLocalInstead': 'Use local AI instead (connect Ollama now)',
  'onboarding.localAI.setupIssue': 'Local AI setup encountered an issue',
  'autonomy.title': 'Agent autonomy',
  'autonomy.maxActionsLabel': 'Max actions per hour',
  'autonomy.maxActionsHelp':
    'Maximum tool actions an agent can run per rolling hour. New value applies to your next chat. Cron jobs and channel listeners keep their current limit until you restart OpenHuman.',
  'autonomy.statusSaving': 'Saving…',
  'autonomy.statusSaved': 'Saved.',
  'autonomy.statusFailed': 'Failed',
  'autonomy.unlimitedNote': 'Unlimited — rate limiting disabled.',
  'autonomy.invalidIntegerMsg':
    'Must be a positive integer (use the Unlimited preset for no limit).',
  'autonomy.presetUnlimited': 'Unlimited (default)',
  'triggers.toggleFailed': '{action} failed for {trigger}: {message}',

  // Settings: AI
  'settings.ai.overview': 'AI System Overview',
  'settings.ai.configStatus': 'Configuration Status',
  'settings.ai.fallbackMode': 'Fallback Mode',
  'settings.ai.loadedFromRuntime': 'Loaded from Runtime',
  'settings.ai.loadingDuration': 'Loading Duration',
  'settings.ai.localRuntime': 'Local Model Runtime',
  'settings.ai.openManager': 'Open Manager',
  'settings.ai.retryDownload': 'Retry Download',
  'settings.ai.state': 'State',
  'settings.ai.targetModel': 'Target Model',
  'settings.ai.download': 'Download',
  'settings.ai.localModelUnavailable': 'Local model status unavailable.',
  'settings.ai.soulConfig': 'SOUL Persona Configuration',
  'settings.ai.refreshing': 'Refreshing...',
  'settings.ai.refreshSoul': 'Refresh SOUL',
  'settings.ai.loadingSoul': 'Loading SOUL configuration...',
  'settings.ai.identity': 'Identity',
  'settings.ai.personality': 'Personality',
  'settings.ai.safetyRules': 'Safety Rules',
  'settings.ai.source': 'Source',
  'settings.ai.loaded': 'Loaded',
  'settings.ai.toolsConfig': 'TOOLS Configuration',
  'settings.ai.refreshTools': 'Refresh TOOLS',
  'settings.ai.toolsAvailable': 'Tools Available',
  'settings.ai.tools': 'tools',
  'settings.ai.activeSkills': 'Active Skills',
  'settings.ai.skills': 'skills',
  'settings.ai.skillsOverview': 'Skills Overview',
  'settings.ai.refreshingAll': 'Refreshing All...',
  'settings.ai.refreshAll': 'Refresh All AI Configuration',

  // Settings: Notifications
  'settings.notifications.suppressAll': 'Suppress all notifications',
  'settings.notifications.suppressAllDesc':
    'Block all OS notification toasts from embedded apps regardless of focus state.',
  'settings.notifications.toggleDnd': 'Toggle Do Not Disturb',
  'settings.notifications.categories': 'Categories',
  'settings.notifications.categoryFooter':
    'Disabling a category stops new notifications of that type from appearing in the notification center. Existing notifications remain until cleared.',

  // Settings: Billing
  'settings.billing.movedToWeb': 'Billing moved to the web',
  'settings.billing.openDashboard': 'Open billing dashboard',
  'settings.billing.movedToWebDesc':
    'Subscription changes, payment methods, credits, and invoices are now managed at TinyHumans on the web.',
  'settings.billing.backToSettings': 'Back to settings',
  'settings.billing.openingBrowser': 'Opening your browser...',
  'settings.billing.browserNotOpen': 'If your browser did not open, use the button above.',
  'settings.billing.browserOpenFailed':
    'The browser could not be opened automatically. Use the button above.',

  // Settings: Tools
  'settings.tools.chooseCapabilities':
    'Choose which capabilities OpenHuman can use on your behalf.',
  'settings.tools.saveChanges': 'Save Changes',
  'settings.tools.preferencesSaved': 'Preferences saved',
  'settings.tools.saveFailed': 'Failed to save preferences. Try again.',

  // Settings: Screen Awareness
  'settings.screenAwareness.mode': 'Mode',
  'settings.screenAwareness.allExceptBlacklist': 'All Except Blacklist',
  'settings.screenAwareness.whitelistOnly': 'Whitelist Only',
  'settings.screenAwareness.screenMonitoring': 'Screen Monitoring',
  'settings.screenAwareness.saveSettings': 'Save Settings',
  'settings.screenAwareness.session': 'Session',
  'settings.screenAwareness.status': 'Status',
  'settings.screenAwareness.active': 'Active',
  'settings.screenAwareness.stopped': 'Stopped',
  'settings.screenAwareness.remaining': 'Remaining',
  'settings.screenAwareness.startSession': 'Start Session',
  'settings.screenAwareness.stopSession': 'Stop Session',
  'settings.screenAwareness.analyzeNow': 'Analyze Now',
  'settings.screenAwareness.macosOnly':
    'Screen Awareness desktop capture and permission controls are currently supported on macOS only.',

  // Connections
  'connections.comingSoon': 'Coming soon',
  'connections.setUp': 'Set up',
  'connections.configured': 'Configured',
  'connections.unavailable': 'Unavailable',
  'connections.checking': 'Checking…',
  'connections.walletConfigured':
    'Local EVM, BTC, Solana, and Tron identities are configured from your recovery phrase.',
  'connections.walletReady':
    'Set up local EVM, BTC, Solana, and Tron identities from one recovery phrase.',
  'connections.walletError':
    'Could not check wallet status. Tap to retry from the Recovery Phrase panel.',
  'connections.walletChecking': 'Checking wallet status...',
  'connections.walletIdentities': 'Wallet identities',
  'connections.walletDerived':
    'Derived locally from your recovery phrase and stored as safe metadata only.',
  'connections.privacySecurity': 'Privacy & Security',
  'connections.privacySecurityDesc':
    'All data and credentials are stored locally with zero-data retention policy. Your information is encrypted and never shared with third parties.',

  // Channels
  'channels.status.connecting': 'Connecting',
  'channels.status.notConfigured': 'Not configured',
  'channels.noActiveRoute': 'No active route',
  'channels.activeRoute': 'Active route',
  'channels.loadingDefinitions': 'Loading channel definitions...',
  'channels.channelConnections': 'Channel Connections',
  'channels.configureAuthModes': 'Configure auth modes for each messaging channel.',
  'channels.configNotAvailable': 'Configuration for',
  'channels.channel': 'channel',

  // Dev Options
  'devOptions.coreModeNotSet': 'Core mode: not set',
  'devOptions.coreModeNotSetDesc':
    "The boot-check picker hasn't been confirmed yet. Use Switch mode on the picker to choose Local or Cloud.",
  'devOptions.local': 'Local',
  'devOptions.embeddedCoreSidecar': 'Embedded core sidecar',
  'devOptions.sidecarSpawned': 'Spawned in-process by the Tauri shell on app launch.',
  'devOptions.cloud': 'Cloud',
  'devOptions.remoteCoreRpc': 'Remote core RPC',
  'devOptions.token': 'Token',
  'devOptions.tokenNotSet': 'not set — RPC will 401',
  'devOptions.triggerSentryTest': 'Trigger Sentry Test (staging)',
  'devOptions.triggerSentryTestDesc':
    'Fires a tagged error to verify the Sentry pipeline. Issue #1072 — remove after verification.',
  'devOptions.sendTestEvent': 'Send test event',
  'devOptions.sending': 'Sending…',
  'devOptions.eventSent': 'Event sent',
  'devOptions.sentryDisabled': '(no id — Sentry disabled in this build)',
  'devOptions.failed': 'Failed',
  'devOptions.appLogs': 'App logs',
  'devOptions.appLogsDesc':
    'Open the folder containing rolling daily log files. Attach the most recent file when reporting an issue.',
  'devOptions.openLogsFolder': 'Open logs folder',

  // Mnemonic
  'mnemonic.phraseSaved': 'Recovery phrase saved',
  'mnemonic.walletReady': 'Multi-chain wallet identities are ready. Returning to settings...',
  'mnemonic.writeDownWords': 'Write down these',
  'mnemonic.wordsInOrder':
    'words in order and store them somewhere safe. This phrase secures your local encryption key and your EVM, BTC, Solana, and Tron wallet identities.',
  'mnemonic.cannotRecover':
    'This phrase can never be recovered if lost and should stay fully local to your device.',
  'mnemonic.copyToClipboard': 'Copy to Clipboard',
  'mnemonic.alreadyHavePhrase': 'I already have a recovery phrase',
  'mnemonic.consentSaved': 'I saved this phrase and consent to using it for local wallet setup',
  'mnemonic.enterPhraseToRestore':
    'Enter your recovery phrase below to restore your local wallet identities, or paste the full phrase into any field (12 words for new backups; 24-word phrases from older versions still work).',
  'mnemonic.words': 'Words',
  'mnemonic.validPhrase': 'Valid recovery phrase',
  'mnemonic.generateNewPhrase': 'Generate a new recovery phrase instead',
  'mnemonic.securingData': 'Securing Your Data...',
  'mnemonic.saveRecoveryPhrase': 'Save Recovery Phrase',
  'mnemonic.userNotLoaded': 'User not loaded. Please sign in again or refresh the page.',
  'mnemonic.invalidPhrase': 'Invalid recovery phrase. Please check your words and try again.',
  'mnemonic.somethingWentWrong': 'Something went wrong. Please try again.',
  'mnemonic.walletAlreadyConfigured': 'Your wallet is already set up.',
  'mnemonic.walletSource': 'Source',
  'mnemonic.walletWordCount': 'Recovery phrase length',
  'mnemonic.walletLastUpdated': 'Last updated',
  'mnemonic.replaceWallet': 'Replace wallet',
  'mnemonic.replaceWalletWarning':
    'This will permanently replace your current wallet. Make sure you have backed up your recovery phrase before proceeding.',
  'mnemonic.replaceWalletConfirm': 'I understand, replace my wallet',
  'mnemonic.loadingWalletStatus': 'Checking wallet status...',
  'mnemonic.viewAccounts': 'Wallet accounts',
  'mnemonic.revealRecoveryPhrase': 'Reveal recovery phrase',
  'mnemonic.hidePhrase': 'Hide phrase',

  // Team
  'team.failedToCreate': 'Failed to create team',
  'team.invalidInviteCode': 'Invalid or expired invite code',
  'team.failedToSwitch': 'Failed to switch team',
  'team.failedToLeave': 'Failed to leave team',
  'team.role.owner': 'Owner',
  'team.role.admin': 'Admin',
  'team.role.billingManager': 'Billing Manager',
  'team.role.member': 'Member',
  'team.active': 'Active',
  'team.personalTeam': 'Personal team',
  'team.manageTeam': 'Manage Team',
  'team.switching': 'Switching...',
  'team.switch': 'Switch',
  'team.leaving': 'Leaving...',
  'team.leave': 'Leave',
  'team.yourTeams': 'Your Teams',
  'team.createNewTeam': 'Create New Team',
  'team.teamName': 'Team name',
  'team.creating': 'Creating...',
  'team.joinExistingTeam': 'Join Existing Team',
  'team.personalAutoCreatedNote':
    'Your personal team is created automatically. To collaborate, join an existing team with an invite code below.',
  'team.inviteCode': 'Invite code',
  'team.joining': 'Joining...',
  'team.join': 'Join',
  'team.leaveTeam': 'Leave Team',
  'team.confirmLeave': 'Are you sure you want to leave',
  'team.leaveWarning':
    "You will lose access to the team and all team resources. You'll need a new invite to rejoin.",
  'team.management': 'Team Management',
  'team.notFound': 'Team not found',
  'team.accessDenied': 'Access denied',
  'team.members': 'Members',
  'team.membersDesc': 'Manage team members and roles',
  'team.invites': 'Invites',
  'team.invitesDesc': 'Generate and manage invite codes',
  'team.settings': 'Team Settings',
  'team.settingsDesc': 'Edit team name and settings',
  'team.editSettings': 'Edit Team Settings',
  'team.enterName': 'Enter team name',
  'team.saving': 'Saving...',
  'team.saveChanges': 'Save Changes',
  'team.delete': 'Delete Team',
  'team.deleteDesc': 'Permanently delete this team',
  'team.deleting': 'Deleting...',
  'team.failedToUpdate': 'Failed to update team',
  'team.failedToDelete': 'Failed to delete team',
  'team.manageTitle': 'Manage {name}',
  'team.planCreated': '{plan} Plan • Created {date}',
  'team.confirmDelete': 'Are you sure you want to delete {name}?',
  'team.deleteWarning': 'This action cannot be undone. All team data will be permanently removed.',

  // Voice
  'voice.title': 'Voice Dictation',
  'voice.settings': 'Voice Settings',
  'voice.settingsDesc': 'Hold the hotkey to dictate and insert text into the active field.',
  'voice.hotkey': 'Hotkey',
  'voice.activationMode': 'Activation Mode',
  'voice.tapToToggle': 'Tap to toggle',
  'voice.writingStyle': 'Writing Style',
  'voice.verbatimTranscription': 'Verbatim transcription',
  'voice.naturalCleanup': 'Natural cleanup',
  'voice.autoStart': 'Start voice server automatically with the core',
  'voice.customDictionary': 'Custom Dictionary',
  'voice.customDictionaryDesc':
    'Add names, technical terms, and domain words to improve recognition accuracy.',
  'voice.addWord': 'Add a word...',
  'voice.sttDisabled':
    'Voice dictation is disabled until the local STT model is downloaded and ready.',
  'voice.openLocalAiModel': 'Open Local AI Model',
  'voice.serverRestarted': 'Voice server restarted with the new settings.',
  'voice.settingsSaved': 'Voice settings saved.',
  'voice.serverStarted': 'Voice server started.',
  'voice.serverStopped': 'Voice server stopped.',
  'voice.saveVoiceSettings': 'Save Voice Settings',
  'voice.startVoiceServer': 'Start Voice Server',
  'voice.stopVoiceServer': 'Stop Voice Server',
  'voice.debugTitle': 'Voice Debug',
  'voice.failedToLoadSettings': 'Failed to load voice settings',
  'voice.failedToSaveSettings': 'Failed to save voice settings',
  'voice.failedToStartServer': 'Failed to start voice server',
  'voice.failedToStopServer': 'Failed to stop voice server',
  'voice.sttDisabledPrefix':
    'Voice dictation is disabled until the local STT model is downloaded. Use the',
  'voice.sttDisabledSuffix': 'section above to install Whisper.',
  'voice.debug.failedToLoadVoiceDebugData': 'Failed to load voice debug data',
  'voice.debug.settingsSaved': 'Debug settings saved.',
  'voice.debug.failedToSaveSettings': 'Failed to save voice settings',
  'voice.debug.runtimeStatus': 'Runtime Status',
  'voice.debug.runtimeStatusDesc':
    'Live diagnostics for the voice server and speech-to-text engine.',
  'voice.debug.server': 'Server',
  'voice.debug.unavailable': 'Unavailable',
  'voice.debug.ready': 'Ready',
  'voice.debug.notReady': 'Not ready',
  'voice.debug.hotkey': 'Hotkey',
  'voice.debug.notAvailable': 'n/a',
  'voice.debug.mode': 'Mode',
  'voice.debug.transcriptions': 'Transcriptions',
  'voice.debug.serverError': 'Server Error',
  'voice.debug.advancedSettings': 'Advanced Settings',
  'voice.debug.advancedSettingsDesc':
    'Low-level tuning parameters for recording and silence detection.',
  'voice.debug.minimumRecordingSeconds': 'Minimum Recording Seconds',
  'voice.debug.silenceThreshold': 'Silence Threshold (RMS)',
  'voice.debug.silenceThresholdDesc':
    'Recordings with energy below this are treated as silence and skipped. Lower = more sensitive.',
  'voice.debug.alwaysOn': 'Always-on listening',
  'voice.debug.alwaysOnDesc':
    'Keep the microphone open and send what you say to the agent automatically, no hotkey. Pauses when the screen is locked.',
  'voice.providers.saved': 'Voice providers saved.',
  'voice.providers.failedToSave': 'Failed to save voice providers',
  'voice.providers.ellipsis': '…',
  'voice.providers.installing': 'Installing',
  'voice.providers.installingBusy': 'Installing…',
  'voice.providers.reinstallLocally': 'Reinstall locally',
  'voice.providers.repair': 'Repair',
  'voice.providers.retryLocally': 'Retry locally',
  'voice.providers.installLocally': 'Install locally',
  'voice.providers.whisperReady': 'Whisper is ready.',
  'voice.providers.whisperInstallStarted': 'Whisper install started',
  'voice.providers.queued': 'queued',
  'voice.providers.failedToInstallWhisper': 'Failed to install Whisper',
  'voice.providers.piperReady': 'Piper is ready.',
  'voice.providers.piperInstallStarted': 'Piper install started',
  'voice.providers.failedToInstallPiper': 'Failed to install Piper',
  'voice.providers.title': 'Voice Providers',
  'voice.providers.desc':
    'Choose where transcription and synthesis run. Use the Install locally buttons to download the binaries and models into your workspace. Local providers can be saved before the install finishes — no manual WHISPER_BIN or PIPER_BIN setup required.',
  'voice.providers.sttProvider': 'Speech-to-Text Provider',
  'voice.providers.sttProviderAria': 'STT provider',
  'voice.providers.cloudWhisperProxy': 'OpenHuman (Managed)',
  'voice.providers.localWhisper': 'Local Whisper',
  'voice.providers.installRequired': ' (install required)',
  'voice.providers.whisperInstalledTitle': 'Whisper is installed. Click to reinstall.',
  'voice.providers.whisperDownloadTitle':
    'Download whisper.cpp and the GGML model into your workspace.',
  'voice.providers.installed': 'Installed',
  'voice.providers.installFailed': 'Install failed',
  'voice.providers.notInstalled': 'Not installed',
  'voice.providers.whisperModel': 'Whisper Model',
  'voice.providers.whisperModelAria': 'Whisper model',
  'voice.providers.whisperModelTiny': 'Tiny (39 MB, fastest)',
  'voice.providers.whisperModelBase': 'Base (74 MB)',
  'voice.providers.whisperModelSmall': 'Small (244 MB)',
  'voice.providers.whisperModelMedium': 'Medium (769 MB, recommended)',
  'voice.providers.whisperModelLargeTurbo': 'Large v3 Turbo (1.5 GB, best accuracy)',
  'voice.providers.ttsProvider': 'Text-to-Speech Provider',
  'voice.providers.ttsProviderAria': 'TTS provider',
  'voice.providers.cloudElevenLabsProxy': 'OpenHuman (Managed)',
  'voice.providers.localPiper': 'Local Piper',
  'voice.providers.piperInstalledTitle': 'Piper is installed. Click to reinstall.',
  'voice.providers.piperDownloadTitle':
    'Download Piper and the bundled en_US-lessac-medium voice into your workspace.',
  'voice.providers.piperVoice': 'Piper Voice',
  'voice.providers.piperVoiceAria': 'Piper voice',
  'voice.providers.customVoiceOption': 'Other (type below)…',
  'voice.providers.customVoiceAria': 'Piper voice id (custom)',
  'voice.providers.customVoicePlaceholder': 'en_US-lessac-medium',
  'voice.providers.piperVoicesDesc':
    'Voices come from huggingface.co/rhasspy/piper-voices. Switching voices may require an Install/Reinstall click to download the new .onnx.',
  'voice.providers.mascotVoice': 'Mascot Voice',
  'voice.providers.mascotVoiceDescPrefix':
    'The ElevenLabs voice the mascot uses for spoken replies is configured under',
  'voice.providers.mascotSettings': 'Mascot settings',
  'voice.providers.mascotVoiceDescSuffix': '.',
  'voice.providers.hotkeyPlaceholder': 'Fn',
  'voice.providers.piperPreset.lessacMedium': 'US · Lessac (neutral, recommended)',
  'voice.providers.piperPreset.lessacHigh': 'US · Lessac (higher quality, larger)',
  'voice.providers.piperPreset.ryanMedium': 'US · Ryan (male)',
  'voice.providers.piperPreset.amyMedium': 'US · Amy (female)',
  'voice.providers.piperPreset.librittsHigh': 'US · LibriTTS (multi-speaker)',
  'voice.providers.piperPreset.alanMedium': 'GB · Alan (male)',
  'voice.providers.piperPreset.jennyDiocoMedium': 'GB · Jenny Dioco (female)',
  'voice.providers.piperPreset.northernEnglishMaleMedium': 'GB · Northern English (male)',

  // Voice provider chips (new chip-toggle UI)
  'voice.providers.chip.cloud': 'OpenHuman (Managed)',
  'voice.providers.chip.cloudAria': 'OpenHuman managed provider is always enabled',
  'voice.providers.chip.whisper': 'Whisper (Local)',
  'voice.providers.chip.enableWhisper': 'Enable local Whisper STT',
  'voice.providers.chip.disableWhisper': 'Disable local Whisper STT',
  'voice.providers.chip.piper': 'Piper (Local)',
  'voice.providers.chip.enablePiper': 'Enable local Piper TTS',
  'voice.providers.chip.disablePiper': 'Disable local Piper TTS',
  'voice.providers.chip.enableProvider': 'Enable',
  'voice.providers.chip.disableProvider': 'Disable',
  'voice.providers.chip.apiKeyLabel': 'API Key',
  'voice.providers.chip.apiKeyPlaceholder': 'sk-…',
  'voice.providers.chip.comingSoon': 'coming soon',

  // Voice provider modal
  'voice.modal.title': 'Configure',
  'voice.modal.desc':
    'Enter your API key to enable this provider. You can test the connection before saving.',
  'voice.modal.testKey': 'Test Key',
  'voice.modal.testing': 'Testing…',
  'voice.modal.saveAndEnable': 'Save & Enable',
  'voice.modal.enable': 'Enable',
  'voice.modal.whisperDesc':
    'Choose a model size and install the Whisper binary and GGML model into your workspace. Larger models are more accurate but slower.',
  'voice.modal.piperDesc':
    'Choose a voice and install the Piper binary and ONNX model into your workspace. Piper runs fully offline with low latency.',

  // Voice routing section
  'voice.routing.title': 'Voice Routing',
  'voice.routing.desc': 'Choose which enabled providers handle speech-to-text and text-to-speech.',
  'voice.routing.save': 'Save',
  'voice.routing.testStt': 'Test STT',
  'voice.routing.testTts': 'Test TTS',
  'voice.routing.elevenlabsVoice': 'ElevenLabs Voice',
  'voice.routing.elevenlabsVoiceAria': 'ElevenLabs voice selection',
  'voice.routing.elevenlabsVoiceIdAria': 'ElevenLabs voice ID (custom)',
  'voice.routing.elevenlabsVoiceDesc':
    'Pick a curated voice or paste a custom voice ID from your ElevenLabs dashboard.',

  // External voice providers
  'voice.externalProviders.title': 'External Voice Providers',
  'voice.externalProviders.desc':
    'Connect third-party STT/TTS APIs like Deepgram, ElevenLabs, or OpenAI directly.',
  'voice.externalProviders.keySet': 'Key set',
  'voice.externalProviders.noKey': 'No API key',
  'voice.externalProviders.test': 'Test',
  'voice.externalProviders.testing': 'Testing…',
  'voice.externalProviders.remove': 'Remove',
  'voice.externalProviders.provider': 'Provider',
  'voice.externalProviders.selectProvider': 'Select a provider…',
  'voice.externalProviders.apiKey': 'API Key',
  'voice.externalProviders.apiKeyPlaceholder': 'sk-…',
  'voice.externalProviders.add': 'Add',

  // Push-to-talk (PTT)
  'pttSettings.title': 'Push-to-talk',
  'pttSettings.description':
    "Hold a key to talk to OpenHuman while you're in another app. Release the key to send; OpenHuman speaks the reply if 'Speak agent replies' is on.",
  'pttSettings.shortcutLabel': 'Hotkey',
  'pttSettings.shortcutPlaceholder': 'Press a key (e.g. F13)',
  'pttSettings.shortcutUnsetHint': 'Push-to-talk is off — pick a hotkey to enable.',
  'pttSettings.speakRepliesLabel': 'Speak agent replies',
  'pttSettings.showOverlayLabel': 'Show overlay while held',
  'pttSettings.errorConflictsWithDictation':
    'This shortcut is already used by dictation. Pick a different key.',
  'pttSettings.errorModifierOnly':
    "Pick a regular key (e.g. F13) — modifier-only shortcuts don't work for push-to-talk.",
  'pttSettings.errorEmpty': 'Pick a key to bind.',
  'pttSettings.errorAccessibility':
    'macOS needs Accessibility permission for this shortcut. Open System Settings → Privacy & Security → Accessibility and enable OpenHuman.',
  'pttSettings.errorShortcutInUse': 'Another app already uses this shortcut. Pick a different one.',
  'pttSettings.errorUnsupportedWayland':
    "Wayland sessions don't support global shortcuts in OpenHuman yet — switch to an X11 session or use the in-app dictation toggle.",
  'pttSettings.exclusiveFullscreenHint':
    "In exclusive-fullscreen games the overlay won't render — you'll only hear the chime. Switch to borderless fullscreen for the overlay.",
  'pttOverlay.listening': 'Listening…',
  'pttOverlay.idle': 'Idle',

  // Autocomplete
  'autocomplete.title': 'Autocomplete',
  'autocomplete.settings': 'Settings',
  'autocomplete.acceptWithTab': 'Accept With Tab',
  'autocomplete.stylePreset': 'Style Preset',
  'autocomplete.style.balanced': 'Balanced',
  'autocomplete.style.concise': 'Concise',
  'autocomplete.style.formal': 'Formal',
  'autocomplete.style.casual': 'Casual',
  'autocomplete.style.custom': 'Custom',
  'autocomplete.disabledApps': 'Disabled Apps (one bundle/app token per line)',
  'autocomplete.debounceMs': 'Debounce (ms)',
  'autocomplete.maxChars': 'Max context characters',
  'autocomplete.overlayTtlMs': 'Overlay timeout (ms)',
  'autocomplete.saveSettings': 'Save Settings',
  'autocomplete.saving': 'Saving…',
  'autocomplete.runtime': 'Runtime',
  'autocomplete.running': 'Running',
  'autocomplete.start': 'Start',
  'autocomplete.stop': 'Stop',
  'autocomplete.settingsSaved': 'Autocomplete settings saved.',
  'autocomplete.started': 'Autocomplete started.',
  'autocomplete.didNotStart': 'Autocomplete did not start. Check if it is enabled.',
  'autocomplete.stopped': 'Autocomplete stopped.',
  'autocomplete.advancedSettings': 'Advanced settings',
  'autocomplete.debugTitle': 'Autocomplete Debug',

  // Chat
  'chat.agentChat': 'Agent Chat',
  'chat.overrides': 'Overrides',
  'chat.model': 'Model',
  'chat.temperature': 'Temperature',
  'chat.conversation': 'Conversation',
  'chat.startAgentConversation': 'Start a conversation with the agent.',
  'chat.you': 'You',
  'chat.agent': 'Agent',
  'chat.askAgent': 'Ask the agent anything...',
  'chat.sendMessage': 'Send Message',

  // Composio
  'composio.triageTitle': 'Integration Triggers',
  'composio.triageDesc':
    'When active, each incoming Composio trigger runs through an AI triage step that classifies the event and may kick off automated actions — one local LLM turn per trigger. Disable globally or per integration if you prefer manual review. If the environment variable',
  'composio.disableAllTriage': 'Disable AI triage for all triggers',
  'composio.triggersStillRecorded': 'Triggers are still recorded to history — no LLM turn is run.',
  'composio.disableSpecificIntegrations': 'Disable AI triage for specific integrations',
  'composio.settingsSaved': 'Settings saved',
  'composio.saveFailed': 'Failed to save. Try again.',

  // Cron
  'cron.title': 'Cron Jobs',
  'cron.scheduledJobs': 'Scheduled Jobs',
  'cron.manageCronJobs': 'Manage cron jobs from the core scheduler.',
  'cron.refreshCronJobs': 'Refresh Cron Jobs',

  // Local Model
  'localModel.modelStatus': 'Model Status',
  'localModel.downloadModels': 'Download Models',
  'localModel.usage': 'Usage',
  'localModel.usageDesc':
    'Choose which subsystems run on the local model. Anything off uses the cloud.',
  'localModel.enableRuntime': 'Enable local AI runtime',
  'localModel.enableRuntimeDesc':
    'Master switch. Off by default — Ollama stays idle. When on, the tree summarizer, screen intelligence, and autocomplete always use the local model.',
  'localModel.advancedSettings': 'Advanced settings',
  'localModel.debugTitle': 'Local Model Debug',

  // Screen Awareness
  'screenAwareness.debugTitle': 'Screen Awareness Debug',
  'screenAwareness.debug.debugAndDiagnostics': 'Debug & Diagnostics',
  'screenAwareness.debug.collapse': 'Collapse',
  'screenAwareness.debug.expand': 'Expand',
  'screenAwareness.debug.failedToSave': 'Failed to save screen intelligence',
  'screenAwareness.debug.policyTitle': 'Screen Intelligence Policy',
  'screenAwareness.debug.baselineFps': 'Baseline FPS',
  'screenAwareness.debug.useVisionModel': 'Use Vision Model',
  'screenAwareness.debug.useVisionModelDesc':
    'Send screenshots to a vision LLM for richer context. When off, only OCR text is used with a text LLM — faster and no vision model required.',
  'screenAwareness.debug.keepScreenshots': 'Keep Screenshots',
  'screenAwareness.debug.keepScreenshotsDesc':
    'Save captured screenshots to the workspace instead of deleting after processing',
  'screenAwareness.debug.allowlist': 'Allowlist (one rule per line)',
  'screenAwareness.debug.denylist': 'Denylist (one rule per line)',
  'screenAwareness.debug.saveSettings': 'Save Screen Intelligence Settings',
  'screenAwareness.debug.sessionStats': 'Session Stats',
  'screenAwareness.debug.framesEphemeral': 'Frames (ephemeral)',
  'screenAwareness.debug.panicStop': 'Panic stop',
  'screenAwareness.debug.defaultPanicHotkey': 'Cmd+Shift+.',
  'screenAwareness.debug.vision': 'Vision',
  'screenAwareness.debug.idle': 'idle',
  'screenAwareness.debug.visionQueue': 'Vision queue',
  'screenAwareness.debug.lastVision': 'Last vision',
  'screenAwareness.debug.notAvailable': 'n/a',
  'screenAwareness.debug.visionSummaries': 'Vision Summaries',
  'screenAwareness.debug.refreshing': 'Refreshing…',
  'screenAwareness.debug.noSummaries': 'No summaries yet.',
  'screenAwareness.debug.unknownApp': 'Unknown App',
  'screenAwareness.debug.macosOnly': 'Screen Intelligence V1 is currently supported on macOS only.',

  // Memory
  'memory.debugTitle': 'Memory Debug',
  'memory.documents': 'Documents',
  'memory.filterByNamespace': 'Filter by namespace...',
  'memory.refresh': 'Refresh',
  'memory.noDocumentsFound': 'No documents found.',
  'memory.delete': 'Delete',
  'memory.rawResponse': 'Raw response',
  'memory.namespaces': 'Namespaces',
  'memory.noNamespacesFound': 'No namespaces found.',
  'memory.queryRecall': 'Query & Recall',
  'memory.namespace': 'Namespace',
  'memory.queryText': 'Query text...',
  'memory.defaultMaxChunks': '10',
  'memory.maxChunks': 'max chunks',
  'memory.query': 'Query',
  'memory.recall': 'Recall',
  'memory.queryLabel': 'Query',
  'memory.recallLabel': 'Recall',
  'memory.queryResult': 'Query result',
  'memory.recallResult': 'Recall result',
  'memory.clearNamespace': 'Clear Namespace',
  'memory.clearNamespaceDescription': 'Permanently delete all documents within a namespace.',
  'memory.selectNamespace': 'Select namespace...',
  'memory.exampleNamespace': 'e.g. skill:gmail:user@example.com',
  'memory.clear': 'Clear',
  'memory.deleteConfirm': 'Delete document "{documentId}" in namespace "{namespace}"?',
  'memory.clearNamespaceConfirm':
    'This will permanently delete ALL documents in namespace "{namespace}". Continue?',
  'memory.clearNamespaceSuccess': 'Namespace "{namespace}" cleared.',
  'memory.clearNamespaceEmpty': 'Nothing to clear in "{namespace}".',

  // Webhooks
  'webhooks.debugTitle': 'Webhooks Debug',
  'webhooks.failedToLoadDebugData': 'Failed to load webhook debug data',
  'webhooks.clearLogsConfirm': 'Clear all captured webhook debug logs?',
  'webhooks.failedToClearLogs': 'Failed to clear webhook logs',
  'webhooks.loading': 'Loading...',
  'webhooks.refresh': 'Refresh',
  'webhooks.clearing': 'Clearing...',
  'webhooks.clearLogs': 'Clear Logs',
  'webhooks.registered': 'registered',
  'webhooks.captured': 'captured',
  'webhooks.live': 'live',
  'webhooks.disconnected': 'disconnected',
  'webhooks.lastEvent': 'Last event',
  'webhooks.at': 'at',
  'webhooks.registeredWebhooks': 'Registered Webhooks',
  'webhooks.noActiveRegistrations': 'No active registrations.',
  'webhooks.resolvingBackendUrl': 'Resolving backend URL…',
  'webhooks.capturedRequests': 'Captured Requests',
  'webhooks.noRequestsCaptured': 'No webhook requests captured yet.',
  'webhooks.unrouted': 'unrouted',
  'webhooks.pending': 'pending',
  'webhooks.requestHeaders': 'Request Headers',
  'webhooks.queryParams': 'Query Params',
  'webhooks.requestBody': 'Request Body',
  'webhooks.responseHeaders': 'Response Headers',
  'webhooks.responseBody': 'Response Body',
  'webhooks.rawPayload': 'Raw Payload',
  'webhooks.empty': '[empty]',

  // Provider setup
  'providerSetup.error.defaultDetails': 'Provider setup failed.',
  'providerSetup.error.providerFallback': 'The provider',
  'providerSetup.error.credentialsRejected':
    '{provider} rejected the credentials. Check the API key and try again.',
  'providerSetup.error.endpointNotRecognized':
    '{provider} did not recognize the endpoint. Check the base URL and try again.',
  'providerSetup.error.providerUnavailable':
    '{provider} is unavailable right now. Try again or check the provider status.',
  'providerSetup.error.unreachable':
    'Could not reach {provider}. Check the endpoint URL and network connection, then try again.',
  'providerSetup.error.couldNotReachWithMessage': 'Could not reach {provider}: {message}',
  'providerSetup.error.technicalDetails': 'Technical details',

  // Notifications
  'notifications.routingTitle': 'Notification Routing',
  'notifications.routing.pipelineStats': 'Pipeline stats',
  'notifications.routing.total': 'Total',
  'notifications.routing.unread': 'Unread',
  'notifications.routing.unscored': 'Unscored',
  'notifications.routing.intelligenceTitle': 'Notification Intelligence',
  'notifications.routing.intelligenceDesc':
    'Every notification from your connected accounts is scored by a local AI model. High-importance notifications are automatically routed to your orchestrator agent so nothing critical slips through.',
  'notifications.routing.howItWorks': 'How it works',
  'notifications.routing.level.drop': 'Drop',
  'notifications.routing.level.dropDesc': 'Noise / spam — stored but not surfaced',
  'notifications.routing.level.acknowledge': 'Acknowledge',
  'notifications.routing.level.acknowledgeDesc': 'Low-priority — shown in notification center',
  'notifications.routing.level.react': 'React',
  'notifications.routing.level.reactDesc': 'Medium-priority — triggers a focused agent response',
  'notifications.routing.level.escalate': 'Escalate',
  'notifications.routing.level.escalateDesc': 'High-priority — forwarded to orchestrator agent',
  'notifications.routing.perProvider': 'Per-provider routing',
  'notifications.routing.threshold': 'Threshold',
  'notifications.routing.routeToOrchestrator': 'Route to orchestrator',
  'notifications.routing.loadSettingsError': 'Failed to load settings. Reopen this panel to retry.',

  // Common (additional)
  'common.reload': 'Reload',
  'common.skip': 'Skip',
  'common.disable': 'Disable',
  'common.enable': 'Enable',

  // Chat (additional)
  'chat.safetyTimeout':
    'No response from the agent after 2 minutes. Try again or check your connection.',
  'chat.filter.general': 'General',
  'chat.filter.subconscious': 'Subconscious',
  'chat.filter.meetings': 'Meetings',
  'chat.filter.tasks': 'Tasks',
  'chat.selectThread': 'Select a thread',
  'chat.threads': 'Threads',
  'chat.noThreads': 'No threads yet',
  'chat.noLabelThreads': 'No "{label}" threads',
  'chat.deleteThread': 'Delete thread',
  'chat.deleteThreadConfirm': 'Are you sure you want to delete "{title}"?',
  'chat.untitledThread': 'Untitled thread',
  'chat.editThreadTitle': 'Edit thread title',
  'chat.hideSidebar': 'Hide sidebar',
  'chat.showSidebar': 'Show sidebar',
  'chat.searchThreads': 'Search conversations',
  'layout.resizeSidebar': 'Resize sidebar',
  'layout.showSidebar': 'Show sidebar',
  'chat.newThreadShortcut': 'New thread (/new)',
  'chat.new': 'New',
  'chat.failedToLoadMessages': 'Failed to load messages',
  'chat.thinkingIteration': 'Thinking... ({n})',
  'chat.thinkingDots': 'Thinking...',
  'chat.approachingLimit': 'Approaching usage limit',
  'chat.approachingLimitMsg': 'You have used {pct}% of your available quota.',
  'chat.upgrade': 'Upgrade',
  'chat.weeklyLimitHit': "You've used your included cycle budget.",
  'chat.resets': 'Resets',
  'chat.topUpToContinue': 'Top up to continue.',
  'chat.budgetComplete': 'Your included budget is complete. Add credits or upgrade to continue.',
  'chat.topUp': 'Top Up',
  'chat.cycle': 'Cycle',
  'chat.cycleSpent': 'Spent this cycle',
  'chat.cycleRemaining': 'Remaining',
  'chat.left': 'left',
  'chat.setup': 'Set up',
  'chat.switchToText': 'Switch to text',
  'chat.superContext.label': 'Super Context',
  'chat.superContext.hint':
    'Super Context allows OpenHuman to gather and prepare context from all the data it has access to so that it can deliver a highly relevant answer. Super Context is in early beta.',
  'chat.transcribing': 'Transcribing...',
  'chat.stopAndSend': 'Stop and send',
  'chat.startTalking': 'Start talking',
  'chat.playingVoiceReply': 'Playing voice reply',
  'chat.voiceHint': 'Use the mic to speak',
  'chat.micUnavailable': 'Microphone unavailable',
  'chat.turn': 'turn',
  'chat.turns': 'turns',
  'chat.openWorkerThread': 'Open worker thread',
  'chat.attachment.attach': 'Attach image',
  'chat.attachment.remove': 'Remove {name}',
  'chat.attachment.tooMany': 'Maximum {max} images per message',
  'chat.attachment.tooManyFiles': 'Maximum {max} files per message',
  'chat.attachment.tooManyVideos': 'Maximum {max} videos per message',
  'chat.attachment.videoNotSupported':
    'This model can’t read videos. You can use the OpenHuman Reasoning tier to attach your video.',
  'chat.attachment.dropToAttach': 'Drop files to attach',
  'chat.attachment.tooLarge': 'Image exceeds {max} size limit',
  'chat.attachment.unsupportedType':
    'Unsupported file type. Use an image (PNG, JPEG, WebP, GIF, BMP) or a PDF, TXT, or Markdown file.',
  'chat.attachment.imageNotSupported':
    'This model can’t read images. You can use the OpenHuman Reasoning tier to attach your image.',
  'chat.attachment.readFailed': 'Could not read file',

  // Memory (additional)
  'memory.searchAria': 'Search memory',
  'memory.searchPlaceholder': 'Search memory entries...',
  'memory.sourceFilter.all': 'All sources',
  'memory.sourceFilter.email': 'Email',
  'memory.sourceFilter.calendar': 'Calendar',
  'memory.sourceFilter.telegram': 'Telegram',
  'memory.sourceFilter.aiInsight': 'AI Insight',
  'memory.sourceFilter.system': 'System',
  'memory.sourceFilter.trading': 'Trading',
  'memory.sourceFilter.security': 'Security',
  'memory.ingestionActivity': 'Ingestion Activity',
  'memory.events': 'events',
  'memory.event': 'event',
  'memory.overTheLast': 'over the last',
  'memory.months': 'months',
  'memory.peak': 'Peak',
  'memory.perDay': '/day',
  'memory.less': 'Less',
  'memory.more': 'More',
  'memory.on': 'on',
  'memory.loading': 'Loading Memory',
  'memory.fetching': 'Fetching your memory entries...',
  'memory.analyzing': 'Analyzing Memory',
  'memory.analyzingHint': 'Processing your memories to extract insights...',
  'memory.noMatches': 'No Matches Found',
  'memory.noMatchesHint': 'Try changing your search terms or filters.',
  'memory.allCaughtUp': 'All Caught Up',
  'memory.allCaughtUpHint': 'No new memory entries to process.',
  'memory.noAnalysis': 'No Analysis Yet',
  'memory.noAnalysisHint': 'Run an analysis to discover patterns in your memories.',
  'memory.emptyHint': 'Start interacting to create your first memories.',

  // Mic
  'mic.unavailable': 'Microphone is not available',
  'mic.permissionDenied': 'Microphone permission denied',
  'mic.failedToStartRecorder': 'Failed to start recorder',
  'mic.deviceUnavailable': 'Selected microphone is unavailable — try a different device.',
  'mic.deviceInUse': 'Microphone is in use by another application.',
  'mic.error': 'Microphone error',
  'mic.transcribing': 'Transcribing...',
  'mic.retryingTranscription': 'Retrying... ({attempt} of {max})',
  'mic.tapToSend': 'Tap to send',
  'mic.waitingForAgent': 'Waiting for agent...',
  'mic.tapAndSpeak': 'Tap and speak',
  'mic.stopRecording': 'Stop recording and send',
  'mic.startRecording': 'Start recording',
  'mic.deviceSelector': 'Microphone device',
  'mic.tapToSendCountdown': 'Tap to send ({seconds}s)',

  // Token
  'token.usageLimitReached': 'Usage limit reached',
  'token.approachingLimit': 'Approaching limit',
  'token.planClickForDetails': 'plan - click for details',
  'token.sessionTokens': 'In: {in} | Out: {out} | Turns: {turns}',
  'token.limit': 'Limit Reached',
  'token.inLabel': 'IN',
  'token.outLabel': 'OUT',
  'token.inputTokens': 'Input tokens this session',
  'token.outputTokens': 'Output tokens this session',
  'token.turnsCount': 'Inference turns this session',
  'token.turn': 'turn',
  'token.turns': 'turns',
  'token.ctxLabel': 'CTX',
  'token.contextWindow': 'Context window usage (last turn)',
  'token.cachedLabel': 'Cached',
  'token.costLabel': 'Cost',
  'token.costTitle': 'Estimated cost this session (USD)',
  'token.sessionUsageTitle': 'Session usage',
  'token.subAgentsHeading': 'Sub-agent usage',
  'token.byAgentHeading': 'By agent',
  'token.orchestrator': 'Orchestrator',
  'token.noSubAgents': 'No sub-agent usage yet',
  'token.popInput': 'Input tokens',
  'token.popOutput': 'Output tokens',
  'token.popCacheHit': 'Cache hit',
  'token.popContext': 'Context window',
  'token.tipInput':
    'Tokens sent to the model this session — your prompts plus the conversation history.',
  'token.tipOutput': 'Tokens generated by the model this session.',
  'token.tipCacheHit': 'Input tokens served from a cached prompt prefix, billed at a reduced rate.',
  'token.clickForDetails': 'Click for session usage details',

  // Catalog
  'catalog.noCapabilityBinding': 'No capability binding',
  'catalog.downloadFailed': 'Download failed',
  'catalog.active': 'Active',
  'catalog.installed': 'Installed',
  'catalog.notDownloaded': 'Not downloaded',
  'catalog.inUse': 'In Use',
  'catalog.use': 'Use',
  'catalog.deleteModel': 'Delete model',
  'catalog.download': 'Download',

  // Navigator
  'navigator.recent': 'Recent',
  'navigator.today': 'Today',
  'navigator.thisWeek': 'This Week',
  'navigator.sources': 'Sources',
  'navigator.email': 'Email',
  'navigator.slack': 'Slack',
  'navigator.chat': 'Chat',
  'navigator.documents': 'Documents',
  'navigator.people': 'People',
  'navigator.topics': 'Topics',

  // Dreams
  'dreams.description':
    'Dreams are AI-generated reflections that synthesize patterns from your memories.',
  'dreams.comingSoon': 'Coming soon',

  // Assignment
  'assignment.memoryLlm': 'Memory LLM',
  'assignment.memoryLlmAria': 'Memory LLM selection',
  'assignment.embedder': 'Embedder',
  'assignment.loaded': 'Loaded',
  'assignment.notDownloaded': 'Not downloaded',
  'assignment.usedForExtractSummarise': 'Used for extraction and summarization',

  // Insights
  'insights.knownFacts': 'Known Facts',
  'insights.preferences': 'Preferences',
  'insights.relationships': 'Relationships',
  'insights.skills': 'Skills',
  'insights.opinions': 'Opinions',
  'insights.other': 'Other',
  'insights.title': 'Insights',
  'insights.empty': 'No insights yet. Insights are generated as your memory grows.',
  'insights.description': 'Based on {count} relations in your memory graph.',
  'insights.items': 'items',
  'insights.more': 'more',

  // Calls
  'calls.joiningCall': 'Joining call',
  'calls.meetWindowOpening': 'The Meet window is opening...',
  'calls.failedToStart': 'Failed to start Meet call',
  'calls.couldNotStart': 'Could not start call',
  'calls.failedToClose': 'Failed to close call',
  'calls.couldNotClose': 'Could not close call',
  'calls.joinMeet': 'Join a Google Meet call',
  'calls.joinMeetDescription': 'Enter a Google Meet link to join.',
  'calls.meetLink': 'Meet Link',
  'calls.displayName': 'Display Name',
  'calls.openingMeet': 'Opening Meet...',
  'calls.joinCall': 'Join Call',
  'calls.activeCalls': 'Active Calls',
  'calls.leave': 'Leave',

  // Workspace
  'workspace.wipeConfirm': 'Are you sure you want to wipe all memory? This cannot be undone.',
  'workspace.resetTreeConfirm': 'Are you sure you want to rebuild the memory tree?',
  'workspace.wipeTitle': 'Wipe Memory',
  'workspace.resetting': 'Resetting...',
  'workspace.resetMemory': 'Reset Memory',
  'workspace.resetTreeTitle': 'Rebuild Memory Tree',
  'workspace.rebuilding': 'Rebuilding...',
  'workspace.resetMemoryTree': 'Reset Memory Tree',
  'workspace.building': 'Building...',
  'workspace.buildSummaryTrees': 'Build Summary Trees',
  'workspace.viewVault': 'View Vault',
  'workspace.openingVaultTitle': 'Opening vault in Obsidian',
  'workspace.openingVaultMessage':
    "If Obsidian doesn't open, install it from obsidian.md or use Reveal Folder. Vault path:",
  'workspace.openVaultFailedTitle': "Couldn't open vault in Obsidian",
  'workspace.openVaultFailedMessage':
    'Use Reveal Folder to open the vault directory directly. Vault path:',
  'workspace.revealVaultFailed': "Couldn't reveal vault folder",
  'workspace.revealFolder': 'Reveal Folder',
  'workspace.checkingVault': 'Checking…',
  'workspace.vaultNotRegisteredHelp':
    'Obsidian only opens folders you\'ve added as a vault. In Obsidian, choose "Open folder as vault" and pick the folder below — you only need to do this once. Then click View Vault again.',
  'workspace.obsidianNotFoundHelp':
    "We couldn't find Obsidian on this device. Install it, or — if it's installed somewhere non-standard — set its config folder under Advanced.",
  'workspace.openAnyway': 'Open in Obsidian anyway',
  'workspace.installObsidian': 'Install Obsidian',
  'workspace.obsidianAdvanced': 'Obsidian installed elsewhere?',
  'workspace.obsidianConfigDirLabel': 'Obsidian config folder',
  'workspace.obsidianConfigDirHint':
    'Path to the folder containing obsidian.json (e.g. ~/.config/obsidian). Leave blank to auto-detect.',
  'workspace.obsidianConfigDirPlaceholder': '~/.config/obsidian',
  'workspace.graphLoadFailed': 'Failed to load memory graph',
  'workspace.loadingGraph': 'Loading memory graph...',
  'workspace.graphViewMode': 'Memory graph view mode',
  'workspace.trees': 'Trees',
  'workspace.contacts': 'Contacts',

  // Vault health checklist
  'vaultHealth.title': 'Vault Health Checklist',
  'vaultHealth.setupTitle': 'Vault setup health',
  'vaultHealth.workspaceVault': 'Workspace vault:',
  'vaultHealth.refresh': 'Refresh',
  'vaultHealth.refreshing': 'Refreshing…',
  'vaultHealth.revealFolder': 'Reveal Folder',
  'vaultHealth.openInObsidian': 'Open in Obsidian',
  'vaultHealth.installObsidian': 'Install Obsidian',
  'vaultHealth.openObsidianError': 'Could not open Obsidian',
  'vaultHealth.revealError': 'Could not reveal vault folder',
  'vaultHealth.downloadError': 'Could not open Obsidian download page',
  'vaultHealth.loadError': 'Could not load vault health:',
  'vaultHealth.lastSync': 'Last sync:',
  'vaultHealth.passed': 'Passed',
  'vaultHealth.needsAttention': 'Needs attention',
  'vaultHealth.existsLabel': 'Workspace vault path exists',
  'vaultHealth.existsRecovery':
    'Vault folder is missing. Start a sync or create this folder, then refresh this checklist.',
  'vaultHealth.writableLabel': 'Vault is writable by OpenHuman',
  'vaultHealth.writableRecovery':
    'OpenHuman cannot write to this vault yet. Grant write permissions and refresh.',
  'vaultHealth.obsidianLabel': 'Vault is registered in Obsidian',
  'vaultHealth.obsidianRecovery':
    'In Obsidian, choose "Open folder as vault" for this path, then refresh this checklist.',
  'vaultHealth.pipelineLabel': 'Memory pipeline is healthy',
  'vaultHealth.pipelineRecovery':
    'Memory pipeline is paused or in error. Re-enable Auto-sync in Memory Tree status and retry.',
  'vaultHealth.timeNever': 'Never',
  'vaultHealth.timeJustNow': 'just now',
  'vaultHealth.timeMinAgo': '{n} min ago',
  'vaultHealth.timeHrAgo': '{n} hr ago',
  'vaultHealth.timeDayAgo': '{n} day ago',
  'vaultHealth.timeDaysAgo': '{n} days ago',

  // Cross-host vault (#4278) — shared by VaultHealthChecklist + ObsidianVaultSection
  'crossHostVault.title': 'Vault is on the core host.',
  'crossHostVault.message':
    'This memory vault is stored on the openhuman-core host ({os}). It can only be opened or revealed on that machine, not from this device.',

  // Memory data panel (storage explainer)
  'memoryData.howItWorks': 'How memory storage works',
  'memoryData.workspaceVault': 'Workspace vault · write',
  'memoryData.workspaceVaultDesc':
    'OpenHuman writes generated memory notes to memory_tree/content.',
  'memoryData.connectedSources': 'Connected sources · read',
  'memoryData.connectedSourcesDesc':
    'Folders, mailboxes, chats, and repos are imported for memory indexing — their original files are never rewritten.',
  'memoryData.internalFiles': 'Internal memory-tree files',
  'memoryData.internalFilesDesc':
    'Indexes, queue state, and summaries are managed by OpenHuman to keep recall and sync healthy.',
  'memoryData.windowError': 'Memory window',
  'memoryData.windowUpdated': 'Memory window updated',
  'memoryData.windowUpdatedMsg': 'Set to {window}.',

  // Graph
  'graph.noContactMentions': 'No contact mentions',
  'graph.noMemory': 'No memory',
  'graph.source': 'Source',
  'graph.topic': 'Topic',
  'graph.global': 'Global',
  'graph.document': 'Document',
  'graph.contact': 'Contact',
  'graph.nodes': 'nodes',
  'graph.parentChild': 'parent-child',
  'graph.documentContact': 'document-contact',
  'graph.link': 'link',
  'graph.links': 'links',
  'graph.children': 'children',
  'graph.clickToOpenObsidian': 'Click to open in Obsidian',
  'graph.person': 'Person',
  'graph.resetView': 'Reset view',

  // Modal
  'modal.dontShowAgain': "Don't show similar suggestions",

  // Reflections
  'reflections.loading': 'Loading reflections...',
  'reflections.empty': 'No reflections yet',
  'reflections.title': 'Reflections',
  'reflections.proposedAction': 'Proposed Action',
  'reflections.act': 'Act',
  'reflections.dismiss': 'Dismiss',
  'reflections.viewConversation': 'View',

  // Subconscious mode selector
  'subconscious.mode.label': 'Subconscious Mode',
  'subconscious.mode.off.title': 'Off',
  'subconscious.mode.off.desc': 'Subconscious is disabled.',
  'subconscious.mode.simple.title': 'Simple',
  'subconscious.mode.simple.desc': 'Read-only observation. Memory and file access only.',
  'subconscious.mode.aggressive.title': 'Aggressive',
  'subconscious.mode.aggressive.desc':
    'Full tool access. Can write, spawn agents, and delegate tasks.',
  'subconscious.mode.aggressiveWarning':
    'Aggressive mode gives the subconscious full tool access including writes and sub-agent spawning.',
  'subconscious.interval.label': 'Frequency',
  'subconscious.interval.minutes': '{n} min',
  'subconscious.interval.hours': '{n}h',
  'subconscious.interval.oneHour': '1 hour',
  'subconscious.interval.oneDay': '24 hours',

  // WhatsApp
  'whatsapp.chatsSynced': 'chats synced',
  'whatsapp.chatSynced': 'chat synced',

  // Sync
  'sync.active': 'Active',
  'sync.recent': 'Recent',
  'sync.idle': 'Idle',
  'sync.memorySources': 'Memory Sources',
  'sync.noConnectedSources': 'No connected sources',
  'sync.chunks': 'chunks',
  'sync.lastChunk': 'Last chunk:',
  'sync.pending': 'pending',
  'sync.processed': 'processed',
  'sync.syncing': 'Syncing…',
  'sync.sync': 'Sync',
  'sync.failedToLoad': 'Failed to load sync status',
  'sync.noContent': 'No content has been synced into memory yet. Connect an integration to start.',

  // Memory Sync Schedule (global cadence)
  'memorySyncInterval.title': 'Sync schedule',
  'memorySyncInterval.lastSynced': 'Last synced',
  'memorySyncInterval.never': 'never',
  'memorySyncInterval.everyHours': 'Every {h}h',
  'memorySyncInterval.everyMinutes': 'Every {m}m',
  'memorySyncInterval.manual': 'Manual only',
  'memorySyncInterval.saveFailed': 'Failed to update sync schedule',

  // Memory Sources Registry
  'memorySources.title': 'Memory Sources',
  'memorySources.empty': 'No memory sources yet. Add one to start feeding memory.',
  'memorySources.customSources': 'Custom Sources',
  'memorySources.addSource': 'Add Source',
  'memorySources.noCustomSources':
    'No custom sources yet. Add a folder, GitHub repo, RSS feed, or web page to start.',
  'memorySources.loadingConnections': 'Loading connections…',
  'memorySources.noConnections':
    'No active Composio connections found. Connect an integration first.',
  'memorySources.pickConnection': 'Pick a connection',
  'memorySources.selectConnection': '— Select a connection —',
  'memorySources.comingSoon': 'Coming soon',
  'memorySources.composioListFailed': 'Failed to load Composio connections.',
  'memorySources.browse': 'Browse…',
  'memorySources.folderPathPlaceholder': '/Users/you/notes',
  'memorySources.globPatternPlaceholder': '**/*.md',
  'memorySources.repoUrlPlaceholder': 'https://github.com/org/repo',
  'memorySources.branchPlaceholder': 'main',
  'memorySources.feedUrlPlaceholder': 'https://example.com/feed.xml',
  'memorySources.pageUrlPlaceholder': 'https://example.com/article',
  'memorySources.cssSelectorPlaceholder': 'article',
  'memorySources.searchQueryPlaceholder': 'from:user AI safety',
  'memorySources.kind.composio': 'Integration',
  'memorySources.kind.conversation': 'Conversation',
  'memorySources.kind.folder': 'Local Folder',
  'memorySources.kind.github_repo': 'GitHub Repo',
  'memorySources.kind.twitter_query': 'Twitter Search',
  'memorySources.kind.rss_feed': 'RSS Feed',
  'memorySources.kind.web_page': 'Web Page',
  'memorySources.sync.successTitle': 'Syncing',
  'memorySources.sync.successMessage': 'Progress will appear shortly.',
  'memorySources.sync.failedTitle': 'Sync failed:',
  'memorySources.sync.completeTitle': 'Synced',
  'memorySources.sync.itemsSynced': 'items synced',
  'memorySources.sync.upToDate': 'Up to date',
  'memorySources.sync.failedLabel': 'Failed',
  'time.justNow': 'just now',
  'time.secondsAgoSuffix': 's ago',
  'time.minutesAgoSuffix': 'm ago',
  'time.hoursAgoSuffix': 'h ago',
  'time.daysAgoSuffix': 'd ago',
  'memorySources.pickKind': 'What kind of source do you want to add?',
  'memorySources.backToKinds': 'Back to source types',
  'memorySources.label': 'Label',
  'memorySources.labelPlaceholder': 'My research notes',
  'memorySources.add': 'Add',
  'memorySources.adding': 'Adding…',
  'memorySources.added': 'Source added',
  'memorySources.removed': 'Source removed',
  'memorySources.remove': 'Remove',
  'memorySources.enable': 'Enable',
  'memorySources.disable': 'Disable',
  'memorySources.toggleFailed': 'Toggle failed',
  'memorySources.removeFailed': 'Remove failed',
  'memorySources.folderPath': 'Folder path',
  'memorySources.globPattern': 'Glob pattern',
  'memorySources.repoUrl': 'Repository URL',
  'memorySources.branch': 'Branch',
  'memorySources.feedUrl': 'Feed URL',
  'memorySources.pageUrl': 'Page URL',
  'memorySources.cssSelector': 'CSS selector (optional)',
  'memorySources.searchQuery': 'Search query',
  'memorySources.build.title': 'Build',
  'memorySources.build.building': 'Building…',
  'memorySources.build.successTitle': 'Tree built',
  'memorySources.build.failedTitle': 'Build failed',
  'memorySources.build.sealsMessage': 'seal(s) completed',
  'memorySources.allIn.button': 'All In',
  'memorySources.allIn.title': 'Go All In?',
  'memorySources.allIn.message':
    'This enables every memory source and removes all sync limits. It builds the richest memory graph, but may use more credits.',
  'memorySources.allIn.confirm': 'Yes',
  'memorySources.allIn.cancel': 'No',
  'memorySources.allIn.success': 'All sources enabled with no limits. Syncing started.',
  'memorySources.allIn.failed': 'Could not apply All In. Please try again.',
  'memorySources.settings.button': 'Settings',
  'memorySources.settings.title': 'Sync settings',
  'memorySources.settings.maxPrs': 'Max pull requests',
  'memorySources.settings.maxIssues': 'Max issues',
  'memorySources.settings.maxCommits': 'Max commits',
  'memorySources.settings.maxItems': 'Max items',
  'memorySources.settings.sinceDays': 'Lookback (days)',
  'memorySources.settings.syncDepthDays': 'Sync depth (days)',
  'memorySources.settings.maxTokens': 'Max tokens per sync',
  'memorySources.settings.maxCost': 'Max cost per sync (USD)',
  'memorySources.settings.unlimited': 'Unlimited',
  'memorySources.settings.unlimitedTooltip':
    "You've opted in to sync the maximum for {toolkit}. You can change the caps here.",
  'memorySources.settings.maxed': 'Maxed',
  'memorySources.settings.save': 'Save',
  'memorySources.settings.saving': 'Saving…',
  'memorySources.settings.saved': 'Settings saved',
  'memorySources.settings.saveFailed': 'Could not save settings',

  // Backend
  'backend.aiBackend': 'AI Backend',
  'backend.cloud': 'Cloud',
  'backend.recommended': 'Recommended',
  'backend.cloudDescription':
    'Fast, powerful models routed through the OpenHuman backend. Ready to use immediately.',
  'backend.privacyNote':
    'Prompts and selected context may be sent to the configured backend/provider. Use local mode for supported on-device workloads.',
  'backend.local': 'Local',
  'backend.advanced': 'Advanced',
  'backend.localDescription':
    'Run models on your own machine using Ollama. Full privacy, requires setup.',
  'backend.ramRecommended': '16GB+ RAM recommended',

  // Subconscious
  'subconscious.tasks': 'tasks',
  'subconscious.ticks': 'ticks',
  'subconscious.last': 'Last',
  'subconscious.failed': 'failed',
  'subconscious.tickInterval': 'Tick Interval',
  'subconscious.runNow': 'Run Now',
  'subconscious.providerUnavailableTitle': 'Subconscious is paused',
  'subconscious.providerSettings': 'AI settings',
  'subconscious.scratchpadInfo':
    'On each tick the subconscious checks what changed across your connected sources, then records follow-ups on your to-do list, updates your goals, or notifies you when something needs attention. Check Settings → Agent access to configure mode and frequency.',
  'subconscious.approvalNeeded': 'Approval Needed',
  'subconscious.requiresApproval': 'Requires approval',
  'subconscious.fixInConnections': 'Fix in Connections',
  'subconscious.goAhead': 'Go Ahead',
  'subconscious.activeTasks': 'Active Tasks',
  'subconscious.noActiveTasks': 'No active tasks',
  'subconscious.default': 'Default',
  'subconscious.addTaskPlaceholder': 'Add a new task...',
  'subconscious.activityLog': 'Activity Log',
  'subconscious.noActivity': 'No activity yet',
  'subconscious.decision.nothingNew': 'Nothing new',
  'subconscious.decision.completed': 'Completed',
  'subconscious.decision.evaluating': 'Evaluating',
  'subconscious.decision.waitingApproval': 'Waiting for approval',
  'subconscious.decision.failed': 'Failed',
  'subconscious.decision.cancelled': 'Cancelled',
  'subconscious.decision.skipped': 'Skipped',

  // Subconscious triggers (event-driven orchestrator) debug panel
  'subconsciousTriggers.title': 'Subconscious Triggers',
  'subconsciousTriggers.subtitle': 'Event-driven background orchestrator',
  'subconsciousTriggers.pipeline': 'Pipeline',
  'subconsciousTriggers.mode': 'Mode',
  'subconsciousTriggers.orchestrator': 'Orchestrator',
  'subconsciousTriggers.running': 'Running',
  'subconsciousTriggers.stopped': 'Stopped',
  'subconsciousTriggers.promotionsPerHour': 'Promotions / hour',
  'subconsciousTriggers.queueDepth': 'Queue depth',
  'subconsciousTriggers.orchestratorThread': 'Orchestrator thread',
  'subconsciousTriggers.userThread': 'User thread',
  'subconsciousTriggers.disabledHint': 'Enable event-driven mode to activate the pipeline.',
  'subconsciousTriggers.enable': 'Enable',
  'subconsciousTriggers.disable': 'Disable',

  // Actionable
  'actionable.complete': 'Complete',
  'actionable.dismiss': 'Dismiss',
  'actionable.snooze': 'Snooze',
  'actionable.new': 'New',

  // Stats
  'stats.storage': 'Storage',
  'stats.files': 'files',
  'stats.documents': 'Documents',
  'stats.today': 'today',
  'stats.namespaces': 'Namespaces',
  'stats.relations': 'Relations',
  'stats.firstMemory': 'First Memory',
  'stats.latest': 'Latest',
  'stats.sessions': 'Sessions',
  'stats.tokens': 'tokens',

  // Boot Check Gate
  'bootCheck.invalidUrl': 'Please enter a runtime URL.',
  'bootCheck.urlMustStartWith': 'The URL needs to start with http:// or https://',
  'bootCheck.validUrlRequired':
    "That doesn't look like a valid URL (try https://core.example.com/rpc)",
  'bootCheck.tokenRequired': "We'll need an auth token to connect.",
  'bootCheck.httpPublicWarning':
    'This is a plain HTTP URL on a public host — traffic will not be encrypted. Use HTTPS unless you trust this network.',
  'bootCheck.chooseCoreMode': 'Select a Runtime',
  'bootCheck.connectToCore': 'Connect to Your Runtime',
  'bootCheck.desktopDescription': 'OpenHuman needs a runtime to think. Pick where it should live.',
  'bootCheck.webDescription':
    'On the web, OpenHuman connects to a runtime you control. Drop in its URL and auth token below, or grab the desktop app to run one right on your machine.',
  'bootCheck.preferDesktop': 'Rather keep everything on your own device?',
  'bootCheck.downloadDesktop': 'Get the Desktop App',
  'bootCheck.localRecommended': 'Run Locally (Recommended)',
  'bootCheck.localDescription':
    'Runs right here on your computer. Fastest, fully private, nothing to set up.',
  'bootCheck.cloudMode': 'Run on the Cloud (Complex)',
  'bootCheck.cloudDescription':
    "Connect to a runtime you're hosting elsewhere. Stays online 24×7 so you don't need to keep this device running.",
  'bootCheck.coreRpcUrl': 'Runtime URL',
  'bootCheck.rpcUrlPlaceholder': 'https://core.example.com/rpc',
  'bootCheck.authToken': 'Auth Token',
  'bootCheck.bearerTokenPlaceholder': 'The bearer token from your remote runtime',
  'bootCheck.storedLocally': 'Kept on this device only. Sent as ',
  'bootCheck.testing': 'Testing…',
  'bootCheck.testConnection': 'Test Connection',
  'bootCheck.connectedOk': "Connected. You're good to go.",
  'bootCheck.authFailed': "That token didn't work. Double-check it and try again.",
  'bootCheck.unreachablePrefix': "Couldn't reach it:",
  'bootCheck.checkingCore': 'Waking up your runtime…',
  'bootCheck.cannotReach': "Can't Reach the Runtime",
  'bootCheck.cannotReachDesc': "We couldn't connect to your runtime. Want to try a different one?",
  'bootCheck.switchMode': 'Pick a Different Runtime',
  'bootCheck.quit': 'Quit',
  'bootCheck.legacyDetected': 'Legacy Background Runtime Detected',
  'bootCheck.legacyDescription':
    'A separately-installed OpenHuman daemon is already running on this device. We need to clear it out before the built-in runtime can take over.',
  'bootCheck.removing': 'Removing…',
  'bootCheck.removeContinue': 'Remove and Continue',
  'bootCheck.localNeedsRestart': 'Local Runtime Needs a Restart',
  'bootCheck.localNeedsRestartDesc':
    'Your local runtime is on a different version than this app. A quick restart will get them back in sync.',
  'bootCheck.restarting': 'Restarting…',
  'bootCheck.restartCore': 'Restart Runtime',
  'bootCheck.cloudNeedsUpdate': 'Cloud Runtime Needs an Update',
  'bootCheck.cloudNeedsUpdateDesc':
    'Your cloud runtime is on a different version than this app. Run the updater to bring them back in sync.',
  'bootCheck.updating': 'Updating…',
  'bootCheck.updateCloudCore': 'Update Cloud Runtime',
  'bootCheck.versionCheckFailed': 'Runtime Version Check Failed',
  'bootCheck.versionCheckFailedDesc':
    "Your runtime is up but isn't reporting its version. It may be outdated. Restart or update it to continue.",
  'bootCheck.working': 'Working…',
  'bootCheck.restartUpdateCore': 'Restart / Update Runtime',
  'bootCheck.unexpectedError': 'Unexpected Boot-Check Error',
  'bootCheck.actionFailed': 'Something went wrong. Please try again.',
  'bootCheck.portConflictTitle': "Couldn't Start the App Engine",
  'bootCheck.portConflictBody':
    "Another process is using the network port OpenHuman needs. We'll try to fix this automatically.",
  'bootCheck.portConflictFixButton': 'Fix Automatically',
  'bootCheck.portConflictFixing': 'Fixing…',
  'bootCheck.portConflictFixFailed':
    "Automatic fix didn't work. Please restart your computer and try again.",
  'bootCheck.portConflictOwner': '{name} (PID {pid}) is using the network port OpenHuman needs.',
  'bootCheck.portConflictGuidance':
    'Close that program to free the port, or force-quit it below, then try again.',
  'bootCheck.portConflictForceQuit': 'Force-quit {name}',
  'bootCheck.portConflictForceQuitting': 'Closing {name}…',
  'bootCheck.portConflictForceQuitFailed':
    "Couldn't close that program. You may need to close it manually, then retry.",

  // Notifications: category labels & timestamps
  'notifications.justNow': 'just now',
  'notifications.minAgo': '{n}m ago',
  'notifications.hrAgo': '{n}h ago',
  'notifications.dayAgo': '{n}d ago',
  'notifications.category.messages': 'Messages',
  'notifications.category.agents': 'Agents',
  'notifications.category.skills': 'Skills',
  'notifications.category.system': 'System',
  'notifications.category.meetings': 'Meetings',
  'notifications.category.reminders': 'Reminders',
  'notifications.category.important': 'Important',
  'notifications.filterAll': 'All',
  'notifications.filterEmpty': 'No alerts in this category',

  // About / Updates: status summary phrases
  'about.update.status.checking': 'Checking...',
  'about.update.status.available': 'v{version} available',
  'about.update.status.availableNoVersion': 'Update available',
  'about.update.status.downloading': 'Downloading...',
  'about.update.status.readyToInstall': 'v{version} ready to install',
  'about.update.status.readyToInstallNoVersion':
    'A new version is downloaded and ready. Restart to apply.',
  'about.update.status.installing': 'Installing...',
  'about.update.status.restarting': 'Restarting...',
  'about.update.status.upToDate': 'You are running the latest version.',
  'about.update.status.error': 'Update check failed',
  'about.update.status.default': 'Check for updates',

  // Welcome: connection error messages
  'welcome.connectionFailed': 'Connection failed: {status} {statusText}',
  'welcome.connectionFailedMsg': 'Connection failed: {message}',
  'welcome.continueLocally': 'Continue locally',
  'welcome.continueLocallyExperimental': 'Continue Locally (Experimental)',
  'welcome.localSessionStarting': 'Starting local session...',
  'welcome.localSessionDesc': 'Uses an offline local profile and skips TinyHumans OAuth.',

  // Chat: Agent chat panel description
  'chat.agentChatDesc': 'Open a direct chat session with the agent.',
  'chat.modelPlaceholder': 'gpt-4o',

  // Channels: active route interpolated value
  'channels.activeRouteValue': '{channel} via {authMode}',

  // Privacy: data kind labels for What Leaves My Computer
  'privacy.dataKind.messages': 'Messages',
  'privacy.dataKind.agents': 'Agents',
  'privacy.dataKind.skills': 'Skills',
  'privacy.dataKind.system': 'System',
  'privacy.dataKind.meetings': 'Meetings',
  'privacy.dataKind.reminders': 'Reminders',
  'privacy.dataKind.important': 'Important',

  // Onboarding: supplementary keys
  'onboarding.enableLocalAI': 'Enable Local AI',
  'onboarding.skills.status.available': 'Available',
  'onboarding.skills.status.connected': 'Connected',
  'onboarding.skills.status.connecting': 'Connecting',
  'onboarding.skills.status.error': 'Error',
  'onboarding.skills.status.unavailable': 'Unavailable',

  // Composio: miscellaneous
  'composio.statusUnavailable': 'Status unavailable',
  'composio.authExpired': 'Auth expired',
  'composio.reconnect': 'Reconnect',
  'composio.expiredAuthorization': '{name} authorization expired',
  'composio.expiredDescription':
    'Reconnect to re-enable {name} tools. OpenHuman will keep this integration unavailable until you refresh OAuth access.',
  'composio.envVarOverrides': 'is set, it overrides this setting.',
  'composio.previewBadge': 'Preview',
  'composio.previewTooltip':
    "Agent integration coming soon — you can connect, but the agent can't use this toolkit yet.",

  // Memory: day-of-week labels for heatmap
  'memory.day.sun': 'Sun',
  'memory.day.mon': 'Mon',
  'memory.day.tue': 'Tue',
  'memory.day.wed': 'Wed',
  'memory.day.thu': 'Thu',
  'memory.day.fri': 'Fri',
  'memory.day.sat': 'Sat',

  // Memory: ingestion status labels
  'memory.ingesting': 'Ingesting',
  'memory.ingestionQueued': 'Queued',
  'memory.ingestingTitle': 'Ingesting {title}',

  // Mic: error messages
  'mic.noAudioCaptured': 'No audio captured',
  'mic.noSpeechDetected': 'No speech detected',
  'mic.lowConfidenceResult': 'Could not understand the audio clearly — please try again',
  'mic.failedToStopRecording': 'Failed to stop recording: {message}',
  'mic.transcriptionFailed': 'Transcription failed: {message}',

  // Reflections: kind labels
  'reflections.kind.retrospective': 'Retrospective',
  'reflections.kind.derivedFact': 'Derived Fact',
  'reflections.kind.moodInsight': 'Mood Insight',
  'reflections.kind.relationshipInsight': 'Relationship Insight',

  // Graph: tooltip keys
  'graph.tooltip.summary': 'Summary',
  'graph.tooltip.contact': 'Contact',

  // Local Model: usage labels
  'localModel.usage.never': 'Never',
  'localModel.usage.mediumLoad': 'Medium load',
  'localModel.usage.lowLoad': 'Low load',
  'localModel.usage.idleMode': 'Idle mode',
  'localModel.rebootstrapComplete': 'Model re-bootstrap complete.',
  'localModel.modelsVerified': 'Local models verified.',

  // === i18n migration: extracted strings (auto-merged) ===
  'accounts.addModal.allConnected': 'All connected',
  'accounts.addModal.title': 'Add account',
  'accounts.respondQueue.empty': 'Empty',
  'accounts.respondQueue.hide': 'Hide respond queue',
  'accounts.respondQueue.loadFailed': 'Failed to load respond queue',
  'accounts.respondQueue.loading': 'Loading queue…',
  'accounts.respondQueue.pending': 'Pending',
  'accounts.respondQueue.show': 'Show respond queue',
  'accounts.respondQueue.title': 'Respond queue',
  'accounts.webviewHost.almostReady': 'Almost ready...',
  'accounts.webviewHost.loadTimeout': 'Webview load timeout',
  'accounts.webviewHost.loading': 'Loading {providerName}...',
  'accounts.webviewHost.loadingAccount': 'Loading account',
  'accounts.webviewHost.restoringSession': 'Restoring session...',
  'accounts.webviewHost.retryLoading': 'Retry loading',
  'accounts.webviewHost.takingLonger': '{providerName} is taking longer than expected.',
  'accounts.webviewHost.timeoutHint': 'Timeout hint',
  'app.connectionBadge.composio': 'Composio',
  'app.connectionBadge.messaging': 'Messaging',
  'app.connectionIndicator.connected': 'Connected',
  'app.connectionIndicator.connecting': 'Connecting',
  'app.connectionIndicator.coreOffline': 'Core offline',
  'app.connectionIndicator.disconnected': 'Disconnected',
  'app.connectionIndicator.offline': 'Offline',
  'app.connectionIndicator.reconnecting': 'Reconnecting…',
  'app.errorFallback.componentStack': 'Component stack',
  'app.errorFallback.contactSupport': 'Contact support',
  'app.errorFallback.copyEventId': 'Copy',
  'app.errorFallback.downloadLatest': 'Download latest',
  'app.errorFallback.eventIdCopied': 'Copied',
  'app.errorFallback.eventIdLabel': 'Error ID',
  'app.errorFallback.heading': 'Something went wrong',
  'app.errorFallback.hint':
    'Try reloading the app. If the problem persists, download the latest version.',
  'app.errorFallback.reloadApp': 'Reload app',
  'app.errorFallback.revealLogs': 'Reveal logs',
  'app.errorFallback.subheading': 'An unexpected error occurred',
  'app.errorFallback.tryRecover': 'Try recover',
  'app.localAiDownload.installing': 'Installing...',
  'app.localAiDownload.preparing': 'Preparing...',
  'app.openhumanLink.accounts.continueWith': 'Continue with {label} sign-in',
  'app.openhumanLink.accounts.done': 'Done',
  'app.openhumanLink.accounts.intro':
    'Connect your apps to give OpenHuman access to your accounts.',
  'app.openhumanLink.accounts.webviewNote':
    'Your credentials stay on this device and are never shared.',
  'app.openhumanLink.billing.openDashboard': 'Open dashboard',
  'app.openhumanLink.billing.stayOnTrial': 'Stay on trial',
  'app.openhumanLink.billing.trialCredit': 'Signup credits',
  'app.openhumanLink.billing.trialDesc':
    'Credit offers can vary by promotion and account eligibility.',
  'app.openhumanLink.defaultBody':
    "Not ready in the popup yet. Open the full settings page when you're done.",
  'app.openhumanLink.discord.intro': 'Join the OpenHuman community on Discord.',
  'app.openhumanLink.discord.openInvite': 'Open invite link',
  'app.openhumanLink.discord.perk1': 'Early access to new features',
  'app.openhumanLink.discord.perk2': 'Connect with other OpenHuman users',
  'app.openhumanLink.discord.perk3': 'Share feedback directly with the team',
  'app.openhumanLink.discord.perk4': 'Community help and support',
  'app.openhumanLink.discordReport.intro':
    'Sorry — something broke on our end. We try to log these automatically, but sharing the details on Discord helps us fix it faster.',
  'app.openhumanLink.discordReport.openDiscord': 'Open Discord',
  'app.openhumanLink.done': 'Done',
  'app.openhumanLink.notifications.desktopOnly':
    'Native notifications are only available in the desktop app (run `pnpm dev:app`).',
  'app.openhumanLink.notifications.permissionOff':
    'Notification permission is off. Enable OpenHuman in System Settings → Notifications, then retry.',
  'app.openhumanLink.notifications.triggerFailed':
    'OpenHuman could not trigger a system notification. Check OS notification settings and retry.',
  'app.openhumanLink.notifications.welcomeBody':
    'You will get pings here when something needs your attention.',
  'app.openhumanLink.notifications.welcomeTitle': 'OpenHuman is good to go',
  'app.openhumanLink.status.closed': 'Closed',
  'app.openhumanLink.status.connected': 'Connected',
  'app.openhumanLink.status.error': 'Error',
  'app.openhumanLink.status.loading': 'Loading…',
  'app.openhumanLink.status.needsSignIn': 'Needs sign-in',
  'app.openhumanLink.status.timedOut': 'Timed out',
  'app.openhumanLink.loadingChannelSetup': 'Loading channel setup',
  'app.openhumanLink.maybeLater': 'Maybe later',
  'app.openhumanLink.notifications.asking': 'Asking your OS…',
  'app.openhumanLink.notifications.blocked': 'Notifications blocked',
  'app.openhumanLink.notifications.blockedStep1': 'Open System Settings',
  'app.openhumanLink.notifications.blockedStep2': 'Go to Notifications → OpenHuman',
  'app.openhumanLink.notifications.blockedStep3': 'Enable Allow Notifications',
  'app.openhumanLink.notifications.intro': 'Allow OpenHuman to send you notifications.',
  'app.openhumanLink.notifications.promptHint': 'Click Allow when your system asks for permission.',
  'app.openhumanLink.notifications.retry': 'Retry test notification',
  'app.openhumanLink.notifications.send': 'Send test notification',
  'app.openhumanLink.notifications.sendFailed': "Couldn't send: {error}",
  'app.openhumanLink.notifications.sent':
    "Test notification sent. If you didn't receive it, go to System Settings → Notifications → OpenHuman, turn on Allow Notifications, and set Banner Style to Persistent.",
  'app.openhumanLink.skipForNow': 'Skip for now',
  'app.openhumanLink.telegramUnavailable': 'Telegram unavailable',
  'app.openhumanLink.title.accounts': 'Connect your apps',
  'app.openhumanLink.title.billing': 'Billing & credits',
  'app.openhumanLink.title.discord': 'Join the community',
  'app.openhumanLink.title.discordReport': 'Report this error',
  'app.openhumanLink.title.messaging': 'Connect a chat channel',
  'app.openhumanLink.title.notifications': 'Allow notifications',
  'app.persistRehydration.body': 'Loading your saved settings…',
  'app.persistRehydration.heading': 'Restoring your data',
  'app.persistRehydration.resetCta': 'Resetting…',
  'app.persistRehydration.resetting': 'Resetting…',
  'app.routeLoading.initializing': 'Initializing OpenHuman...',
  'app.update.currentlyOn': '{version}',
  'app.update.errorFallback': 'Something went wrong while updating.',
  'app.update.header.default': 'Update',
  'app.update.header.error': 'Update failed',
  'app.update.header.installing': 'Installing update',
  'app.update.header.readyToInstall': 'Update ready to install',
  'app.update.header.restarting': 'Restarting…',
  'app.update.later': 'Later',
  'app.update.newVersionReady': 'A new version is ready to install.',
  'app.update.progress.downloaded': '${formatBytes(downloaded)} downloaded',
  'app.update.progress.installing': 'Installing the new version…',
  'app.update.progress.restarting': 'Relaunching the app…',
  'app.update.progress.working': '{percent}%',
  'app.update.restartNote': 'The app will restart to apply the update.',
  'app.update.restartNow': 'Restart now',
  'app.update.versionReady': 'Version {newVersion} is ready to install.',
  'channels.discord.accountLinked': 'Account linked',
  'channels.discord.connect': 'Connect',
  'channels.discord.linkTokenExpired': 'Link token expired. Please try again.',
  'channels.discord.linkTokenInstruction': '{token}',
  'channels.discord.linkTokenLabel': 'Link token',
  'channels.discord.linkTokenOnce': 'This token can only be used once.',
  'channels.discord.picker.allPermissionsOk': 'Bot has all required permissions in this channel.',
  'channels.discord.picker.botNotInServers': 'Bot not in servers',
  'channels.discord.picker.category': 'Category',
  'channels.discord.picker.channel': 'Channel',
  'channels.discord.picker.checkingPermissions': 'Checking permissions',
  'channels.discord.picker.loadingChannels': 'Loading channels...',
  'channels.discord.picker.loadingServers': 'Loading servers...',
  'channels.discord.picker.missingPermissions': 'Missing permissions',
  'channels.discord.picker.noChannels': 'No text channels found',
  'channels.discord.picker.noServers': 'No servers found',
  'channels.discord.picker.selectChannel': 'Select a channel',
  'channels.discord.picker.selectServer': 'Select a server',
  'channels.discord.picker.server': 'Server',
  'channels.discord.picker.serverChannelSelection': 'Server & Channel Selection',
  'channels.discord.savedRestartRequired': 'Channel saved. Restart the app to activate it.',
  'channels.telegram.connect': 'Connect',
  'channels.telegram.managedDmConnecting': 'Connecting your Telegram account…',
  'channels.telegram.managedDmTimeout': 'Connection timed out. Please try again.',
  'channels.telegram.reconnect': 'Reconnect',
  'channels.telegram.savedRestartRequired': 'Channel saved. Restart the app to activate it.',
  'channels.web.alwaysAvailable': 'Always available',
  'chat.approval.approve': 'Approve',
  'chat.approval.alwaysAllow': 'Always allow',
  'chat.approval.alwaysAllowHint': 'Stop asking for this tool — add it to your Always-allow list',
  'chat.approval.deciding': 'Working…',
  'chat.approval.deny': 'Deny',
  'chat.approval.error': 'Could not record your decision — try again.',
  'chat.approval.fallback': 'The agent wants to run an action that needs your approval.',
  'chat.approval.title': 'Approval needed',
  'chat.approval.tool': 'Tool:',

  // Auth mode labels
  'channels.authMode.managed_dm': 'Login with OpenHuman',
  'channels.authMode.oauth': 'OAuth Sign-in',
  'channels.authMode.bot_token': 'Use your own Bot Token',
  'channels.authMode.api_key': 'Use your own API Key',

  // Field validation
  'channels.fieldRequired': '{field} is required',

  // MCP (virtual channel)
  'channels.mcp.title': 'MCP Servers',
  'channels.mcp.description':
    'Browse and manage Model Context Protocol servers that extend the AI with new tools.',

  // Discord
  'channels.discord.displayName': 'Discord',
  'channels.discord.description': 'Send and receive messages via Discord.',
  'channels.discord.authMode.bot_token.description': 'Provide your own Discord bot token.',
  'channels.discord.authMode.oauth.description':
    'Install the OpenHuman bot to your Discord server via OAuth.',
  'channels.discord.authMode.managed_dm.description':
    'Link your personal Discord account to the OpenHuman bot.',
  'channels.discord.fields.bot_token.label': 'Bot Token',
  'channels.discord.fields.bot_token.placeholder': 'Your Discord bot token',
  'channels.discord.fields.guild_id.label': 'Server (Guild) ID',
  'channels.discord.fields.guild_id.placeholder': 'Optional: restrict to a specific server',

  // Telegram
  'channels.telegram.displayName': 'Telegram',
  'channels.telegram.description': 'Send and receive messages via Telegram.',
  'channels.telegram.authMode.managed_dm.description':
    'Message the OpenHuman Telegram bot directly.',
  'channels.telegram.authMode.bot_token.description':
    'Provide your own Telegram Bot token from @BotFather.',
  'channels.telegram.fields.bot_token.label': 'Bot Token',
  'channels.telegram.fields.bot_token.placeholder': '123456:ABC-DEF1234ghIkl-zyx57W2v1u123ew11',
  'channels.telegram.fields.allowed_users.label': 'Allowed Users',
  'channels.telegram.fields.allowed_users.placeholder': 'Comma-separated Telegram usernames',
  'channels.telegram.remoteControlTitle': 'Remote control (Telegram)',
  'channels.telegram.remoteControlBody':
    'From an allowed Telegram chat, send /status, /sessions, /new, or /help. Model routing still uses /model and /models.',

  // Web
  'channels.web.displayName': 'Web',
  'channels.web.description': 'Chat via the built-in web UI.',
  'channels.web.authMode.managed_dm.description': 'Use the embedded web chat — no setup required.',
  'channels.yuanbao.connect': 'Connect',
  'channels.yuanbao.connecting': 'Connecting…',
  'channels.yuanbao.fieldRequired': '{field} is required',
  'channels.yuanbao.reconnect': 'Reconnect',
  'channels.yuanbao.savedRestartRequired': 'Channel saved. Restart the app to activate it.',
  'channels.yuanbao.unexpectedStatus': 'Unexpected connection status: {status}',
  'chat.unsubscribeApproval.approve': 'Approve & Unsubscribe',
  'chat.unsubscribeApproval.approved': '✓ Successfully unsubscribed.',
  'chat.unsubscribeApproval.denied': '✕ Request denied.',
  'chat.unsubscribeApproval.deny': 'Deny',
  'chat.unsubscribeApproval.processing': 'Processing...',
  'chat.unsubscribeApproval.title': 'Unsubscribe Request',
  'commandPalette.ariaLabel': 'Command palette',
  'commandPalette.description': 'Description',
  'commandPalette.label': 'Commands',
  'commandPalette.noResults': 'No results',
  'commandPalette.placeholder': 'Type a command or search…',
  'commandPalette.searchAria': 'Search commands',
  'commandPalette.shortcutHint': 'Press ? for all shortcuts',
  'commandPalette.title': 'Command palette',
  'kbd.ariaLabel': 'Keyboard shortcut: {shortcut}',
  'shortcuts.title': 'Keyboard Shortcuts',
  'shortcuts.subtitle': 'Speed up your workflow with these keyboard shortcuts.',
  'shortcuts.menuDesc': 'Browse every app-wide keyboard shortcut.',
  'shortcuts.empty': 'No keyboard shortcuts are available right now.',
  'shortcuts.openHint': 'Open this list anytime with',
  'shortcuts.group.navigation': 'Navigation',
  'shortcuts.group.profiles': 'Profiles',
  'shortcuts.group.chat': 'Chat',
  'shortcuts.group.view': 'View',
  'shortcuts.group.general': 'General',
  'shortcuts.group.help': 'Help',
  'shortcuts.action.home': 'Go Home',
  'shortcuts.action.chat': 'Go to Chat',
  'shortcuts.action.knowledge': 'Go to Knowledge & Memory',
  'shortcuts.action.connections': 'Go to Connections',
  'shortcuts.action.activity': 'Go to Activity',
  'shortcuts.action.settings': 'Open Settings',
  'shortcuts.action.newChat': 'New Chat',
  'shortcuts.action.toggleSidebar': 'Toggle Sidebar',
  'shortcuts.action.commandPalette': 'Command Palette',
  'iosMascot.connectedTo': 'Connected to',
  'iosMascot.defaultPairedLabel': 'Desktop',
  'iosMascot.disconnect': 'Disconnect',
  'iosMascot.error.generic': 'Something went wrong. Please try again.',
  'iosMascot.error.sendFailed': 'Failed to send. Check your connection.',
  'iosMascot.pushToTalk': 'Push to talk',
  'iosMascot.sendMessage': 'Send message',
  'iosMascot.thinking': 'Thinking...',
  'iosMascot.typeMessage': 'Type a message...',
  'iosPair.connectedLoading': 'Connected! Loading...',
  'iosPair.connecting': 'Connecting to desktop...',
  'iosPair.desktopLabel': 'Desktop',
  'iosPair.error.camera': 'Camera scan failed. Check camera permissions and try again.',
  'iosPair.error.connectionFailed':
    'Connection failed. Make sure the desktop app is running and try again.',
  'iosPair.error.invalidQr':
    'Invalid QR code. Make sure you are scanning an OpenHuman pairing code.',
  'iosPair.error.unreachableDesktop':
    'Could not reach the desktop. Make sure both devices are online and try again.',
  'iosPair.expired': 'QR code expired. Ask the desktop to regenerate the code.',
  'iosPair.instructions':
    'Open OpenHuman on your desktop, go to Settings > Devices, and tap "Pair phone" to show the QR code.',
  'iosPair.retryScan': 'Retry scan',
  'iosPair.scanQrCode': 'Scan QR code',
  'iosPair.scannerOpening': 'Scanner opening...',
  'iosPair.step.openDesktop': 'Open OpenHuman on desktop',
  'iosPair.step.openSettings': 'Go to Settings > Devices',
  'iosPair.step.showQr': 'Tap "Pair phone" to show QR',
  'iosPair.title': 'Pair with your desktop',
  'composio.connect.additionalConfigRequired': 'Additional config required',
  'composio.connect.atlassianSubdomainHint': 'acme',
  'composio.connect.atlassianSubdomainLabel': 'Atlassian subdomain',
  'composio.connect.connect': 'Connect',
  'composio.connect.connectedAccounts': 'Connected accounts',
  'composio.connect.defaultLabel': 'Default',
  'composio.connect.disconnectAccount': 'Remove',
  'composio.connect.addAnotherAccount': 'Add another account',
  'composio.connect.dynamicsOrgNameHint':
    'For example, "myorg" for myorg.crm.dynamics.com. Enter the short org name only, not the full URL.',
  'composio.connect.dynamicsOrgNameLabel': 'Dynamics 365 Organization Name',
  'composio.connect.connectionFailed': 'Connection failed (status: {status}).',
  'composio.connect.disconnectFailed': 'Disconnect failed: {msg}',
  'composio.connect.disconnecting': 'Disconnecting…',
  'composio.connect.idleDescription': 'Connect your',
  'composio.connect.idleDescriptionSuffix':
    "account. We'll open a browser window, you approve access there, and this app will detect the connection automatically.",
  'composio.connect.isConnected': 'is connected.',
  'composio.connect.manage': 'Manage',
  'composio.connect.needsFieldsPrefix': 'To connect',
  'composio.connect.needsFieldsSuffix':
    'we need a bit more information. Fill in the missing fields below and try again.',
  'composio.connect.needsSubdomain': 'To connect',
  'composio.connect.needsSubdomainSuffix':
    'enter your Atlassian subdomain (e.g. acme for acme.atlassian.net) and try again.',
  'composio.connect.oauthComplete': 'OAuth to complete…',
  'composio.connect.oauthTimeout': 'OAuth timed out. Please try again.',
  'composio.connect.permissions': 'Permissions',
  'composio.connect.permissionsDefault': 'Read + Write enabled by default',
  'composio.connect.permissionsNote': 'can expose',
  'composio.connect.permissionsNoteSuffix':
    "OpenHuman's own agent permissions are controlled below as read, write, and admin toggles.",
  'composio.connect.reopenBrowser': 'Reopen browser',
  'composio.connect.requestingUrl': 'Requesting connect URL…',
  'composio.connect.requiredFieldEmpty': 'This field is required.',
  'composio.connect.retryConnection': 'Retry connection',
  'composio.connect.scopeLoadError': "Couldn't load scope preferences: {msg}",
  'composio.connect.scopeSaveError': "Couldn't save {key} scope: {msg}",
  'composio.connect.scope.read': 'Read',
  'composio.connect.scope.readHint': 'Allow the agent to read data from this connection.',
  'composio.connect.scope.write': 'Write',
  'composio.connect.scope.writeHint':
    'Allow the agent to create or modify data through this connection.',
  'composio.connect.scope.admin': 'Admin',
  'composio.connect.scope.adminHint':
    'Allow the agent to manage settings, permissions, or destructive actions.',
  'composio.connect.subdomainInvalid':
    'Enter the short subdomain only (e.g. "acme"), not the full URL. It should contain only letters, numbers, and hyphens.',
  'composio.connect.subdomainRequired': 'Please enter your Atlassian subdomain to continue.',
  'composio.connect.wabaIdHint':
    'Find it via GET /me/businesses then GET /{business_id}/owned_whatsapp_business_accounts using your Meta access token.',
  'composio.connect.wabaIdLabel': 'WhatsApp Business Account ID (WABA ID)',
  'composio.connect.atlassianSubdomainPlaceholder': 'your-subdomain',
  'composio.connect.dynamicsOrgNamePlaceholder': 'myorg',
  'composio.connect.wabaIdPlaceholder': 'e.g. 123456789012345',
  'composio.connect.wabaIdRequired':
    'Please enter your WhatsApp Business Account ID (WABA ID) to continue.',
  'composio.connect.waitingFor': 'Waiting for',
  'composio.connect.waitingHint': 'Complete the connection in the browser window that just opened.',
  'composio.triggers.heading': 'Triggers',
  'composio.triggers.listenFrom': 'Listen for events from',
  'composio.triggers.loadError': "Couldn't load triggers",
  'composio.triggers.sessionExpired':
    'Your OpenHuman session expired. Sign in again to load triggers.',
  'composio.triggers.needsConfiguration': 'Needs configuration',
  'composio.triggers.noneAvailable': 'No triggers are currently available for',
  'conversations.taskKanban.moveLeft': 'Move left',
  'conversations.taskKanban.moveRight': 'Move right',
  'conversations.taskKanban.title': 'Tasks',
  'conversations.threadTodo.title': 'Plan',
  'conversations.planReview.title': 'Review plan',
  'conversations.planReview.subtitle':
    'Approve to run it, reject to discard, or send feedback to revise.',
  'conversations.planReview.approve': 'Approve & run',
  'conversations.planReview.reject': 'Reject',
  'conversations.planReview.feedbackLabel': 'Request changes',
  'conversations.planReview.feedbackPlaceholder': 'Describe what to change…',
  'conversations.planReview.sendFeedback': 'Send feedback',
  // Thread-level goal chip (Codex-style per-thread completion contract).
  'conversations.threadGoal.label': 'Goal',
  'conversations.threadGoal.setCta': 'Set goal',
  'conversations.threadGoal.placeholder': 'What should this thread accomplish?',
  'conversations.threadGoal.save': 'Save',
  'conversations.threadGoal.cancel': 'Cancel',
  'conversations.threadGoal.edit': 'Edit goal',
  'conversations.threadGoal.clear': 'Clear goal',
  'conversations.threadGoal.complete': 'Mark complete',
  'conversations.threadGoal.pause': 'Pause',
  'conversations.threadGoal.resume': 'Resume',
  'conversations.threadGoal.tokensSuffix': 'tokens',
  'conversations.threadGoal.status.active': 'Active',
  'conversations.threadGoal.status.paused': 'Paused',
  'conversations.threadGoal.status.budget_limited': 'Budget reached',
  'conversations.threadGoal.status.complete': 'Complete',
  'conversations.taskKanban.approval.default': 'Default',
  'conversations.taskKanban.approval.notRequired': 'Not required',
  'conversations.taskKanban.approval.notRequiredBadge': 'no approval',
  'conversations.taskKanban.approval.required': 'Required',
  'conversations.taskKanban.approval.requiredBadge': 'approval',
  'conversations.taskKanban.approval.requiredBeforeExecution': 'Required before execution',
  'conversations.taskKanban.briefButton': 'Task brief',
  'conversations.taskKanban.briefTitle': 'Task brief',
  'conversations.taskKanban.closeBrief': 'Close task brief',
  'conversations.taskKanban.field.acceptanceCriteria': 'Acceptance criteria',
  'conversations.taskKanban.field.allowedTools': 'Allowed tools',
  'conversations.taskKanban.field.approval': 'Approval',
  'conversations.taskKanban.field.assignedAgent': 'Assigned agent',
  'conversations.taskKanban.field.blocker': 'Blocker',
  'conversations.taskKanban.field.evidence': 'Evidence',
  'conversations.taskKanban.field.notes': 'Notes',
  'conversations.taskKanban.field.objective': 'Objective',
  'conversations.taskKanban.field.plan': 'Plan',
  'conversations.taskKanban.field.status': 'Status',
  'conversations.taskKanban.field.title': 'Title',
  'conversations.taskKanban.saveChanges': 'Save changes',
  'conversations.taskKanban.deleteCard': 'Delete',
  'conversations.taskKanban.workTask': 'Work task',
  'conversations.taskKanban.viewWork': 'View work',
  'conversations.taskKanban.startingTask': 'Starting…',
  'conversations.taskKanban.updateFailed': 'Could not update task; changes were not saved.',
  'conversations.taskKanban.sourcesButton': 'Sources',
  'conversations.taskKanban.source.openExternal': 'Open external task',
  'conversations.taskKanban.source.openExternalShort': 'Open',
  'conversations.taskKanban.source.unknownProvider': 'Unknown source',
  'conversations.taskKanban.source.urgencyValue': 'Urgency {percent}%',
  'conversations.taskKanban.sources.desktopOnly':
    'Task source controls are available in the desktop app.',
  'conversations.taskKanban.sources.title': 'Task sources',
  'conversations.taskKanban.sources.statusEnabled': 'Automatic polling enabled',
  'conversations.taskKanban.sources.manage': 'Manage sources',
  'conversations.taskKanban.source.title': 'Source',
  'conversations.taskKanban.source.sourceId': 'Source ID',
  'conversations.taskKanban.source.externalId': 'External ID',
  'conversations.taskKanban.source.repo': 'Repository',
  'conversations.taskKanban.source.urgency': 'Urgency',
  'conversations.toolTimeline.turn': 'turn',
  'conversations.toolTimeline.step': 'step',
  'conversations.toolTimeline.workerThread': 'worker thread',
  'conversations.subagent.viewProcessing': 'View full processing',
  'conversations.subagent.parent': 'Parent',
  'conversations.subagent.thinking': 'Thinking',
  'conversations.subagent.thoughts': 'Thoughts',
  'conversations.subagent.response': 'Response',
  'conversations.subagent.toolCalls': 'Tool calls',
  'conversations.subagent.working': 'Working…',
  'conversations.subagent.noOutputYet': 'No output yet',
  'conversations.subagent.input': 'Input',
  'conversations.subagent.output': 'Output',
  'conversations.subagent.noOutput': 'No output returned',
  'conversations.subagent.close': 'Close',
  'conversations.subagent.cancel': 'Cancel task',
  'conversations.subagent.cancelling': 'Cancelling…',
  'conversations.subagent.cancelFailed': "Couldn't cancel the task. Try again.",
  'conversations.backgroundTasks.title': 'Background tasks',
  'conversations.backgroundTasks.titleWithCount': 'Background tasks ({count})',
  'conversations.backgroundTasks.running': '{count} running',
  'conversations.backgroundTasks.noneRunning': 'none running',
  'conversations.backgroundTasks.total': '{count} total',
  'conversations.backgroundTasks.empty':
    'No background tasks in this chat. Ask the assistant to do something in the background and it shows up here.',
  'conversations.backgroundTasks.statusRunning': 'Running',
  'conversations.backgroundTasks.statusDone': 'Done',
  'conversations.backgroundTasks.statusFailed': 'Failed',
  'conversations.backgroundTasks.statusNeedsYou': 'Needs you',
  'conversations.backgroundTasks.statusCancelled': 'Cancelled',
  'conversations.backgroundTasks.toolCallOne': '{count} tool call',
  'conversations.backgroundTasks.toolCallOther': '{count} tool calls',
  'conversations.backgroundTasks.steps': '{count} steps',
  'conversations.backgroundTasks.viewDetails': 'View details →',
  'conversations.backgroundTasks.close': 'Close',
  // Section headers for the broader background-activity panel.
  'conversations.backgroundTasks.sectionThisChat': 'In this chat',
  'conversations.backgroundTasks.sectionScheduled': 'Scheduled jobs',
  'conversations.backgroundTasks.sectionSubconscious': 'Subconscious thinking',
  'conversations.backgroundTasks.sectionMemory': 'Memory syncing',
  // Scheduled (cron) jobs.
  'conversations.backgroundTasks.cronEmpty': 'No scheduled jobs.',
  'conversations.backgroundTasks.cronUnnamed': 'Untitled job',
  'conversations.backgroundTasks.cronPaused': 'Paused',
  'conversations.backgroundTasks.cronNext': 'Next {time}',
  'conversations.backgroundTasks.cronLast': 'Last run {time}',
  'conversations.backgroundTasks.cronNever': 'Hasn’t run yet',
  'conversations.backgroundTasks.cronSchedCron': 'Cron {expr}',
  'conversations.backgroundTasks.cronSchedEvery': 'Every {duration}',
  'conversations.backgroundTasks.cronSchedAt': 'Once',
  // Subconscious / heartbeat loop.
  'conversations.backgroundTasks.subOff': 'Off',
  'conversations.backgroundTasks.subWorking': 'Working…',
  'conversations.backgroundTasks.subIdle': 'Idle',
  'conversations.backgroundTasks.subLastRan': 'Last ran {time}',
  'conversations.backgroundTasks.subNeverRan': 'Hasn’t run yet',
  'conversations.backgroundTasks.subTicks': '{count} runs',
  'conversations.backgroundTasks.subQueued': '{count} queued',
  // Memory syncing / ingestion.
  'conversations.backgroundTasks.memUpToDate': 'All memories up to date',
  'conversations.backgroundTasks.memIngesting': 'Indexing {title}',
  'conversations.backgroundTasks.memIngestingUntitled': 'Indexing memories',
  'conversations.backgroundTasks.memQueued': '{count} queued',
  'conversations.backgroundTasks.memProviderActive': 'Syncing now',
  'conversations.backgroundTasks.memProviderRecent': 'Synced recently',
  'conversations.backgroundTasks.memProviderIdle': 'Idle',
  'conversations.subagent.statusRunning': 'running',
  'conversations.subagent.statusCompleted': 'completed',
  'conversations.subagent.statusFailed': 'failed',
  'conversations.subagent.statusAwaitingUser': 'awaiting user',
  'conversations.subagent.statusCancelled': 'cancelled',
  'conversations.agentTaskInsights.title': 'Agentic task insights',
  'conversations.agentTaskInsights.response': 'Response',
  'conversations.agentTaskInsights.processSourceTitle': 'Agent Process Source',
  'conversations.agentTaskInsights.stepsHeading': 'Steps',
  'conversations.agentTaskInsights.sourcesHeading': 'Sources',
  'conversations.agentTaskInsights.noSteps': 'No steps recorded',
  'conversations.agentTaskInsights.viewProcessSource': 'View full agent process Source',
  'conversations.agentTaskInsights.processing': 'Processing',
  'conversations.agentTaskInsights.done': 'Done',
  'conversations.agentTaskInsights.failed': 'Failed',
  'conversations.agentTaskInsights.running': 'Running',
  'conversations.agentTaskInsights.cancelled': 'Cancelled',
  'conversations.agentTaskInsights.awaitingUser': 'Awaiting input',
  'conversations.agentTaskInsights.viewDetails': 'View details',
  'conversations.agentTaskInsights.subagentsHeading': 'Sub-agents',
  'daemon.serviceBlockingGate.body':
    'Retrying in the background. This usually resolves in a few seconds.',
  'daemon.serviceBlockingGate.downloadHint':
    'If this keeps happening, download the latest version.',
  'daemon.serviceBlockingGate.downloadLatest': 'Download Latest Version',
  'daemon.serviceBlockingGate.retryCore': 'Retry Core',
  'daemon.serviceBlockingGate.retryFailed':
    'Retry failed. Download the latest app build and try again.',
  'daemon.serviceBlockingGate.retrying': 'Retrying...',
  'daemon.serviceBlockingGate.title': 'OpenHuman core is unavailable',
  'home.banners.discordSubtitle': 'get support, share feedback, and meet the community.',
  'home.banners.discordTitle': 'Join our Discord',
  'home.banners.earlyBirdDismiss': 'Dismiss early bird banner',
  'home.banners.earlyBirdFirstSub': 'first subscription.',
  'home.banners.earlyBirdOn': 'Early bird on',
  'home.banners.earlyBirdTitle': 'The first 1,000 users get 60% off.',
  'home.banners.earlyBirdUseCode': 'Use code',
  'home.banners.getSubscription': 'get a subscription',
  'home.banners.promoCreditsBody': 'You have {amount} in promo credits. You can',
  'home.banners.promoCreditsUsage': 'and put them toward any AI workload.',
  'intelligence.memoryChunk.detail.chunk': 'Chunk',
  'intelligence.memoryChunk.detail.copyChunkId': 'Copy chunk id',
  'intelligence.memoryChunk.detail.embeddingInfo': 'bge-m3 1024dim',
  'intelligence.memoryChunk.detail.noEmbedding': 'No embedding',
  'intelligence.memoryChunk.letterhead.from': 'from',
  'intelligence.memoryChunk.letterhead.to': 'to',
  'intelligence.memoryChunk.mentioned.chunkOne': '1 chunk',
  'intelligence.memoryChunk.mentioned.chunkOther': '{count} chunks',
  'intelligence.memoryChunk.mentioned.heading': 'm e n t i o n e d',
  'intelligence.memoryChunk.scoreBars.ariaScore': '{name} score {pct} percent',
  'intelligence.memoryChunk.scoreBars.atThreshold': 'at {threshold}',
  'intelligence.memoryChunk.scoreBars.dropped': 'dropped',
  'intelligence.memoryChunk.scoreBars.heading': 'w h y   k e p t',
  'intelligence.memoryChunk.scoreBars.kept': 'kept',
  'intelligence.diagram.title': 'Architecture Diagram',
  'intelligence.diagram.description':
    'Latest local architecture output from the configured diagram endpoint.',
  'intelligence.diagram.refresh': 'Refresh',
  'intelligence.diagram.refreshAria': 'Refresh diagram',
  'intelligence.diagram.emptyTitle': 'No diagram available yet',
  'intelligence.diagram.emptyDescription':
    'Generate an architecture diagram from the orchestrator and this panel will refresh from the configured local endpoint.',
  'intelligence.diagram.skillInstallCommand': 'npx skills add yizhiyanhua-ai/fireworks-tech-graph',
  'intelligence.diagram.promptExample':
    'Generate an architecture diagram of the current swarm in dark terminal style',
  'intelligence.diagram.imageAlt': 'Latest generated OpenHuman architecture diagram',
  'intelligence.diagram.refreshesEvery': 'Refreshes every {seconds}s',
  'intelligence.memoryText.entityTypePrefix': 'Entity type',
  'intelligence.screenDebug.active': 'Active',
  'intelligence.screenDebug.app': 'App',
  'intelligence.screenDebug.bounds': 'Bounds',
  'intelligence.screenDebug.captureAlt': 'Capture test result',
  'intelligence.screenDebug.captureFailed': 'Failed',
  'intelligence.screenDebug.captureSuccess': 'Success',
  'intelligence.screenDebug.captureTest': 'Capture test',
  'intelligence.screenDebug.capturing': 'Capturing',
  'intelligence.screenDebug.frames': 'Frames',
  'intelligence.screenDebug.idle': 'Idle',
  'intelligence.screenDebug.lastApp': 'Last App',
  'intelligence.screenDebug.mode': 'Mode',
  'intelligence.screenDebug.permAccessibility': 'Perm accessibility',
  'intelligence.screenDebug.permInput': 'Perm input',
  'intelligence.screenDebug.permScreen': 'Accessibility',
  'intelligence.screenDebug.permissions': 'Permissions',
  'intelligence.screenDebug.platformNotSupported': 'Platform not supported',
  'intelligence.screenDebug.recentVisionSummaries': 'Recent vision summaries',
  'intelligence.screenDebug.session': 'Session',
  'intelligence.screenDebug.size': 'Size',
  'intelligence.screenDebug.status': 'Status',
  'intelligence.screenDebug.testCapture': 'Test capture',
  'intelligence.screenDebug.time': 'Time',
  'intelligence.screenDebug.title': 'Title',
  'intelligence.screenDebug.unknown': 'Unknown',
  'intelligence.screenDebug.visionQueue': 'Vision Queue',
  'intelligence.screenDebug.visionState': 'Vision State',
  'intelligence.tasks.activeBoardOne': '1 active board across conversations',
  'intelligence.tasks.activeBoardOther': '{count} active boards across conversations',
  'intelligence.tasks.empty': 'No agent task boards yet',
  'intelligence.tasks.emptyHint':
    'Task boards appear here when your agent is running multi-step jobs.',
  'intelligence.tasks.failedToLoad': 'Failed to load',
  'intelligence.tasks.live': 'live',
  'intelligence.tasks.loadingBoards': 'Loading task boards…',
  'intelligence.tasks.threadPrefix': 'Thread {thread}',
  'intelligence.tasks.subtitle': 'Your tasks and agent task boards across the workspace.',
  'intelligence.tasks.newTask': 'New task',
  'intelligence.tasks.personalBoardTitle': 'Agent Tasks',
  'intelligence.tasks.personalEmpty': 'No personal tasks yet',
  'intelligence.tasks.composer.title': 'New task',
  'intelligence.tasks.composer.titleLabel': 'Title',
  'intelligence.tasks.composer.titlePlaceholder': 'What needs to be done?',
  'intelligence.tasks.composer.statusLabel': 'Status',
  'intelligence.tasks.composer.attachLabel': 'Attach to conversation',
  'intelligence.tasks.composer.attachNone': 'Personal (no conversation)',
  'intelligence.tasks.composer.objectiveLabel': 'Objective',
  'intelligence.tasks.composer.objectivePlaceholder': 'Optional — the desired outcome',
  'intelligence.tasks.composer.notesLabel': 'Notes',
  'intelligence.tasks.composer.notesPlaceholder': 'Optional notes',
  'intelligence.tasks.composer.create': 'Create task',
  'intelligence.tasks.composer.creating': 'Creating…',
  'intelligence.tasks.composer.createFailed': "Couldn't create the task",
  'intelligence.tasks.composer.assignAgentLabel': 'Let an agent work on this automatically',
  'intelligence.tasks.composer.assignAgentHint':
    'The task board picks it up and runs it for you. Leave off for a plain personal to-do.',
  'intelligence.tasks.sourceList.subtitle': 'Source tasks waiting to become agent work.',
  'intelligence.tasks.sourceList.empty': 'No source tasks waiting.',
  'intelligence.tasks.sourceList.queued': 'Queued',
  'intelligence.tasks.sourceList.workOnTask': 'Work on task',
  'intelligence.tasks.sourcePlan.title': 'Refine source task',
  'intelligence.tasks.sourcePlan.subtitle':
    'Review the research draft before creating an agent task.',
  'intelligence.tasks.sourcePlan.researchAgent': 'Research agent draft',
  'intelligence.tasks.sourcePlan.approve': 'Approve Plan',
  'intelligence.tasks.sourcePlan.creating': 'Creating task…',
  'intelligence.tasks.sourcePlan.createFailed': "Couldn't create the agent task",
  'intelligence.tasks.workTaskFailed': "Couldn't start work on the task",
  'intelligence.workTask.sourceTaskHeading': 'Source task:',
  'intelligence.workTask.repositoryLine': '- Repository: {repo}',
  'intelligence.workTask.externalIdLine': '- External ID: {externalId}',
  'intelligence.workTask.urlLine': '- URL: {url}',
  'intelligence.workTask.closingInstruction':
    'Start by restating the concrete implementation plan briefly, then execute it. Keep progress visible in this thread and update the task board when the work state changes.',
  'intelligence.agentWork.subtitle': 'Every background agent run, grouped by lifecycle state.',
  'intelligence.agentWork.loading': 'Loading agent work…',
  'intelligence.agentWork.failedToLoad': 'Failed to load agent work',
  'intelligence.agentWork.empty': 'No background agent runs yet.',
  'intelligence.agentWork.bucket.needsInput': 'Needs input',
  'intelligence.agentWork.bucket.working': 'Working',
  'intelligence.agentWork.bucket.completed': 'Completed',
  'intelligence.agentWork.bucket.failed': 'Failed',
  'intelligence.agentWork.bucket.stopped': 'Stopped',
  'intelligence.agentWork.column.agent': 'Agent',
  'intelligence.agentWork.column.status': 'Status',
  'intelligence.agentWork.column.elapsed': 'Elapsed',
  'intelligence.agentWork.column.cost': 'Cost',
  'intelligence.agentWork.column.tokens': 'Tokens',
  'intelligence.agentWork.status.pending': 'Pending',
  'intelligence.agentWork.status.running': 'Running',
  'intelligence.agentWork.status.awaitingUser': 'Awaiting input',
  'intelligence.agentWork.status.paused': 'Paused',
  'intelligence.agentWork.status.completed': 'Completed',
  'intelligence.agentWork.status.failed': 'Failed',
  'intelligence.agentWork.status.cancelled': 'Cancelled',
  'intelligence.agentWork.status.interrupted': 'Interrupted',
  'intelligence.agentWork.kind.subagent': 'Subagent',
  'intelligence.agentWork.kind.workerThread': 'Worker thread',
  'intelligence.agentWork.kind.backgroundAgent': 'Background agent',
  'intelligence.agentWork.kind.teamMember': 'Team member',
  'intelligence.agentWork.kind.workflowChild': 'Workflow child',
  'intelligence.agentWork.openThread': 'Open thread',
  'intelligence.agentWork.openWorker': 'Open worker',
  // Worktree manager (#3376) — isolated worker git worktrees
  'worktree.label': 'Worktree',
  'worktree.dirty': 'Uncommitted changes',
  'worktree.clean': 'Clean',
  'worktree.changedFile': 'changed file',
  'worktree.changedFiles': 'changed files',
  'worktree.removing': 'Removing…',
  'worktree.removeFailed': 'Failed to remove worktree',
  'worktree.diffFailed': 'Failed to load diff',
  'worktree.diffLoading': 'Loading diff…',
  'worktree.diffEmpty': 'No changes vs HEAD.',
  'worktree.dirtyConfirm':
    'This worktree has uncommitted changes. Removing it discards that work. The worker branch is kept.',
  'worktree.action.open': 'Open folder',
  'worktree.action.diff': 'Diff',
  'worktree.action.hideDiff': 'Hide diff',
  'worktree.action.remove': 'Remove',
  'worktree.action.removeAnyway': 'Discard & remove',
  'worktree.action.preserve': 'Preserve',
  'worktree.panel.subtitle': 'Isolated git worktrees created by parallel agent workers.',
  'worktree.panel.loading': 'Loading worktrees…',
  'worktree.panel.failedToLoad': 'Failed to load worktrees',
  'worktree.panel.empty':
    'No isolated worktrees. Parallel workers with worktree isolation will appear here.',
  'worktree.panel.overlapsTitle': 'Overlapping changes',
  'worktree.panel.overlapHint':
    'These files were changed by more than one worktree — reconcile before merging.',
  'intelligence.agentWork.action.stop': 'Stop',
  'intelligence.agentWork.action.retry': 'Retry',
  'intelligence.agentWork.action.continue': 'Continue',
  'intelligence.agentWork.action.followUp': 'Follow up',
  'intelligence.agentWork.action.send': 'Send',
  'intelligence.agentWork.action.cancel': 'Cancel',
  'intelligence.agentWork.action.continuePlaceholder': 'Reply to unblock this agent…',
  'intelligence.agentWork.action.followUpPlaceholder': 'Send a follow-up instruction…',
  'intelligence.agentWork.action.failed': 'Action failed',
  // Orchestration tab (#3375) — multi-agent workflow runs.
  'orchestration.subtitle':
    'Start a multi-agent workflow, watch its phases progress, and read the synthesized result.',
  'orchestration.loading': 'Loading workflows…',
  'orchestration.failedToLoad': 'Failed to load workflows',
  'orchestration.definitions': 'Available workflows',
  'orchestration.noDefinitions': 'No workflow definitions are available.',
  'orchestration.approvalRequired': 'Approval required',
  'orchestration.start': 'Start',
  'orchestration.confirmStart': 'Start run',
  'orchestration.starting': 'Starting…',
  'orchestration.questionLabel': 'Research question (optional)',
  'orchestration.questionPlaceholder': 'What should the agents research?',
  'orchestration.runProgress': 'Run progress',
  'orchestration.recentRuns': 'Recent runs',
  'orchestration.noRuns': 'No workflow runs yet.',
  'orchestration.close': 'Close',
  'orchestration.tier.readOnly': 'Read-only',
  'orchestration.tier.standard': 'Standard',
  'orchestration.tier.editCapable': 'Edit-capable',
  'orchestration.approval.title': 'Approve this workflow run',
  'orchestration.approval.body':
    'This is a high-cost or high-concurrency run and needs your explicit approval before it starts:',
  'orchestration.approval.reason.tier': 'Its agents can take actions beyond read-only research.',
  'orchestration.approval.reason.concurrency': 'It runs many agents at the same time.',
  'orchestration.approval.reason.children': 'It can spawn a large number of agents in total.',
  'orchestration.approval.tier': 'Safety tier',
  'orchestration.approval.concurrency': 'Concurrency',
  'orchestration.approval.maxChildren': 'Max agents',
  'orchestration.approval.approve': 'Approve & start',
  'orchestration.approval.starting': 'Starting…',
  'orchestration.approval.cancel': 'Cancel',
  'orchestration.runStatus.pending': 'Pending',
  'orchestration.runStatus.running': 'Running',
  'orchestration.runStatus.completed': 'Completed',
  'orchestration.runStatus.failed': 'Failed',
  'orchestration.runStatus.cancelled': 'Cancelled',
  'orchestration.runStatus.interrupted': 'Interrupted',
  'orchestration.phaseStatus.pending': 'Pending',
  'orchestration.phaseStatus.running': 'Running',
  'orchestration.phaseStatus.completed': 'Completed',
  'orchestration.phaseStatus.failed': 'Failed',
  'orchestration.detail.stop': 'Stop',
  'orchestration.detail.resume': 'Resume',
  'orchestration.detail.agents': 'agents',
  'orchestration.detail.childRefs': 'Child agents',
  'orchestration.detail.synthesis': 'Final synthesis',
  'tinyplaceOrchestration.title': 'TinyPlace relay',
  'tinyplaceOrchestration.subtitle': 'Pinned agent channels and app-session chats',
  'tinyplaceOrchestration.refresh': 'Refresh',
  'tinyplaceOrchestration.pinned': 'Pinned',
  'tinyplaceOrchestration.sessions': 'Sessions',
  'tinyplaceOrchestration.loading': 'Loading TinyPlace chats…',
  'tinyplaceOrchestration.paymentRequired': 'TinyPlace access requires payment.',
  'tinyplaceOrchestration.failedToLoad': 'Failed to load TinyPlace chats',
  'tinyplaceOrchestration.noSessions': 'No TinyPlace app sessions yet.',
  'tinyplaceOrchestration.noMessages': 'No messages in this chat yet.',
  'tinyplaceOrchestration.active': 'Active',
  'tinyplaceOrchestration.inactive': 'Inactive',
  'tinyplaceOrchestration.encryptedBody': 'Encrypted TinyPlace message',
  'tinyplaceOrchestration.unknownSender': 'Unknown sender',
  'tinyplaceOrchestration.master.title': 'Agent / human',
  'tinyplaceOrchestration.master.subtitle': 'Master chat',
  'tinyplaceOrchestration.master.preview': 'Direct coordination between you and OpenHuman.',
  'tinyplaceOrchestration.subconscious.title': 'Subconscious',
  'tinyplaceOrchestration.subconscious.subtitle': 'Internal agent chats',
  'tinyplaceOrchestration.subconscious.preview': 'Background agent coordination and memory loops.',
  'tinyplaceOrchestration.session.subtitle': 'TinyPlace app session',
  'tinyplaceOrchestration.pairing.linkLabel': 'Link session',
  'tinyplaceOrchestration.pairing.linkPlaceholder': 'Paste session agent ID',
  'tinyplaceOrchestration.pairing.linkAction': 'Link',
  'tinyplaceOrchestration.pairing.requests': 'Contact requests',
  'tinyplaceOrchestration.pairing.accept': 'Accept',
  'tinyplaceOrchestration.pairing.decline': 'Decline',
  'tinyplaceOrchestration.pairing.block': 'Block',
  'tinyplaceOrchestration.pairing.linked': 'Linked',
  'tinyplaceOrchestration.pairing.pending': 'Pending',
  'tinyplaceOrchestration.pairing.unlinked': 'Unlinked',
  'tinyplaceOrchestration.pairing.incoming': 'Incoming',
  'tinyplaceOrchestration.pairing.outgoing': 'Outgoing',
  'intelligence.teams.subtitle': 'Coordinated agent teams and the tasks they share.',
  'intelligence.teams.loading': 'Loading teams…',
  'intelligence.teams.failedToLoad': 'Failed to load teams',
  'intelligence.teams.empty': 'No agent teams yet',
  'intelligence.teams.emptyHint':
    'Teams appear here when an agent spawns coordinated sub-agents to share a goal.',
  'intelligence.teams.refresh': 'Refresh',
  'intelligence.teams.backToList': 'All teams',
  'intelligence.teams.status.active': 'Active',
  'intelligence.teams.status.closed': 'Closed',
  'intelligence.teams.header.lead': 'lead',
  'intelligence.teams.header.taskCount': '{count} tasks',
  'intelligence.teams.header.memberCount': '{count} members',
  'intelligence.teams.member.active': 'Active',
  'intelligence.teams.member.pending': 'Pending',
  'intelligence.teams.member.idle': 'Idle',
  'intelligence.teams.member.stopped': 'Stopped',
  'intelligence.teams.column.todo': 'To do',
  'intelligence.teams.column.ready': 'Ready',
  'intelligence.teams.column.inProgress': 'In progress',
  'intelligence.teams.column.blocked': 'Blocked',
  'intelligence.teams.column.done': 'Done',
  'intelligence.teams.emptyColumn': 'Empty',
  'intelligence.teams.unclaimed': 'Unclaimed',
  'intelligence.teams.pickedUpBy': 'Picked up by {name}',
  'intelligence.teams.depLockTitle': '{count} unmet dependencies',
  'intelligence.teams.gate.pending': 'Gate pending',
  'intelligence.teams.gate.passed': 'Gate passed',
  'intelligence.teams.gate.failed': 'Gate failed',
  'intelligence.teams.gate.label': 'Gate: {status}',
  'intelligence.teams.activity.title': 'Team activity',
  'intelligence.teams.activity.empty': 'No messages yet',
  'intelligence.teams.activity.toTeam': 'team',
  'intelligence.teams.member.start': 'Start',
  'intelligence.teams.composer.placeholder': 'Message a teammate…',
  'intelligence.teams.composer.send': 'Send',
  'intelligence.teams.composer.recipient': 'Recipient',
  'intelligence.teams.composer.toTeam': 'Whole team',
  'intelligence.teams.action.blocked': 'Waiting on dependencies',
  'intelligence.teams.action.alreadyClaimed': 'Already claimed by another teammate',
  'intelligence.teams.action.alreadyActive': 'Teammate is already running',
  'intelligence.teams.action.noClaimableTask': 'No task ready for this teammate',
  'intelligence.teams.action.unknownTask': 'Task not found',
  'intelligence.refine.objectiveDefault':
    'Turn the source task into an implementation-ready agent task: {title}',
  'intelligence.refine.sourceLine': 'Source: {url}',
  'intelligence.refine.sourceIntake': 'Source: task source intake',
  'intelligence.refine.repositoryLine': 'Repository: {repo}',
  'intelligence.refine.externalTaskLine': 'External task: {externalId}',
  'intelligence.refine.planStep1':
    'Read the linked source task and confirm the exact requested behavior.',
  'intelligence.refine.planStep2':
    'Inspect the relevant code paths and identify the smallest implementation boundary.',
  'intelligence.refine.planStep3':
    'Implement the change with focused tests around the user-visible behavior.',
  'intelligence.refine.planStep4':
    'Run targeted validation and capture any residual risks or follow-up work.',
  'intelligence.refine.acceptance1':
    'The source task requirements are represented in the final implementation.',
  'intelligence.refine.acceptance2':
    'Relevant unit or integration tests cover the changed behavior.',
  'intelligence.refine.acceptance3':
    'Validation results and any unresolved risk are recorded on completion.',
  'notifications.card.dismiss': 'Dismiss notification',
  'notifications.card.importanceTitle': 'Importance: {pct}%',
  'notifications.center.empty': 'No notifications yet',
  'notifications.center.emptyHint': "You're all caught up.",
  'notifications.center.filterAll': 'Filter all',
  'notifications.center.markAllRead': 'Mark all read',
  'notifications.center.title': 'Notifications',
  'notifications.meeting.joinListen': 'Join (listen only)',
  'notifications.meeting.joinActive': 'Join & reply',
  'notifications.meeting.skip': 'Not this one',
  'notifications.meeting.alwaysJoin': 'Always join',
  'notifications.meeting.actionError': 'Could not complete that action. Please try again.',
  'oauth.button.connecting': 'Connecting...',
  'oauth.button.loopbackTimeout':
    'Sign-in timed out — the browser did not complete the OAuth redirect. Please try again.',
  'oauth.login.continueWith': 'Continue with',
  'onboarding.contextGathering.buildingDesc': 'Gathering context from your connected accounts…',
  'onboarding.contextGathering.buildingProfile': 'Building your profile...',
  'onboarding.contextGathering.continueToChat': 'Continue to chat',
  'onboarding.contextGathering.coreAlive': 'Core is reachable — first launch can take a minute.',
  'onboarding.contextGathering.coreAliveProbing': 'Checking core connection…',
  'onboarding.contextGathering.coreUnreachable':
    'Core is not responding. You can continue and try again later.',
  'onboarding.contextGathering.errorDesc':
    "Your chat is ready. We'll keep building your full profile in the background, so you can continue now and refine it over time.",
  'onboarding.contextGathering.stillWorkingDesc':
    'First launch can take 30–60 seconds while we warm up your local model and tools. You can continue to chat at any time — profile build keeps running in the background.',
  'onboarding.contextGathering.stillWorkingTitle': 'Still working on your profile…',
  'onboarding.contextGathering.title': 'Context Gathering',
  'openhuman.team_list_teams': 'Team list teams',
  'overlay.ariaAttention': 'Attention message',
  'overlay.ariaCompanion': 'Companion active',
  'overlay.ariaOrb': 'OpenHuman overlay',
  'overlay.ariaVoiceActive': 'Voice input active',
  'overlay.companion.error': 'Error',
  'overlay.companion.listening': 'Listening…',
  'overlay.companion.pointing': 'Pointing…',
  'overlay.companion.speaking': 'Speaking…',
  'overlay.companion.thinking': 'Thinking…',
  'overlay.orbTitle': 'Drag to move · Double-click to reset position',
  'pages.settings.account.connections': 'Connections',
  'pages.settings.account.connectionsDesc': 'Review and manage linked account connections',
  'pages.settings.account.migration': 'Import from another assistant',
  'pages.settings.account.migrationDesc':
    'Bring memory and notes over from OpenClaw (Hermes coming soon)',
  'pages.settings.account.privacy': 'Privacy',
  'pages.settings.account.privacyDesc': 'Control what data leaves your computer',
  'pages.settings.account.recoveryPhrase': 'Recovery phrase',
  'pages.settings.account.recoveryPhraseDesc': 'View and back up your account recovery phrase',
  'pages.settings.account.team': 'Team',
  'pages.settings.account.teamDesc': 'Manage team members and permissions',
  'pages.settings.accountSection.description':
    'Recovery phrase, team, connections, and privacy settings.',
  'pages.settings.accountSection.title': 'Account',
  'pages.settings.ai.llm': 'LLM',
  'pages.settings.ai.llmDesc': 'Language model provider and routing',
  'pages.settings.ai.voice': 'Voice',
  'pages.settings.ai.voiceDesc': 'Speech-to-text and text-to-speech settings',
  'pages.settings.aiSection.description':
    'Language model providers, local Ollama, and voice (STT / TTS).',
  'pages.settings.aiSection.title': 'AI',
  'settings.developerMenu.composio.title': 'Composio',
  'settings.developerMenu.composio.desc':
    'Routing mode, integration triggers, and trigger history archive.',
  'pages.settings.features.desktopCompanion': 'Desktop Companion',
  'pages.settings.features.desktopCompanionDesc':
    'Voice assistant with screen awareness — listens, sees, speaks, points',
  'pages.settings.features.messagingChannels': 'Messaging channels',
  'pages.settings.features.messagingChannelsDesc': 'Messaging channels desc',
  'pages.settings.features.notifications': 'Notifications',
  'pages.settings.features.notificationsDesc': 'Notifications desc',
  'pages.settings.features.screenAwareness': 'Screen awareness',
  'pages.settings.features.screenAwarenessDesc': 'Screen awareness desc',
  'pages.settings.features.tools': 'Tools',
  'pages.settings.features.toolsDesc': 'Tools desc',
  'pages.settings.featuresSection.description': 'Screen awareness, messaging, and tools.',
  'pages.settings.featuresSection.title': 'Features',
  'privacy.dataKind.credentials': 'Credentials',
  'privacy.dataKind.derived': 'Derived',
  'privacy.dataKind.diagnostics': 'Diagnostics',
  'privacy.dataKind.metadata': 'Metadata',
  'privacy.dataKind.raw': 'Raw',
  'privacy.whatLeaves.link.label': 'What leaves my computer?',
  'rewards.community.achievementsUnlocked': '{unlocked} of {total} achievements unlocked',
  'rewards.community.connectDiscord': 'Connect discord',
  'rewards.community.connectDiscordError': 'Could not start Discord connection. Please try again.',
  'rewards.community.connectingDiscord': 'Connecting…',
  'rewards.community.cumulativeTokens': 'Cumulative tokens',
  'rewards.community.currentStreak': 'Current streak',
  'rewards.community.disconnectDiscord': 'Disconnect',
  'rewards.community.disconnectDiscordError': 'Could not disconnect Discord. Please try again.',
  'rewards.community.disconnectingDiscord': 'Disconnecting…',
  'rewards.community.discordAccount': 'Discord account',
  'rewards.community.discordConnected': 'Discord connected',
  'rewards.community.discordConnectedAs': 'Connected as {username}',
  'rewards.community.discordLinkedNotInGuild': 'Discord linked — not yet a server member',
  'rewards.community.discordMember': 'Joined the server',
  'rewards.community.discordNotLinked': 'Discord not connected',
  'rewards.community.discordServer': 'Discord server',
  'rewards.community.discordStatusUnavailable': 'Discord status unavailable',
  'rewards.community.discordWaiting': 'Waiting for Discord…',
  'rewards.community.heroSubtitle': 'Refer friends and complete challenges to earn credits.',
  'rewards.community.heroTitle': 'Earn rewards with OpenHuman',
  'rewards.community.joinDiscord': 'Join Discord',
  'rewards.community.loadingRewards': 'Loading rewards…',
  'rewards.community.locked': 'Locked',
  'rewards.community.retrying': 'Retrying…',
  'rewards.community.roleAssigned': 'Role assigned',
  'rewards.community.roleAssignmentCount': '{assigned} of {unlocked} roles assigned',
  'rewards.community.roleClaimDesc':
    'You unlocked Discord roles but have not joined the OpenHuman server yet. Join to get them assigned automatically.',
  'rewards.community.roleClaimTitle': 'Claim your Discord roles',
  'rewards.community.roleJoinToClaim': 'Join server to claim',
  'rewards.community.rolePending': 'Syncing role…',
  'rewards.community.rolesAndRewards': 'Roles & Rewards',
  'rewards.community.streakDays': '{n}',
  'rewards.community.syncPending': 'Rewards sync pending',
  'rewards.community.syncPendingDesc': 'Your rewards are syncing. Check back shortly.',
  'rewards.community.syncUnavailable': 'Sync unavailable',
  'rewards.community.tryAgain': 'Retrying…',
  'rewards.community.unknown': 'Unknown',
  'rewards.community.unlocked': 'Unlocked',
  'rewards.community.yourProgress': 'Your Progress',
  'rewards.coupon.colCode': 'Code',
  'rewards.coupon.colRedeemed': 'Redeemed',
  'rewards.coupon.colReward': 'Reward',
  'rewards.coupon.colStatus': 'Status',
  'rewards.coupon.loadingHistory': 'Loading reward history…',
  'rewards.coupon.noCodes': 'No reward codes redeemed yet.',
  'rewards.coupon.pending': 'Pending',
  'rewards.coupon.placeholder': 'Coupon code',
  'rewards.coupon.promoCredits': 'Promo credits',
  'rewards.coupon.recentRedemptions': 'Recent redemptions',
  'rewards.coupon.redeemAccepted':
    '{code} accepted. {amount} will unlock after the required action is completed.',
  'rewards.coupon.redeemButton': 'Redeem Code',
  'rewards.coupon.redeemSuccess': '{code} redeemed. {amount} was added to your credits.',
  'rewards.coupon.redeemedCodes': 'Redeemed codes',
  'rewards.coupon.redeeming': 'Redeeming...',
  'rewards.coupon.statusApplied': 'Applied',
  'rewards.coupon.statusPendingAction': 'Pending action',
  'rewards.coupon.statusRedeemed': 'Redeemed',
  'rewards.coupon.subtitle': 'Enter a coupon code to add credits to your account.',
  'rewards.coupon.title': 'Redeem a coupon code',
  'rewards.referralSection.activity': 'Referral activity',
  'rewards.referralSection.apply': 'Applying…',
  'rewards.referralSection.applying': 'Applying…',
  'rewards.referralSection.colReferredUser': 'Referred user',
  'rewards.referralSection.colReward': 'Reward',
  'rewards.referralSection.colStatus': 'Status',
  'rewards.referralSection.colUpdated': 'Updated',
  'rewards.referralSection.completed': 'Completed',
  'rewards.referralSection.copyCode': 'Copy code',
  'rewards.referralSection.copyFailed': 'Copy failed',
  'rewards.referralSection.haveCode': 'Have a referral code?',
  'rewards.referralSection.haveCodeDesc': 'Enter it below to link it to your account.',
  'rewards.referralSection.linked': 'Linked',
  'rewards.referralSection.linkedCode': 'Linked',
  'rewards.referralSection.loading': 'Loading referral program…',
  'rewards.referralSection.retry': 'Retry',
  'rewards.referralSection.noReferrals': 'No referrals',
  'rewards.referralSection.pendingReferrals': 'Pending referrals',
  'rewards.referralSection.placeholder': 'Referral code',
  'rewards.referralSection.share': 'Share',
  'rewards.referralSection.statusCompleted': 'Completed',
  'rewards.referralSection.statusExpired': 'Expired',
  'rewards.referralSection.statusJoined': 'Joined',
  'rewards.referralSection.subtitle':
    'Share your code and earn credits for every friend who joins.',
  'rewards.referralSection.title': 'Invite friends, earn credits',
  'rewards.referralSection.totalEarned': 'Total earned',
  'rewards.referralSection.yourCode': 'Your code',
  'settings.ai.addCloudProvider': 'Add cloud provider',
  'settings.ai.addProvider': 'Add Provider',
  'settings.ai.apiKeyFieldLabel': 'API Key',
  'settings.ai.apiKeyRequired': 'Please paste your API key to continue.',
  'settings.ai.apiKeyStoredEncrypted': 'Your API key is stored encrypted on this device.',
  'settings.ai.apiKeysEncrypted': 'auth-profiles.json',
  'settings.ai.clearStoredKey': 'Clear stored key',
  'settings.ai.connectProvider': 'Connect',
  'settings.ai.customRouting': 'Custom routing',
  'settings.ai.defaultResolvesTo': 'Default resolves to',
  'settings.ai.discard': 'Discard',
  'settings.ai.editProvider': 'Edit {label}',
  'settings.ai.llmProviders': 'LLM Providers',
  'settings.ai.llmProvidersDesc': 'Add and configure language model providers.',
  'settings.ai.localOllama': 'Local (Ollama)',
  'settings.ai.modelLabel': 'Model',
  'settings.ai.noCustomProviders': 'No custom providers',
  'settings.ai.openAiCompat.authHeaderExample': 'Authorization: Bearer <your key>',
  'settings.ai.openAiCompat.authHeaderLabel': 'Auth header',
  'settings.ai.openAiCompat.baseUrlLabel': 'Base URL',
  'settings.ai.openAiCompat.baseUrlUnavailable': 'Unavailable',
  'settings.ai.openAiCompat.clearKey': 'Clear key',
  'settings.ai.openAiCompat.description':
    "Point local harnesses at this /v1 server to route through the providers configured below. Authentication uses a stable key you set here, not the app's internal core bearer.",
  'settings.ai.openAiCompat.keyConfigured': 'Key configured',
  'settings.ai.openAiCompat.keyRequired': 'Key required',
  'settings.ai.openAiCompat.rotateKey': 'Rotate key',
  'settings.ai.openAiCompat.setKey': 'Set key',
  'settings.ai.openAiCompat.title': 'OpenAI-compatible endpoint',
  'settings.ai.providerLabel': 'Provider',
  'skills.mcpComingSoon.title': 'MCP Servers',
  'skills.mcpComingSoon.description':
    'MCP server management is coming soon. This tab will be the home for discovering, connecting, and monitoring your MCP server integrations.',
  'settings.ai.routing': 'Routing',
  // Claude Code CLI connect control + modal (ClaudeCodeStatusCard).
  'settings.ai.claudeCode.button': 'Claude Code',
  'settings.ai.claudeCode.inlineNotConnected':
    'Not connected — routes chat through your local Claude Code CLI.',
  'settings.ai.claudeCode.checkingSignIn': 'Checking sign-in…',
  'settings.ai.claudeCode.inlineConnected': 'Connected.',
  'settings.ai.claudeCode.signedInAs': 'Signed in as',
  'settings.ai.claudeCode.subscriptionFallback': 'Claude subscription',
  'settings.ai.claudeCode.usingApiKeyEnv': 'Using ANTHROPIC_API_KEY',
  'settings.ai.claudeCode.cliNotInstalled': 'CLI not installed',
  'settings.ai.claudeCode.signInUnknown': 'Sign-in state unknown',
  'settings.ai.claudeCode.connectedNotSignedIn': 'Connected · not signed in',
  'settings.ai.claudeCode.modalTitle': 'Claude Code CLI',
  'settings.ai.claudeCode.modalDescription':
    "Routes chat, agentic and reasoning workloads through your locally-installed Claude Code CLI. No API key — it uses the CLI's own login.",
  'settings.ai.claudeCode.close': 'Close',
  'settings.ai.claudeCode.connection': 'Connection',
  'settings.ai.claudeCode.enabled': 'Enabled',
  'settings.ai.claudeCode.notEnabled': 'Not enabled',
  'settings.ai.claudeCode.disconnect': 'Disconnect',
  'settings.ai.claudeCode.disconnecting': 'Disconnecting…',
  'settings.ai.claudeCode.enable': 'Enable Claude Code',
  'settings.ai.claudeCode.enabling': 'Enabling…',
  'settings.ai.claudeCode.authentication': 'Authentication',
  'settings.ai.claudeCode.recheck': 'Recheck',
  'settings.ai.claudeCode.checking': 'Checking…',
  'settings.ai.claudeCode.openingTerminal': 'Opening terminal…',
  'settings.ai.claudeCode.signIn': 'Sign in with Claude',
  'settings.ai.claudeCode.reconnect': 'Reconnect',
  'settings.ai.claudeCode.loginHint':
    'Opens a terminal running claude login. After it completes, click Recheck.',
  'settings.ai.claudeCode.loginError': 'Could not open the login terminal. Please try again.',
  'settings.ai.claudeCode.fullAccess': 'Full access',
  'settings.ai.claudeCode.fullAccessOn':
    'Claude Code can run commands, use the network, and spawn subagents.',
  'settings.ai.claudeCode.fullAccessOff':
    'Accept edits only — auto-applies file edits, gates commands & network.',
  'settings.ai.claudeCode.sandboxNoteMac':
    'On macOS, ~/.openhuman stays protected by the sandbox in either mode.',
  'settings.ai.claudeCode.sandboxNoteOther':
    'Full access is unconfined on this platform — enable only if you trust the workspace.',
  'settings.ai.claudeCode.enableToCheck': 'Enable Claude Code to check sign-in.',
  'settings.ai.claudeCode.usingApiKeyEnvDetail': 'Using ANTHROPIC_API_KEY from the environment.',
  'settings.ai.claudeCode.notFoundInstall':
    'Claude Code CLI not found — install with: npm install -g @anthropic-ai/claude-code',
  'settings.ai.claudeCode.unknownDetail':
    "Couldn't determine sign-in state. Your claude CLI may predate auth status — try Reconnect, then Recheck.",
  'settings.ai.claudeCode.notSignedIn': 'Not signed in.',
  'settings.ai.routingCustom': 'Custom routing',
  'settings.ai.routingDefault': 'Default',
  'settings.ai.routingDesc': 'Choose which model handles each type of workload.',
  'settings.ai.saveChanges': 'Save Changes',
  'settings.ai.saving': 'Saving…',
  'settings.ai.unsavedChange': 'unsaved change',
  'settings.ai.unsavedChanges': 'unsaved changes',
  'settings.ai.workloadGroupBackground': 'Background tasks',
  'settings.ai.workloadGroupChat': 'Chat and conversations',
  'settings.ai.disconnectProvider': 'Disconnect {label}',
  'settings.ai.connectProviderLabel': 'Connect {label}',
  'settings.ai.editProviderEndpoint': 'Edit {label} endpoint',
  'settings.ai.defaultLocalEndpoint': 'http://localhost:11434/v1',
  'settings.ai.editEndpoint': 'Edit endpoint',
  'settings.ai.endpointUrlLabel': 'Endpoint URL',
  'settings.ai.localRuntimeHelper':
    'Where {label} is reachable. Default is localhost; point this at a remote host (for example, http://10.0.0.4:11434/v1) to use a shared instance.',
  'settings.ai.endpointUrlRequired': 'Endpoint URL is required.',
  'settings.ai.endpointProtocolRequired': 'Endpoint must start with http:// or https://.',
  'settings.ai.connectProviderDialog': 'Connect {label}',
  'settings.ai.getProviderApiKey': 'Get API key',
  'settings.ai.or': 'Or',
  'settings.ai.codexOauthMissingAuthUrl':
    'Codex OAuth did not return an authorization URL. Try signing in again.',
  'settings.ai.codexOauthMissingCallbackUrl':
    'Paste the redirect URL from your browser after signing in.',
  'settings.ai.openRouterOauthDescription':
    'Sign in with OpenRouter and import a user-controlled API key using PKCE.',
  'settings.ai.connecting': 'Connecting...',
  'settings.ai.backgroundLoops': 'Background loops',
  'settings.ai.backgroundLoopsDesc':
    'See what runs without a chat message, pause heartbeat work, and inspect recent credit ledger rows.',
  'settings.ai.heartbeatControls': 'Heartbeat controls',
  'settings.ai.heartbeatControlsDesc':
    'Defaults off. Enabling starts the loop; disabling aborts the running task.',
  'settings.ai.heartbeatLoop': 'Heartbeat loop',
  'settings.ai.heartbeatLoopDesc':
    'Master scheduler for planner + optional subconscious inference.',
  'settings.ai.subconsciousInference': 'Subconscious inference',
  'settings.ai.subconsciousInferenceDesc':
    'Runs model-backed task/reflection evaluation on heartbeat ticks.',
  'settings.ai.calendarMeetingChecks': 'Calendar meeting checks',
  'settings.ai.calendarMeetingChecksDesc':
    'Calls calendar event list for active Google Calendar connections.',
  'settings.ai.calendarCap': 'Calendar cap',
  'settings.ai.connectionsPerTick': '{count} conn/tick',
  'settings.ai.meetingLookahead': 'Meeting lookahead',
  'settings.ai.minutesShort': '{count} min',
  'settings.ai.reminderLookahead': 'Reminder lookahead',
  'settings.ai.cronReminderChecks': 'Cron reminder checks',
  'settings.ai.cronReminderChecksDesc': 'Scans enabled cron jobs for reminder-like upcoming items.',
  'settings.ai.relevantNotificationChecks': 'Relevant notification checks',
  'settings.ai.relevantNotificationChecksDesc':
    'Promotes urgent local notifications into proactive alerts.',
  'settings.ai.externalDelivery': 'External delivery',
  'settings.ai.externalDeliveryDesc':
    'Lets heartbeat alerts send proactive messages to external channels.',
  'settings.ai.interval': 'Interval',
  'settings.ai.running': 'Running...',
  'settings.ai.plannerTickNow': 'Planner tick now',
  'settings.ai.loadingHeartbeatControls': 'Loading heartbeat controls...',
  'settings.ai.heartbeatControlsUnavailable': 'Heartbeat controls unavailable.',
  'settings.ai.loopMap': 'Loop map',
  'settings.ai.plannerSummary':
    'Planner: {sourceEvents} source events, {sent} sent, {deduped} deduped.',
  'settings.ai.routeLabel': 'route: {route}',
  'settings.ai.on': 'on',
  'settings.ai.off': 'off',
  'settings.ai.recentUsageLedger': 'Recent usage ledger',
  'settings.ai.recentUsageLedgerDesc':
    'Backend rows expose action/time today; source tags need backend support.',
  'settings.ai.latestSpend': 'Latest spend: {amount} at {time} ({action})',
  'settings.ai.topActions': 'Top actions',
  'settings.ai.noSpendRows': 'No spend rows loaded.',
  'settings.ai.topHours': 'Top hours',
  'settings.ai.noHourlySpend': 'No hourly spend yet.',
  'settings.ai.openhumanDefault': 'OpenHuman (default)',
  'settings.ai.localModelResolved': 'Ollama · {model}',
  'settings.ai.customRoutingForWorkload': 'Custom routing for {label}',
  'settings.ai.loadingModels': 'Loading models...',
  'settings.ai.enterModelIdManually': 'or enter model id manually:',
  'settings.ai.modelIdPlaceholderForProvider': '{slug} model id',
  'settings.ai.modelIdPlaceholder': 'model-id',
  'settings.ai.selectModel': 'Select a model...',
  'settings.ai.temperatureOverride': 'Temperature override',
  'settings.ai.temperatureOverrideSlider': 'Temperature override (slider)',
  'settings.ai.temperatureOverrideValue': 'Temperature override (value)',
  'settings.ai.temperatureOverrideDesc':
    'Lower = more deterministic. Leave unchecked to use the provider default.',
  'settings.ai.modelVision': 'Supports vision (image input)',
  'settings.ai.modelVisionDesc':
    'Enable if this model accepts images. Lets the chat composer attach images when this model is selected.',
  'settings.ai.testFailed': 'Test failed',
  'settings.ai.testingModel': 'Testing model...',
  'settings.ai.modelResponse': 'Model response',
  'settings.ai.providerWithValue': 'Provider: {value}',
  'settings.ai.noneDash': '—',
  'settings.ai.promptHelloWorld': 'Prompt: Hello world',
  'settings.ai.startedAt': 'Started: {value}',
  'settings.ai.waitingForModelResponse': 'Waiting for response from the selected model...',
  'settings.ai.response': 'Response',
  'settings.ai.testing': 'Testing...',
  'settings.ai.test': 'Test',
  'settings.ai.slugMissingError': 'Enter a provider name to generate a slug.',
  'settings.ai.slugInUseError': 'That provider name is already in use.',
  'settings.ai.slugReservedError': 'Choose a different provider name.',
  'settings.ai.providerNamePlaceholder': 'My Provider',
  'settings.ai.slugLabel': 'Slug:',
  'settings.ai.openAiUrlLabel': 'OpenAI URL',
  'settings.ai.openAiUrlPlaceholder': 'https://api.openai.com/v1',
  'settings.ai.keepExistingKeyPlaceholder': 'Leave blank to keep existing key',
  'settings.ai.reindexingMemory': 'Re-indexing memory',
  'settings.ai.reindexingMemoryMessage':
    'Embeddings are being reprocessed. {pending} memory item(s) are being re-embedded under the current model — semantic recall is reduced until this finishes. Keyword search keeps working, and re-embedding continues in the background if you close this.',
  'settings.ai.signInWithOpenRouter': 'Sign in with OpenRouter',
  'settings.ai.weekBudget': 'Week budget',
  'settings.ai.cycleRemaining': 'Cycle remaining',
  'settings.ai.cycleTotalSpend': 'Cycle total spend',
  'settings.ai.avgSpendRow': 'Avg spend row',
  'settings.ai.backgroundApiReads': 'Bg API reads',
  'settings.ai.backgroundWakeups': 'Bg wakeups',
  'settings.ai.budgetMath': 'Budget math',
  'settings.ai.rowsLeft': 'Rows left',
  'settings.ai.rowsPerFullWeekBudget': 'Rows per full week budget',
  'settings.ai.sampleBurnRate': 'Sample burn rate',
  'settings.ai.projectedEmpty': 'Projected empty',
  'settings.ai.apiReadsPerDollarRemaining': 'API reads per $ remaining',
  'settings.ai.loopCallBudget': 'Loop call budget',
  'settings.ai.heartbeatTicks': 'Heartbeat ticks',
  'settings.ai.calendarPlannerCalls': 'Calendar planner calls',
  'settings.ai.calendarFanoutCap': 'Calendar fanout cap',
  'settings.ai.subconsciousModelCalls': 'Subconscious model calls',
  'settings.ai.composioSyncScans': 'Composio sync scans',
  'settings.ai.totalBackgroundApiReadBudget': 'Total bg API read budget',
  'settings.ai.memoryWorkerPolls': 'Memory worker polls',
  'settings.ai.defaultProviderName': 'OpenHuman',
  'settings.ai.routing.managed': 'Managed',
  'settings.ai.routing.managedAlwaysOn': 'Always on',
  'settings.ai.routing.managedHint':
    'Managed is always available as a fallback. To use your own model, choose a routing mode below.',
  'settings.ai.routing.managedDesc':
    'OpenHuman will run all inference in the cloud, choose the best model for the task, optimize for cost, and keep the safest routing defaults.',
  'settings.ai.routing.managedMsg':
    'OpenHuman will handle all inference for every workload and automatically choose the best route for cost, quality, and security.',
  'settings.ai.routing.useYourOwn': 'Use Your Own Models',
  'settings.ai.routing.useYourOwnDesc':
    'Choose one provider + model and route every workload through it. This is simple, but it can be inefficient because lightweight and heavyweight inference all share the same route.',
  'settings.ai.routing.advanced': 'Advanced',
  'settings.ai.routing.advancedDesc':
    'Pick different models for different tasks. This is the best option for tight cost optimization and the most control.',
  'settings.ai.routing.customDesc':
    'Fine-grained routing gives you the best cost optimization and the most control. Use the rows below to decide which workloads stay Managed, which use your shared default, and which pin to a specific model.',
  'settings.ai.routing.chatAndConversations': 'Chat and Conversations',
  'settings.ai.routing.chatDesc':
    'Models used during direct user interaction, replies, reasoning, agent loops, and coding help.',
  'settings.ai.routing.backgroundTasks': 'Background Tasks',
  'settings.ai.routing.bgTasksDesc':
    'Models used outside the main conversation flow for summarization, heartbeat, learning, and subconscious evaluation.',
  'settings.ai.routing.workload.chat.label': 'Chat',
  'settings.ai.routing.workload.chat.description':
    'Direct conversational back-and-forth — “Quick” mode in Conversations',
  'settings.ai.routing.workload.chat.hint':
    'Recommended: a cheap or mid-cost fast chat model with high tokens/sec and low latency. Open-source local models can work well here if they feel responsive.',
  'settings.ai.routing.workload.reasoning.label': 'Reasoning',
  'settings.ai.routing.workload.reasoning.description':
    'Main chat agent, meeting summarizer — “Reasoning” mode in Conversations',
  'settings.ai.routing.workload.reasoning.hint':
    'Recommended: a more expensive frontier or strong reasoning model for deep thinking. This is used for the main chat agent, meeting summaries, and heavier answer synthesis.',
  'settings.ai.routing.workload.agentic.label': 'Agentic',
  'settings.ai.routing.workload.agentic.description':
    'Sub-agent runners, tool loops, GIF decisions',
  'settings.ai.routing.workload.agentic.hint':
    'Recommended: a reliable instruction-following model with strong tool use. Mid-cost frontier models are usually safest; capable open-source models can work if tool calling is stable.',
  'settings.ai.routing.workload.coding.label': 'Coding',
  'settings.ai.routing.workload.coding.description': 'Code generation and refactor passes',
  'settings.ai.routing.workload.coding.hint':
    'Recommended: a coding-tuned model with strong instruction following, edit quality, and long-context performance. This is usually worth spending more on.',
  'settings.ai.routing.workload.vision.label': 'Vision',
  'settings.ai.routing.workload.vision.description':
    'Image understanding for the vision sub-agent — always multimodal',
  'settings.ai.routing.workload.vision.hint':
    'Recommended: a multimodal model that accepts image input. The managed default (vision-v1) is image-capable; any provider you route here is always treated as vision-enabled.',
  'settings.ai.routing.workload.memory.label': 'Memory summarization',
  'settings.ai.routing.workload.memory.description': 'Tree-extracts and consolidations',
  'settings.ai.routing.workload.memory.hint':
    'Recommended: a cheaper summarization model. It should be consistent and compact, but it does not need premium frontier-level reasoning.',
  'settings.ai.routing.workload.heartbeat.label': 'Heartbeat',
  'settings.ai.routing.workload.heartbeat.description': 'Background reasoning between user turns',
  'settings.ai.routing.workload.heartbeat.hint':
    'Recommended: a cheap, efficient background model. This runs often between turns, so low cost matters more than maximum intelligence.',
  'settings.ai.routing.workload.learning.label': 'Learning · Reflections',
  'settings.ai.routing.workload.learning.description': 'Periodic reflection over recent history',
  'settings.ai.routing.workload.learning.hint':
    'Recommended: a stronger reflective model. This can be mid-cost or premium because it benefits from better synthesis over recent history.',
  'settings.ai.routing.workload.subconscious.label': 'Subconscious',
  'settings.ai.routing.workload.subconscious.description': 'Eventfulness scoring + drift checks',
  'settings.ai.routing.workload.subconscious.hint':
    'Recommended: a very cheap monitoring model, ideally one that is lightweight and predictable. This is for eventfulness scoring, drift checks, and quiet background evaluation.',
  'settings.ai.routing.addCustomProvider': 'Add Custom Provider',
  'settings.ai.globalModel.title': 'Choose one model for everything',
  'settings.ai.globalModel.desc':
    'This routes all inference through one model. It is simpler, but it can be inefficient for cost and quality because lightweight and heavy tasks will all use the same route.',
  'settings.ai.globalModel.noProviders':
    'Add or connect a provider first. Then you can route every workload through one model here.',
  'settings.ai.globalModel.provider': 'Provider',
  'settings.ai.globalModel.model': 'Model',
  'settings.ai.globalModel.loadingModels': 'Loading models…',
  'settings.ai.globalModel.enterModelId': 'Enter model id',
  'settings.ai.globalModel.appliesToAll':
    'Applies the same provider + model to chat, reasoning, coding, memory, heartbeat, learning, and subconscious. Embeddings are configured separately. Changes save when you click save.',
  'settings.ai.globalModel.saving': 'Saving…',
  'settings.ai.globalModel.saved': 'Saved',
  'settings.ai.workload.noModel': 'No model selected',
  'settings.ai.workload.changeModel': 'Change Model',
  'settings.ai.workload.chooseModel': 'Choose Model',
  'settings.ai.provider.ollama': 'Ollama',
  'settings.autocomplete.appFilter.acceptSuggestion': 'Accept suggestion',
  'settings.autocomplete.appFilter.app': 'App',
  'settings.autocomplete.appFilter.currentSuggestion': 'Current suggestion',
  'settings.autocomplete.appFilter.contextOverride': 'Context Override (optional)',
  'settings.autocomplete.appFilter.debounce': 'Debounce',
  'settings.autocomplete.appFilter.debugFocus': 'Debug focus',
  'settings.autocomplete.appFilter.enabled': 'Enabled',
  'settings.autocomplete.appFilter.getSuggestion': 'Get suggestion',
  'settings.autocomplete.appFilter.lastError': 'Last error',
  'settings.autocomplete.appFilter.liveLogs': 'Live Logs',
  'settings.autocomplete.appFilter.model': 'Model',
  'settings.autocomplete.appFilter.noLogs': 'No logs yet.',
  'settings.autocomplete.appFilter.phase': 'Phase',
  'settings.autocomplete.appFilter.platformSupported': 'Platform supported',
  'settings.autocomplete.appFilter.refreshStatus': 'Refresh Status',
  'settings.autocomplete.appFilter.refreshing': 'Refreshing…',
  'settings.autocomplete.appFilter.running': 'Running',
  'settings.autocomplete.appFilter.runtime': 'Runtime',
  'settings.autocomplete.appFilter.test': 'Test',
  'settings.autocomplete.completionStyle.acceptedCompletion':
    '{count} accepted completion stored — used to personalize future suggestions.',
  'settings.autocomplete.completionStyle.acceptedCompletions':
    '{count} accepted completions stored — used to personalize future suggestions.',
  'settings.autocomplete.completionStyle.clearHistory': 'Clear History',
  'settings.autocomplete.completionStyle.clearing': 'Clearing…',
  'settings.autocomplete.completionStyle.debounce': 'Debounce (ms)',
  'settings.autocomplete.completionStyle.enabled': 'Enabled',
  'settings.autocomplete.completionStyle.maxChars': 'Max Chars',
  'settings.autocomplete.completionStyle.noHistory':
    'No accepted completions yet. Accept suggestions with Tab to start personalising.',
  'settings.autocomplete.completionStyle.overlayTtl': 'Overlay TTL (ms)',
  'settings.autocomplete.completionStyle.personalizationHistory': 'Personalization History',
  'settings.autocomplete.completionStyle.styleExamples': 'Style Examples (one per line)',
  'settings.autocomplete.completionStyle.styleInstructions': 'Style Instructions',
  'settings.autocomplete.debug.acceptedPrefix': 'Accepted: {value}',
  'settings.autocomplete.debug.acceptFailed': 'Failed to accept suggestion',
  'settings.autocomplete.debug.alreadyRunning': 'Autocomplete is already running.',
  'settings.autocomplete.debug.clearHistoryFailed': 'Failed to clear history',
  'settings.autocomplete.debug.didNotStart': 'Autocomplete did not start.',
  'settings.autocomplete.debug.disabledInSettings':
    'Autocomplete is disabled in settings. Enable it and save first.',
  'settings.autocomplete.debug.fetchSuggestionFailed': 'Failed to fetch current suggestion',
  'settings.autocomplete.debug.inspectFocusedElementFailed': 'Failed to inspect focused element',
  'settings.autocomplete.debug.loadSettingsFailed': 'Failed to load autocomplete settings',
  'settings.autocomplete.debug.noSuggestionApplied': 'No suggestion was applied.',
  'settings.autocomplete.debug.noSuggestionReturned': 'No suggestion returned.',
  'settings.autocomplete.debug.refreshStatusFailed': 'Failed to refresh autocomplete status',
  'settings.autocomplete.debug.saveAdvancedSettingsFailed': 'Failed to save advanced settings',
  'settings.autocomplete.debug.startFailed': 'Failed to start autocomplete',
  'settings.autocomplete.debug.stopFailed': 'Failed to stop autocomplete',
  'settings.autocomplete.debug.suggestionPrefix': 'Suggestion: {value}',
  'settings.autocomplete.shared.none': 'None',
  'settings.autocomplete.shared.notApplicable': 'n/a',
  'settings.autocomplete.shared.unknown': 'Unknown',
  'settings.billing.autoRecharge.addAmount': 'Add this amount',
  'settings.billing.autoRecharge.addCard': 'Add card',
  'settings.billing.autoRecharge.amountHint': 'Will be charged to your default payment method.',
  'settings.billing.autoRecharge.defaultCard': 'Default card',
  'settings.billing.autoRecharge.lastRechargeFailed': 'Last recharge failed',
  'settings.billing.autoRecharge.lastRecharged': 'Last recharged',
  'settings.billing.autoRecharge.expires': 'Expires {date}',
  'settings.billing.autoRecharge.noCards': 'No cards',
  'settings.billing.autoRecharge.paymentMethods': 'Payment Methods',
  'settings.billing.autoRecharge.rechargeInProgress': 'Recharge in progress',
  'settings.billing.autoRecharge.spentThisWeek': '${spent} of ${limit} used this week',
  'settings.billing.autoRecharge.rechargeWhen': 'Recharge when balance drops below',
  'settings.billing.autoRecharge.saveSettings': 'Save Settings',
  'settings.billing.autoRecharge.saving': 'Saving…',
  'settings.billing.autoRecharge.setDefault': 'Set as default',
  'settings.billing.autoRecharge.subtitle':
    'Top up your credits automatically when your balance runs low.',
  'settings.billing.autoRecharge.title': 'Enable Auto-Recharge',
  'settings.billing.autoRecharge.toggleAriaLabel': 'Toggle auto-recharge',
  'settings.billing.autoRecharge.weeklyLimit': 'Weekly spending limit',
  'settings.billing.history.desc': 'Your recent transactions and invoices',
  'settings.billing.history.empty': 'No billing history yet',
  'settings.billing.history.openPortal': 'Open portal',
  'settings.billing.history.posted': 'Posted',
  'settings.billing.history.title': 'Billing History',
  'settings.billing.inferenceBudget.cycleEnds': 'Cycle ends',
  'settings.billing.inferenceBudget.exhausted': 'Exhausted',
  'settings.billing.inferenceBudget.loadError': 'Failed to load budget information.',
  'settings.billing.inferenceBudget.noBudgetDesc':
    'No recurring budget configured for this period.',
  'settings.billing.inferenceBudget.noRecurringBudget': 'No recurring budget',
  'settings.billing.inferenceBudget.noRecurringPlanBudget': 'No recurring plan budget',
  'settings.billing.inferenceBudget.noRecurringWeeklyDesc':
    'Your current plan does not include a recurring weekly inference budget. Usage is paid from available credits instead.',
  'settings.billing.inferenceBudget.remaining': 'Remaining',
  'settings.billing.inferenceBudget.remainingSummary': '{remaining} / {budget} remaining',
  'settings.billing.inferenceBudget.spentThisCycle': 'Spent {amount} this cycle',
  'settings.billing.inferenceBudget.cycleEndsOn': 'Cycle ends {date}',
  'settings.billing.inferenceBudget.exhaustedDesc':
    'Included subscription usage is exhausted. Top up credits to keep using AI without waiting for the next cycle.',
  'settings.billing.inferenceBudget.discountVsPayg': '{pct}% cheaper per call than pay-as-you-go.',
  'settings.billing.inferenceBudget.cycleSpend': 'Cycle spend',
  'settings.billing.inferenceBudget.totalAmount': '{amount} total',
  'settings.billing.inferenceBudget.inference': 'Inference',
  'settings.billing.inferenceBudget.integrations': 'Integrations',
  'settings.billing.inferenceBudget.calls': '{count} calls',
  'settings.billing.inferenceBudget.dailySpend': 'Daily spend',
  'settings.billing.inferenceBudget.dailySpendPoint': '{date}: {amount}',
  'settings.billing.inferenceBudget.topModels': 'Top models',
  'settings.billing.inferenceBudget.noInferenceUsage': 'No inference usage this cycle.',
  'settings.billing.inferenceBudget.topIntegrations': 'Top integrations',
  'settings.billing.inferenceBudget.noIntegrationUsage': 'No integration usage this cycle.',
  'settings.billing.inferenceBudget.tenHourCap': '10-hour cap',
  'settings.billing.inferenceBudget.title': 'Inference Budget',
  'settings.billing.inferenceBudget.unableToLoad': 'Unable to load usage data',
  'settings.billing.inferenceBudget.notAvailable': 'n/a',
  'settings.billing.payAsYouGo.available': 'Available',
  'settings.billing.payAsYouGo.chargeCustomAmount': 'Opening…',
  'settings.billing.payAsYouGo.chooseTopUpDesc': 'Select an amount to add to your credit balance.',
  'settings.billing.payAsYouGo.chooseTopUpTitle': 'Top Up Credits',
  'settings.billing.payAsYouGo.creditBalanceDesc': 'Your available credit for AI usage.',
  'settings.billing.payAsYouGo.creditBalanceTitle': 'Credit Balance',
  'settings.billing.payAsYouGo.customAmount': 'Custom amount',
  'settings.billing.payAsYouGo.enterAmount': 'Enter amount',
  'settings.billing.payAsYouGo.opening': '{amount}',
  'settings.billing.payAsYouGo.promotionalCredits': 'Promotional Credits',
  'settings.billing.payAsYouGo.topUpBalance': 'Top-up Balance',
  'settings.billing.payAsYouGo.topUpCredits': 'Top Up Credits',
  'settings.billing.payAsYouGo.unableToLoad': 'Unable to load balance.',
  'settings.billing.subscription.annual': 'Annual',
  'settings.billing.subscription.billedAnnually': 'Billed annually',
  'settings.billing.subscription.chooseSubtitle': 'Upgrade to unlock more usage and features.',
  'settings.billing.subscription.chooseTitle': 'Choose a Plan',
  'settings.billing.subscription.cryptoDesc': 'Pay with cryptocurrency via our payment gateway.',
  'settings.billing.subscription.cryptoQuestion': 'Want to pay with crypto?',
  'settings.billing.subscription.current': 'Current',
  'settings.billing.subscription.currentPlan': 'Current plan',
  'settings.billing.subscription.monthly': 'Monthly',
  'settings.billing.subscription.paymentConfirmed': 'Payment confirmed',
  'settings.billing.subscription.perMonth': 'Per month',
  'settings.billing.subscription.popular': 'Popular',
  'settings.billing.subscription.save': '{pct}',
  'settings.billing.subscription.upgrade': 'Upgrade',
  'settings.billing.subscription.waiting': 'Waiting',
  'settings.billing.subscription.waitingPayment': 'Waiting payment',
  'settings.composio.apiKeyDesc': 'A Composio API key is currently stored on this device.',
  'settings.composio.apiKeyExamplePlaceholder': 'ck_live_xxxxxxxxxxxxxxxx',
  'settings.composio.apiKeyLabel': 'Composio API key',
  'settings.composio.apiKeyStored': 'API key stored',
  'settings.composio.apiKeyStoredPlaceholder': '••••••••••••••••',
  'settings.composio.clearedToBackend': 'Switched to Backend mode',
  'settings.composio.confirmItem1': 'An account at app.composio.dev with an API key',
  'settings.composio.confirmItem2':
    'To re-link each integration through your personal Composio account',
  'settings.composio.confirmItem3':
    "Note: Composio triggers (real-time webhooks) don't fire in Direct mode yet — only synchronous tool calls",
  'settings.composio.confirmNeedItems': "You'll need:",
  'settings.composio.confirmSwitch': 'I understand, switch to Direct',
  'settings.composio.confirmTitle': '⚠️ Switching to Direct mode',
  'settings.composio.confirmWarning':
    "Your existing integrations (Gmail, Slack, GitHub, etc. linked through OpenHuman) won't be visible — they live in the OpenHuman-managed Composio tenant.",
  'settings.composio.intro':
    'Composio integrates 250+ external apps as tools your agent can call. Choose how those tool calls are routed.',
  'settings.composio.title': 'Composio',
  'settings.composio.modeDirect': 'Direct (bring your own API key)',
  'settings.composio.modeDirectDesc':
    'Calls go to backend.composio.dev directly. Sovereign / offline-friendly. Tool execution works synchronously; real-time trigger webhooks are not yet routed in direct mode (follow-up issue).',
  'settings.composio.modeManaged': 'Managed (OpenHuman handles it for you)',
  'settings.composio.modeManagedDesc':
    'OpenHuman proxies tool calls through our backend (recommended). Auth is brokered; you never paste a Composio API key. Webhooks are fully routed.',
  'settings.composio.routingMode': 'Routing mode',
  'settings.composio.saveErrorNoKey': 'Failed to save. Direct mode requires a non-empty API key.',
  'settings.composio.saving': 'Saving…',
  'settings.composio.switching': 'Switching…',
  'settings.companion.title': 'Desktop Companion',
  'settings.companion.session': 'Session',
  'settings.companion.activeLabel': 'Active',
  'settings.companion.inactiveStatus': 'Inactive',
  'settings.companion.stopping': 'Stopping…',
  'settings.companion.stopSession': 'Stop Session',
  'settings.companion.starting': 'Starting…',
  'settings.companion.startSession': 'Start Session',
  'settings.companion.sessionId': 'Session ID',
  'settings.companion.turns': 'Turns',
  'settings.companion.remaining': 'Remaining',
  'settings.companion.configuration': 'Configuration',
  'settings.companion.hotkey': 'Hotkey',
  'settings.companion.activationMode': 'Activation Mode',
  'settings.companion.sessionTtl': 'Session TTL',
  'settings.companion.screenCapture': 'Screen Capture',
  'settings.companion.appContext': 'App Context',
  'settings.cron.jobs.commandRequired': 'Command is required for shell jobs',
  'settings.cron.jobs.created': 'Job created',
  'settings.cron.jobs.createJob': 'New Scheduled Job',
  'settings.cron.jobs.custom': 'Custom',
  'settings.cron.jobs.desc': 'View and manage scheduled jobs running in the core.',
  'settings.cron.jobs.edit': 'Edit',
  'settings.cron.jobs.editJob': 'Edit Scheduled Job',
  'settings.cron.jobs.empty': 'No core cron jobs found.',
  'settings.cron.jobs.errorCreate': 'Failed to create cron job: {message}',
  'settings.cron.jobs.errorLoadList': 'Failed to load core cron jobs: {message}',
  'settings.cron.jobs.errorLoadRuns': 'Failed to load run history: {message}',
  'settings.cron.jobs.errorRemove': 'Failed to remove core cron job: {message}',
  'settings.cron.jobs.errorRun': 'Failed to run core cron job: {message}',
  'settings.cron.jobs.errorToggle': 'Failed to update core cron job: {message}',
  'settings.cron.jobs.errorUpdate': 'Failed to update cron job: {message}',
  'settings.cron.jobs.formAtLabel': 'Run at',
  'settings.cron.jobs.formCancel': 'Cancel',
  'settings.cron.jobs.formCommand': 'Shell command',
  'settings.cron.jobs.formCommandPlaceholder': 'e.g. curl https://example.com/health',
  'settings.cron.jobs.formCreate': 'Create',
  'settings.cron.jobs.formCronCustom': 'Custom expression',
  'settings.cron.jobs.formCronCustomPlaceholder': 'e.g. */30 * * * *',
  'settings.cron.jobs.formCronPreset': 'Preset',
  'settings.cron.jobs.formCronPreview': 'Runs: {preview}',
  'settings.cron.jobs.formDelivery': 'Delivery mode',
  'settings.cron.jobs.formDeliveryNone': 'None (output only)',
  'settings.cron.jobs.formDeliveryProactive': 'Proactive (push notification)',
  'settings.cron.jobs.formDeleteAfterRun': 'Delete after first run',
  'settings.cron.jobs.formError': 'Failed to save job',
  'settings.cron.jobs.formEveryLabel': 'Interval (milliseconds)',
  'settings.cron.jobs.formEveryPlaceholder': 'e.g. 3600000',
  'settings.cron.jobs.formJobType': 'Job type',
  'settings.cron.jobs.formJobTypeAgent': 'Agent (AI prompt)',
  'settings.cron.jobs.formJobTypeShell': 'Shell command',
  'settings.cron.jobs.formName': 'Job name',
  'settings.cron.jobs.formNamePlaceholder': 'e.g. daily-report, cleanup-task',
  'settings.cron.jobs.formPrompt': 'Agent prompt',
  'settings.cron.jobs.formPromptPlaceholder': 'What should the agent do each run?',
  'settings.cron.jobs.formPromptRequired': 'Prompt is required for agent jobs',
  'settings.cron.jobs.formSave': 'Save',
  'settings.cron.jobs.formSaving': 'Saving…',
  'settings.cron.jobs.formScheduleAt': 'One-time (run at)',
  'settings.cron.jobs.formScheduleCron': 'Recurring (cron)',
  'settings.cron.jobs.formScheduleEvery': 'Interval (every N ms)',
  'settings.cron.jobs.formScheduleRequired': 'Schedule is required',
  'settings.cron.jobs.formScheduleType': 'Schedule type',
  'settings.cron.jobs.formSessionIsolated': 'Isolated (recommended)',
  'settings.cron.jobs.formSessionMain': 'Main session',
  'settings.cron.jobs.formSessionTarget': 'Session target',
  'settings.cron.jobs.lastStatus': 'Last status',
  'settings.cron.jobs.loading': 'Loading cron jobs...',
  'settings.cron.jobs.loadingRuns': 'Loading runs…',
  'settings.cron.jobs.nextRun': 'Next run',
  'settings.cron.jobs.pause': 'Pause',
  'settings.cron.jobs.paused': 'Paused',
  'settings.cron.jobs.recentRuns': 'Recent runs',
  'settings.cron.jobs.removing': 'Removing…',
  'settings.cron.jobs.resume': 'Resume',
  'settings.cron.jobs.runningNow': 'Running now…',
  'settings.cron.jobs.saving': 'Saving…',
  'settings.cron.jobs.schedule': 'Schedule',
  'settings.cron.jobs.title': 'Core Cron Jobs',
  'settings.cron.jobs.updated': 'Job updated',
  'settings.cron.jobs.viewRuns': 'View runs',
  'settings.cron.schedule.every2hours': 'Every 2 hours',
  'settings.cron.schedule.every30min': 'Every 30 minutes',
  'settings.cron.schedule.every6hours': 'Every 6 hours',
  'settings.cron.schedule.everyHour': 'Every hour',
  'settings.cron.schedule.onceDaily': 'Once daily (9 AM)',
  'settings.localModel.deviceCapability.active': 'Active',
  'settings.localModel.deviceCapability.appliedTier': 'Applied tier',
  'settings.localModel.deviceCapability.applying': 'Applying',
  'settings.localModel.deviceCapability.cores': '{count}',
  'settings.localModel.deviceCapability.couldNotLoadPresets': 'Could not load presets',
  'settings.localModel.deviceCapability.cpu': 'CPU',
  'settings.localModel.deviceCapability.customModelIds': 'Custom model IDs',
  'settings.localModel.deviceCapability.detected': 'Detected',
  'settings.localModel.deviceCapability.disabled': 'Disabled',
  'settings.localModel.deviceCapability.disabledDesc':
    'Local AI is off. All inference uses the cloud.',
  'settings.localModel.deviceCapability.downloadingModels': '(downloading models)',
  'settings.localModel.deviceCapability.downloadingSetupDesc':
    'Downloading the OllamaSetup installer (~2 GB) and unpacking it. This can take a minute on first install.',
  'settings.localModel.deviceCapability.failedToApplyPreset': 'Failed to apply preset',
  'settings.localModel.deviceCapability.gpu': 'GPU',
  'settings.localModel.deviceCapability.installFailed': 'Ollama install failed',
  'settings.localModel.deviceCapability.installFailedDesc':
    'The installer exited before Ollama was usable. Click retry to try again, or install manually from ollama.com.',
  'settings.localModel.deviceCapability.installFirst': 'Run Ollama first.',
  'settings.localModel.deviceCapability.installFirstDesc':
    'Local tiers depend on an externally managed Ollama endpoint. Start it yourself, pull the models you want, and keep using "Disabled (cloud fallback)" until the runtime is reachable.',
  'settings.localModel.deviceCapability.installOllamaFirst': 'Run Ollama first to use this tier',
  'settings.localModel.deviceCapability.installingOllama': 'Installing Ollama',
  'settings.localModel.deviceCapability.loadingDeviceInfo': 'Loading device info',
  'settings.localModel.deviceCapability.localAiDisabled':
    'Local AI disabled — using cloud fallback.',
  'settings.localModel.deviceCapability.modelTier': 'Model Tier',
  'settings.localModel.deviceCapability.needsOllama': 'Needs Ollama',
  'settings.localModel.deviceCapability.notDetected': 'Not detected',
  'settings.localModel.deviceCapability.disabledLowercase': 'disabled',
  'settings.localModel.deviceCapability.presetDetails':
    'Chat: {chatModel} · Vision: {visionModel} · Target RAM: {targetRamGb} GB',
  'settings.localModel.deviceCapability.ram': 'RAM',
  'settings.localModel.deviceCapability.recommended': 'Recommended',
  'settings.localModel.deviceCapability.retryInstall': 'Retrying…',
  'settings.localModel.deviceCapability.retrying': 'Retrying…',
  'settings.localModel.deviceCapability.starting': 'Starting…',
  'settings.localModel.download.audioPathPlaceholder': 'Absolute path to audio file',
  'settings.localModel.download.capabilityChat': 'Chat',
  'settings.localModel.download.capabilityEmbedding': 'Embedding',
  'settings.localModel.download.capabilityAssets': 'Capability Assets',
  'settings.localModel.download.capabilityStt': 'STT',
  'settings.localModel.download.capabilityTts': 'TTS',
  'settings.localModel.download.capabilityVision': 'Vision',
  'settings.localModel.download.downloading': 'Downloading...',
  'settings.localModel.download.embeddingDimensions': 'Dimensions: {dimensions}',
  'settings.localModel.download.embeddingModel': 'Model: {modelId}',
  'settings.localModel.download.embeddingPlaceholder': 'One input string per line...',
  'settings.localModel.download.embeddingVectors': 'Vectors: {count}',
  'settings.localModel.download.noThinkMode': 'No think mode',
  'settings.localModel.download.notAvailable': 'n/a',
  'settings.localModel.download.promptPlaceholder':
    'Type any prompt and run it against the local model...',
  'settings.localModel.download.quantizationPref': 'Quantization preference',
  'settings.localModel.download.runEmbeddingTest': 'Run Embedding Test',
  'settings.localModel.download.runPromptTest': 'Run Prompt Test',
  'settings.localModel.download.runSummaryTest': 'Run Summary Test',
  'settings.localModel.download.runTranscriptionTest': 'Run Transcription Test',
  'settings.localModel.download.runTtsTest': 'Run TTS Test',
  'settings.localModel.download.runVisionTest': 'Run Vision Test',
  'settings.localModel.download.running': 'Running...',
  'settings.localModel.download.runningPrompt': 'Running prompt',
  'settings.localModel.download.summaryHelper':
    'Calls `openhuman.inference_summarize` via Rust core',
  'settings.localModel.download.summarizePlaceholder':
    'Paste text to summarize with the local model...',
  'settings.localModel.download.testCustomPrompt': 'Test Custom Prompt',
  'settings.localModel.download.testEmbeddings': 'Test Embeddings',
  'settings.localModel.download.testSummarization': 'Test Summarization',
  'settings.localModel.download.testVisionPrompt': 'Test Vision Prompt',
  'settings.localModel.download.testVoiceInput': 'Test Voice Input (STT)',
  'settings.localModel.download.testVoiceOutput': 'Test Voice Output (TTS)',
  'settings.localModel.download.transcript': 'Transcript:',
  'settings.localModel.download.ttsOutput': 'Output: {outputPath}',
  'settings.localModel.download.ttsOutputPlaceholder': 'Optional output WAV path',
  'settings.localModel.download.ttsPlaceholder': 'Enter text to synthesize...',
  'settings.localModel.download.ttsVoice': 'Voice: {voiceId}',
  'settings.localModel.download.visionImagePlaceholder':
    'One image reference per line (data URI, URL, or local path marker)',
  'settings.localModel.download.visionPromptPlaceholder': 'Enter a prompt for the vision model...',
  'settings.localModel.status.allChecksPassed': 'All checks passed',
  'settings.localModel.status.artifact': 'Artifact',
  'settings.localModel.status.backend': 'Backend',
  'settings.localModel.status.binary': 'Binary',
  'settings.localModel.status.bootstrapResume': 'Bootstrap / Resume',
  'settings.localModel.status.checking': 'Checking...',
  'settings.localModel.status.checkingOllama': 'Checking Ollama',
  'settings.localModel.status.contextBelowMinimumBadge':
    '{contextLength} ctx - below {required} min',
  'settings.localModel.status.contextBelowMinimumTitle':
    'Rejected: context window {contextLength} tokens is below the {required}-token minimum the memory layer requires. Recall would be corrupted by silent truncation.',
  'settings.localModel.status.contextOkBadge': '{contextLength} ctx ✓',
  'settings.localModel.status.contextOkTitle':
    'Context window {contextLength} tokens meets the memory-layer minimum of {required} tokens.',
  'settings.localModel.status.contextUnknownBadge': 'ctx unknown',
  'settings.localModel.status.contextUnknownTitle':
    'Context window unknown; could not confirm it meets the {required}-token memory-layer minimum.',
  'settings.localModel.status.customLocation': 'Custom location',
  'settings.localModel.status.customLocationDesc': 'Point to a custom Ollama binary location.',
  'settings.localModel.status.diagnosticsHint':
    'Click "Run Diagnostics" to verify Ollama is running and models are installed.',
  'settings.localModel.status.downloadingUnknown': 'Downloading (size unknown)',
  'settings.localModel.status.eta': 'ETA',
  'settings.localModel.status.expectedModels': 'Expected models',
  'settings.localModel.status.expectedChat': 'Chat: {model}',
  'settings.localModel.status.expectedEmbedding': 'Embedding: {model}',
  'settings.localModel.status.expectedVision': 'Vision: {model}',
  'settings.localModel.status.externalProcess': 'External process',
  'settings.localModel.status.forceRebootstrap': 'Force Re-bootstrap',
  'settings.localModel.status.generationTps': 'Generation TPS',
  'settings.localModel.status.hideErrorDetails': 'Hide error details',
  'settings.localModel.status.installManually': 'Install manually',
  'settings.localModel.status.installManuallyFrom': 'Install manually from',
  'settings.localModel.status.installOllama': 'Install Ollama',
  'settings.localModel.status.installedModels': 'Installed models',
  'settings.localModel.status.installing': 'Installing...',
  'settings.localModel.status.installingOllama': 'Installing Ollama runtime...',
  'settings.localModel.status.issues': 'Issues',
  'settings.localModel.status.issuesFound': '{count} issue(s) found',
  'settings.localModel.status.lastLatency': 'Last Latency',
  'settings.localModel.status.model': 'Model',
  'settings.localModel.status.notAvailable': 'n/a',
  'settings.localModel.status.notFound': 'Not found',
  'settings.localModel.status.notRunning': 'Not running',
  'settings.localModel.status.ollamaBinaryPath': 'Ollama binary path',
  'localModel.ollamaServer.helperText': 'Example: http://192.168.1.5:11434',
  'localModel.ollamaServer.label': 'Ollama Server URL',
  'localModel.ollamaServer.modelCount': 'models',
  'localModel.ollamaServer.placeholder': 'http://localhost:11434',
  'localModel.ollamaServer.reachable': 'Reachable',
  'localModel.ollamaServer.resetButton': 'Reset to default',
  'localModel.ollamaServer.saveButton': 'Save',
  'localModel.ollamaServer.testButton': 'Test Connection',
  'localModel.ollamaServer.unreachable': 'Unreachable',
  'localModel.ollamaServer.validationError': 'Must be a valid http:// or https:// URL',
  'settings.localModel.status.ollamaDiagnostics': 'Ollama Diagnostics',
  'settings.localModel.status.ollamaNotInstalled': 'Ollama runtime unavailable',
  'settings.localModel.status.ollamaNotInstalledDesc':
    'OpenHuman now treats Ollama as an external inference runtime. Start your own Ollama server, pull the models you want, and point workload routing at it.',
  'settings.localModel.status.progress': 'Progress',
  'settings.localModel.status.provider': 'Provider',
  'settings.localModel.status.retryBootstrap': 'Retry Bootstrap',
  'settings.localModel.status.runDiagnostics': 'Run Diagnostics',
  'settings.localModel.status.running': 'Running',
  'settings.localModel.status.runningExternalProcess': 'Running via external process',
  'settings.localModel.status.runtimeStatus': 'Runtime Status',
  'settings.localModel.status.server': 'Server',
  'settings.localModel.status.setPath': 'Set Path',
  'settings.localModel.status.setting': 'Setting...',
  'settings.localModel.status.showErrorDetails': 'Show error details',
  'settings.localModel.status.showInstallErrorDetails': 'Show error details',
  'settings.localModel.status.suggestedFixes': 'Suggested fixes',
  'settings.localModel.status.thenSetPath': 'Then set path',
  'settings.localModel.status.triggering': 'Triggering...',
  'settings.localModel.status.unavailable': 'Unavailable',
  'settings.localModel.status.working': 'Working...',
  'settings.developerMenu.ai.title': 'AI Configuration',
  'settings.developerMenu.ai.desc':
    'Cloud providers, local Ollama models, and per-workload routing',
  'settings.developerMenu.screenAwareness.title': 'Screen Awareness',
  'settings.developerMenu.screenAwareness.desc':
    'Screen capture permissions, monitoring policy, and session controls',
  'settings.developerMenu.messagingChannels.title': 'Messaging Channels',
  'settings.developerMenu.messagingChannels.desc':
    'Configure Telegram/Discord auth modes and default channel routing',
  'settings.developerMenu.tools.title': 'Tools',
  'settings.developerMenu.tools.desc':
    'Enable or disable capabilities OpenHuman can use on your behalf',
  'settings.developerMenu.agentChat.title': 'Agent Chat',
  'settings.developerMenu.agentChat.desc':
    'Test agent conversation with model and temperature overrides',
  'settings.developerMenu.devWorkflow.title': 'Dev Workflow',
  'settings.developerMenu.devWorkflow.desc':
    'Autonomous agent that picks your GitHub issues and raises PRs on a schedule',
  'settings.developerMenu.devWorkflow.panelDesc':
    'Configure an autonomous developer agent that picks GitHub issues assigned to you and raises pull requests automatically on a schedule.',
  'settings.developerMenu.skillsRunner.title': 'Skills Runner',
  'settings.developerMenu.skillsRunner.desc':
    'Run any bundled skill ad-hoc — fill its inputs and fire a background autonomous run',
  'settings.developerMenu.skillsRunner.panelDesc':
    'Pick a bundled workflow, fill in its declared inputs, and fire a fire-and-forget background run. Use the Schedule section below if you want a cron-scheduled recurring job.',
  'settings.skillsRunner.skill': 'Skill',
  'settings.skillsRunner.selectSkill': 'Select a skill…',
  'settings.skillsRunner.loadingSkills': 'Loading skills…',
  'settings.skillsRunner.loadingDescription': 'Loading skill inputs…',
  'settings.skillsRunner.noInputs': 'This skill declares no inputs.',
  'settings.skillsRunner.placeholder.required': 'required',
  'settings.skillsRunner.runNow': 'Run now',
  'settings.skillsRunner.starting': 'Starting…',
  'settings.skillsRunner.started': 'Started — run id:',
  'settings.skillsRunner.logPath': 'Log:',
  'settings.skillsRunner.error.listSkills': 'Failed to load skills:',
  'settings.skillsRunner.error.describe': 'Failed to load inputs:',
  'settings.skillsRunner.error.missingRequired': 'Missing required input(s):',
  'settings.skillsRunner.error.run': 'Run failed to start:',
  'settings.skillsRunner.error.preflightGate': 'Preflight gate failed',
  'settings.skillsRunner.error.runtimeUnavailable': 'Runtime unavailable',
  'settings.skillsRunner.error.runtimeUnavailableDefault': 'unavailable',
  'settings.skillsRunner.schedule.heading': 'Schedule (recurring)',
  'settings.skillsRunner.schedule.help':
    'Save this workflow + inputs as a recurring cron job. The agent will call run_workflow at each tick.',
  'settings.skillsRunner.schedule.frequency': 'Frequency',
  'settings.skillsRunner.schedule.every30min': 'Every 30 minutes',
  'settings.skillsRunner.schedule.everyHour': 'Every hour',
  'settings.skillsRunner.schedule.every2hours': 'Every 2 hours',
  'settings.skillsRunner.schedule.every6hours': 'Every 6 hours',
  'settings.skillsRunner.schedule.onceDaily': 'Once daily (9:00)',
  'settings.skillsRunner.schedule.save': 'Save schedule',
  'settings.skillsRunner.schedule.saving': 'Saving…',
  'settings.skillsRunner.schedule.saved': 'Schedule saved.',
  'settings.skillsRunner.schedule.error': 'Schedule save failed:',
  'settings.skillsRunner.schedule.loadingJobs': 'Loading existing schedules…',
  'settings.skillsRunner.schedule.noJobs': 'No schedules saved for this skill yet.',
  'settings.skillsRunner.schedule.existing': 'Scheduled jobs for this skill:',
  'settings.skillsRunner.schedule.inputsLabel': 'Inputs',
  'settings.skillsRunner.schedule.inputsNone': 'No inputs',
  'settings.skillsRunner.schedule.runNow': 'Run',
  'settings.skillsRunner.schedule.remove': 'Remove',
  'settings.skillsRunner.scheduleEnabled': 'Enabled',
  'settings.skillsRunner.scheduleDisabled': 'Paused',
  'settings.skillsRunner.scheduleToggleAria': 'Toggle schedule enabled',
  'settings.skillsRunner.schedule.history': 'History',
  'settings.skillsRunner.schedule.historyLoading': 'Loading history…',
  'settings.skillsRunner.schedule.historyEmpty': 'No runs yet for this schedule.',
  'settings.skillsRunner.schedule.historyNoOutput': 'No output captured.',
  'settings.skillsRunner.schedule.active': 'Active',
  'settings.skillsRunner.schedule.lastRunLabel': 'last:',
  'settings.skillsRunner.recentRuns.headingForSkill': 'Recent runs for this skill',
  'settings.skillsRunner.recentRuns.headingAll': 'Recent skill runs (all)',
  'settings.skillsRunner.recentRuns.refresh': 'Refresh',
  'settings.skillsRunner.recentRuns.loading': 'Loading recent runs…',
  'settings.skillsRunner.recentRuns.empty': 'No recent runs.',
  'settings.skillsRunner.viewer.loading': 'Loading log…',
  'settings.skillsRunner.viewer.tailing': 'Live tailing',
  'settings.skillsRunner.viewer.fetching': 'fetching',
  'settings.skillsRunner.viewer.error': 'Log read failed:',
  'settings.skillsRunner.repoPicker.loading': 'Loading repositories…',
  'settings.skillsRunner.repoPicker.select': 'Select a repository…',
  'settings.skillsRunner.repoPicker.empty':
    'No repositories returned. Connect GitHub via Composio to populate this list.',
  'settings.skillsRunner.repoPicker.notConnected':
    "GitHub isn't connected via Composio. Connect it under Skills → Composio first.",
  'settings.skillsRunner.repoPicker.privateTag': '(private)',
  'settings.skillsRunner.branchPicker.needRepo': 'Pick a repo first…',
  'settings.skillsRunner.branchPicker.loading': 'Loading branches…',
  'settings.skillsRunner.branchPicker.select': 'Select a branch…',
  'settings.devWorkflow.githubRepository': 'GitHub Repository',
  'settings.devWorkflow.loadingRepositories': 'Loading repositories...',
  'settings.devWorkflow.selectRepository': 'Select a repository',
  'settings.devWorkflow.privateTag': '(private)',
  'settings.devWorkflow.detectingForkInfo': 'Detecting fork info...',
  'settings.devWorkflow.forkDetected': 'Fork detected',
  'settings.devWorkflow.upstream': 'Upstream:',
  'settings.devWorkflow.forkPrNote': 'PRs will be raised against the upstream repository.',
  'settings.devWorkflow.notForkNote':
    'Not a fork. PRs will be raised against this repository directly.',
  'settings.devWorkflow.targetBranch': 'Target Branch',
  'settings.devWorkflow.targetBranchNote': 'PRs will be raised against this branch',
  'settings.devWorkflow.loadingBranches': 'Loading branches...',
  'settings.devWorkflow.runFrequency': 'Run Frequency',
  'settings.devWorkflow.runFrequencyNote':
    'How often the agent should check for issues and raise PRs.',
  'settings.devWorkflow.updateConfiguration': 'Update Configuration',
  'settings.devWorkflow.saveConfiguration': 'Save Configuration',
  'settings.devWorkflow.remove': 'Remove',
  'settings.devWorkflow.saved': 'Saved',
  'settings.devWorkflow.activeConfiguration': 'Active Configuration',
  'settings.devWorkflow.activeConfigRepository': 'Repository:',
  'settings.devWorkflow.activeConfigUpstream': 'Upstream:',
  'settings.devWorkflow.activeConfigTargetBranch': 'Target branch:',
  'settings.devWorkflow.activeConfigSchedule': 'Schedule:',
  'settings.devWorkflow.enabled': 'Enabled',
  'settings.devWorkflow.paused': 'Paused',
  'settings.devWorkflow.nextRun': 'Next run',
  'settings.devWorkflow.lastRun': 'Last run',
  'settings.devWorkflow.runNow': 'Run now',
  'settings.devWorkflow.running': 'Running\u2026',
  'settings.devWorkflow.recentRuns': 'Recent runs',
  'settings.devWorkflow.cronSaveError': 'Failed to save configuration',
  'settings.devWorkflow.lastOutput': 'Last output',
  'settings.devWorkflow.noOutput': 'No output captured',
  'settings.devWorkflow.runningStatus':
    'Agent is running — picking an issue and working on a fix...',
  'settings.devWorkflow.errorNotConnected':
    'GitHub is not connected. Please connect GitHub via Settings > Advanced > Composio first.',
  'settings.devWorkflow.errorToolNotEnabled':
    'GITHUB_LIST_REPOSITORIES_FOR_THE_AUTHENTICATED_USER tool is not enabled on this backend. Please ask your admin to enable it in the Composio integration (backend#842).',
  'settings.devWorkflow.errorNotAuthenticated': 'Not authenticated. Please sign in first.',
  'settings.devWorkflow.errorNoRepositories': 'No repositories found for this GitHub account.',
  'settings.devWorkflow.schedule.every30min': 'Every 30 minutes',
  'settings.devWorkflow.schedule.everyHour': 'Every hour',
  'settings.devWorkflow.schedule.every2hours': 'Every 2 hours',
  'settings.devWorkflow.schedule.every6hours': 'Every 6 hours',
  'settings.devWorkflow.schedule.onceDaily': 'Once daily (9 AM)',
  'settings.developerMenu.tasks.title': 'Tasks',
  'settings.developerMenu.tasks.desc':
    'Browse and manage task boards — your own to-dos plus the boards agents build across conversations.',
  'settings.developerMenu.cronJobs.title': 'Cron Jobs',
  'settings.developerMenu.cronJobs.desc': 'View and configure scheduled jobs for runtime skills',
  'settings.developerMenu.localModelDebug.title': 'Local Model Debug',
  'settings.developerMenu.localModelDebug.desc':
    'Ollama config, asset downloads, model tests, and diagnostics',
  'settings.developerMenu.webhooks.title': 'Webhooks',
  'settings.developerMenu.webhooks.desc':
    'Inspect runtime webhook registrations and captured request logs',
  'settings.developerMenu.eventLog.title': 'Event Log',
  'settings.developerMenu.eventLog.desc':
    'Live colour-coded stream of all agent, tool, and system events',
  'settings.developerMenu.eventLog.allTypes': 'All types',
  'settings.developerMenu.eventLog.filterAgent': 'Filter...',
  'settings.developerMenu.eventLog.download': 'Download',
  'settings.developerMenu.eventLog.events': 'events',
  'settings.developerMenu.eventLog.live': 'Live',
  'settings.developerMenu.eventLog.disconnected': 'Disconnected',
  'settings.developerMenu.eventLog.waiting': 'Waiting for events...',
  'settings.developerMenu.eventLog.notConnected': 'Not connected to core',
  'settings.developerMenu.eventLog.jumpToLatest': 'Jump to latest',
  'settings.developerMenu.eventLog.badge.tool': 'TOOL',
  'settings.developerMenu.eventLog.badge.agent': 'AGENT',
  'settings.developerMenu.eventLog.badge.info': 'INFO',
  'settings.developerMenu.eventLog.badge.mem': 'MEM',
  'settings.developerMenu.eventLog.badge.chan': 'CHAN',
  'settings.developerMenu.eventLog.badge.cron': 'CRON',
  'settings.developerMenu.eventLog.badge.hook': 'HOOK',
  'settings.developerMenu.eventLog.badge.warn': 'WARN',
  'settings.developerMenu.eventLog.badge.skill': 'SKILL',
  'settings.developerMenu.eventLog.badge.comp': 'COMP',
  'settings.developerMenu.eventLog.badge.mcp': 'MCP',
  'settings.developerMenu.intelligence.title': 'Intelligence',
  'settings.developerMenu.intelligence.desc':
    'Memory workspace, subconscious engine, dreams, and settings',
  'settings.developerMenu.notificationRouting.title': 'Notification Routing',
  'settings.developerMenu.notificationRouting.desc':
    'AI importance scoring and orchestrator escalation for integration alerts',
  'settings.developerMenu.composeioTriggers.title': 'ComposeIO Triggers',
  'settings.developerMenu.composeioTriggers.desc': 'View ComposeIO trigger history and archive',
  'settings.developerMenu.composioRouting.title': 'Composio Routing (Direct Mode)',
  'settings.developerMenu.composioRouting.desc':
    'Bring your own Composio API key and route calls directly to backend.composio.dev',
  'settings.developerMenu.integrationTriggers.title': 'Integration Triggers',
  'settings.developerMenu.integrationTriggers.desc':
    'Configure AI triage settings for Composio integration triggers',
  'settings.developerMenu.mcpServer.title': 'MCP Server',
  'settings.developerMenu.mcpServer.desc': 'Configure external MCP clients to connect to OpenHuman',
  'settings.developerMenu.autonomy.title': 'Agent autonomy',
  'settings.developerMenu.autonomy.desc': 'Tool action rate limits and safety thresholds',
  // Tools & Capabilities group — autocomplete and voice debug (doc § Tools & Capabilities)
  'settings.developerMenu.autocomplete.title': 'Autocomplete',
  'settings.developerMenu.autocomplete.desc': 'AI inline autocomplete settings and debug panel',
  'settings.developerMenu.voiceDebug.title': 'Voice (debug)',
  'settings.developerMenu.voiceDebug.desc': 'Voice dictation runtime status and debug settings',
  'settings.mcpServer.title': 'MCP Server',
  'settings.mcpServer.toolsSectionTitle': 'Available Tools',
  'settings.mcpServer.toolsSectionDesc':
    'Tools exposed via the MCP stdio server when running openhuman-core mcp',
  'settings.mcpServer.configSectionTitle': 'Client Configuration',
  'settings.mcpServer.configSectionDesc':
    'Select your MCP client to generate the correct configuration snippet',
  'settings.mcpServer.copySnippet': 'Copy to Clipboard',
  'settings.mcpServer.copied': 'Copied!',
  'settings.mcpServer.openConfigFile': 'Open Config File',
  'settings.mcpServer.binaryPathNotFound':
    'OpenHuman binary not found. If running from source, build with: cargo build --bin openhuman-core',
  'settings.mcpServer.openConfigError': 'Failed to open config file',
  'settings.mcpServer.clientClaudeDesktop': 'Claude Desktop',
  'settings.mcpServer.clientCursor': 'Cursor',
  'settings.mcpServer.clientCodex': 'Codex',
  'settings.mcpServer.clientZed': 'Zed',
  'settings.mcpServer.configFilePath': 'Config file',
  'settings.mcpServer.clientSelectorAriaLabel': 'MCP client selector',
  'settings.appearance.menuDesc': 'Pick light, dark, or match your system theme',
  'settings.agentAccess.title': 'Agent OS access',
  'settings.agentAccess.menuDesc':
    'Control where the agent can read/write and whether it can use the shell.',
  'settings.agentAccess.loadError': 'Failed to load access settings',
  'settings.agentAccess.saveError': 'Failed to save access settings',
  'settings.agentAccess.saved': 'Saved — applies on your next message.',
  'settings.agentAccess.desktopOnly': 'Access settings are only available in the desktop app.',
  'settings.agentAccess.loading': 'Loading…',
  'settings.agentAccess.accessMode': 'Access mode',
  'settings.agentAccess.tier.readonly.title': 'Read-only',
  'settings.agentAccess.tier.readonly.desc':
    'Reads files and runs read-only commands to explore — but never writes, edits, or runs anything that changes state.',
  'settings.agentAccess.tier.supervised.title': 'Ask before edit',
  'settings.agentAccess.tier.supervised.desc':
    'Creates new files freely, but asks for your approval before editing an existing file, running a command, reaching the network, or installing anything.',
  'settings.agentAccess.tier.full.title': 'Full access',
  'settings.agentAccess.tier.full.desc':
    'Runs commands with your full user account access — it can read/write anywhere allowed, except credential and system stores. Destructive commands, network access, and installs still ask for approval.',
  'settings.agentAccess.defaultTag': '(default)',
  'settings.agentAccess.fullWarning':
    '⚠ Full access runs commands with your full account access and is not sandboxed. Only enable it when you trust the agent with this machine. Credential and system directories stay blocked, and destructive, network, and install actions still ask for approval.',
  'settings.agentAccess.confine.label': 'Confine to workspace',
  'settings.agentAccess.confine.desc':
    'Restrict the agent to the workspace directory (plus any granted folders), whichever access mode is selected. When off, it can reach anywhere your user can — except the always-blocked credential and system directories.',
  'settings.agentAccess.requireTaskPlanApproval.label': 'Require task plan approval',
  'settings.agentAccess.requireTaskPlanApproval.desc':
    'Pause before an assigned agent executes an agent-authored task brief.',
  'settings.agentAccess.tinyplaceAutopilot.title': 'Autonomous tiny.place agent',
  'settings.agentAccess.tinyplaceAutopilot.desc':
    'Let OpenHuman act on tiny.place on its own: on a schedule it finds worthwhile work — open bounties first — does what fits its skills, and acts from your identity. It runs unattended and can spend, so keep it on devnet while testing. Off by default.',
  'settings.agentAccess.tinyplaceAutopilot.label': 'Run automatically',
  'settings.agentAccess.timeout.label': 'Action timeout',
  'settings.agentAccess.timeout.desc':
    'How long a single tool or action may run before it is cancelled. Increase this if a large local model is interrupted before it finishes responding.',
  'settings.agentAccess.timeout.unit': 'seconds',
  'settings.agentAccess.timeout.invalid':
    'Enter a whole number of seconds within the allowed range',
  'settings.agentAccess.timeout.envOverride':
    'The OPENHUMAN_TOOL_TIMEOUT_SECS environment variable is overriding this setting, so changes here have no effect until it is unset.',
  'settings.agentAccess.grantedFolders': 'Granted folders',
  'settings.agentAccess.alwaysAllow': 'Always-allowed tools',
  'settings.agentAccess.alwaysAllowDesc':
    'Tools you marked "Always allow" in chat run without asking. Remove one to be prompted again.',
  'settings.agentAccess.alwaysAllowNone': 'No always-allowed tools yet.',
  'settings.agentAccess.grantedDesc':
    'Folders the agent may read and write, in addition to the workspace. Credential stores (~/.ssh, ~/.gnupg, ~/.aws, keychains) and system directories (/etc, /System, C:\\Windows, …) are always blocked, even inside a granted folder.',
  'settings.agentAccess.noneGranted': 'No folders granted.',
  'settings.agentAccess.readWrite': 'read + write',
  'settings.agentAccess.readOnly': 'read-only',
  'settings.agentAccess.remove': 'Remove',
  'settings.agentAccess.pathPlaceholder': 'Absolute folder path',
  'settings.agentAccess.accessLevelLabel': 'Access level',
  'settings.agentAccess.add': 'Add',
  'settings.agentAccess.saving': 'Saving…',
  'settings.agentAccess.changesApply': 'Changes apply on your next message.',
  'settings.agentAccess.directories': 'Directories',
  'settings.agentAccess.actionSandbox': 'Action sandbox',
  'settings.agentAccess.readWriteAccess': 'read + write',
  'settings.agentAccess.actionSandboxDesc':
    'Default working directory for shell, file, and git tools.',
  'settings.agentAccess.actionDir.edit': 'Edit',
  'settings.agentAccess.actionDir.save': 'Save',
  'settings.agentAccess.actionDir.cancel': 'Cancel',
  'settings.agentAccess.actionDir.placeholder': 'Absolute path, e.g. /Users/you/Projects',
  'settings.agentAccess.actionDir.envLocked':
    'Set by OPENHUMAN_ACTION_DIR. Change the environment variable to override.',
  'settings.agentAccess.actionDir.saved': 'Action directory updated.',
  'settings.agentAccess.internalState': 'Internal state',
  'settings.agentAccess.agentBlocked': 'agent-blocked',
  'settings.agentAccess.internalStateDesc':
    'Memory databases, sessions, tokens, and other core persistence. Not accessible to agent tools.',
  'settings.agentAccess.actionDirInputLabel': 'Action sandbox path',
  'settings.agentAccess.actionDirSave': 'Save',
  'settings.agentAccess.actionDirSaving': 'Saving…',
  'settings.agentAccess.actionDirSaved': 'Action sandbox updated.',
  'settings.agentAccess.actionDirEmptyError': 'Path cannot be empty.',
  'settings.agentAccess.actionDirSaveError': 'Could not update the action sandbox.',
  'settings.agentAccess.actionDirEnvOverrideError':
    'OPENHUMAN_ACTION_DIR is set — unset the env var to edit this from Settings.',
  'settings.agentAccess.actionDirEnvOverrideNote':
    'Overridden by OPENHUMAN_ACTION_DIR — unset the env var to manage from Settings.',
  'settings.agentAccess.approvalHistory': 'Approval history',
  'settings.agentAccess.approvalHistoryDesc':
    'Review past Approve / Deny decisions the agent requested.',
  'settings.agentAccess.viewApprovalHistory': 'View approval history',

  // ── Permissions panel (layman split from Agent Access, Deferred-3) ────────
  'settings.permissions.title': 'Permissions',
  'settings.permissions.menuDesc': 'Choose what your assistant can do and where it can work.',
  'settings.permissions.accessMode': 'What can the assistant do?',
  'settings.permissions.accessModeDesc':
    'Choose how much freedom the assistant has when it takes actions on your computer.',
  'settings.permissions.preset.readonly.title': "Look, don't touch",
  'settings.permissions.preset.readonly.desc':
    'The assistant can read files and explore — but never write, edit, or run anything that changes state.',
  'settings.permissions.preset.supervised.title': 'Ask me first',
  'settings.permissions.preset.supervised.desc':
    'Can create new files freely, but always asks your approval before editing, running commands, or accessing the network.',
  'settings.permissions.preset.full.title': 'Full control',
  'settings.permissions.preset.full.desc':
    'Runs with your full account access. Destructive commands, network access, and installs still ask for approval.',
  'settings.permissions.folders': 'Where can it work?',
  'settings.permissions.foldersDesc':
    'The default folder the assistant reads and writes. You can add more folders in Advanced settings.',

  // ── Sandbox execution backend ─────────────────────────────────────
  'settings.meetings.title': 'Meetings',
  'settings.meetings.menuDesc': 'Meeting Assistant auto-join, summaries, and transcripts',
  'settings.meetings.desktopOnly': 'Meeting settings are available on desktop only.',
  'settings.meetings.loading': 'Loading…',
  'settings.meetings.loadError': 'Failed to load meeting settings.',
  'settings.meetings.saveError': 'Failed to save meeting settings.',
  'settings.meetings.saved': 'Saved',
  'settings.meetings.saving': 'Saving…',
  'settings.meetings.autoJoin.title': 'Auto-join policy',
  'settings.meetings.autoJoin.desc': 'When a calendar event has a Google Meet link',
  'settings.meetings.autoJoin.askEachTime': 'Ask each time',
  'settings.meetings.autoJoin.always': 'Always join',
  'settings.meetings.autoJoin.never': 'Never join',
  'settings.meetings.autoSummarize.title': 'Post-call summary',
  'settings.meetings.autoSummarize.desc': 'Generate a summary after the call ends',
  'settings.meetings.autoSummarize.ask': 'Ask after call',
  'settings.meetings.autoSummarize.always': 'Always summarize',
  'settings.meetings.autoSummarize.never': 'Never summarize',
  'settings.meetings.listenOnly': 'Listen-only mode',
  'settings.meetings.listenOnlyDesc': 'Join with the microphone muted',
  'settings.meetings.ingestTranscripts': 'Ingest backend transcripts',
  'settings.meetings.ingestTranscriptsDesc': 'Store meeting transcripts in memory',
  'settings.sandbox.title': 'Sandbox execution',
  'settings.sandbox.menuDesc': 'Configure sandbox backends for agent tool isolation.',
  'settings.sandbox.loading': 'Loading…',
  'settings.sandbox.desktopOnly': 'Sandbox settings are only available in the desktop app.',
  'settings.sandbox.loadError': 'Failed to load sandbox settings.',
  'settings.sandbox.saveError': 'Failed to save sandbox settings.',
  'settings.sandbox.saved': 'Saved — applies to new agent sessions.',
  'settings.sandbox.saving': 'Saving…',
  'settings.sandbox.status': 'Status',
  'settings.sandbox.dockerStatus': 'Docker',
  'settings.sandbox.available': 'Available',
  'settings.sandbox.unavailable': 'Unavailable',
  'settings.sandbox.detectedBackend': 'OS backend',
  'settings.sandbox.enableLabel': 'Enable sandbox execution',
  'settings.sandbox.enableDesc': 'Run agent tools inside an isolated sandbox environment.',
  'settings.sandbox.backendLabel': 'Backend',
  'settings.sandbox.backendDesc': 'Choose which isolation backend to use for sandboxed execution.',
  'settings.sandbox.backend.auto': 'Auto (detect best available)',
  'settings.sandbox.backend.docker': 'Docker',
  'settings.sandbox.backend.landlock': 'Landlock (Linux)',
  'settings.sandbox.backend.firejail': 'Firejail (Linux)',
  'settings.sandbox.backend.bubblewrap': 'Bubblewrap (Linux)',
  'settings.sandbox.backend.none': 'None (no sandbox)',
  'settings.sandbox.dockerSettings': 'Docker settings',
  'settings.sandbox.dockerImage': 'Image',
  'settings.sandbox.dockerImagePlaceholder': 'alpine:3.20',
  'settings.sandbox.memoryLimit': 'Memory limit',
  'settings.sandbox.memoryUnit': 'MB',
  'settings.sandbox.cpuLimit': 'CPU limit',
  'settings.sandbox.cpuUnit': 'cores',
  'settings.sandbox.envPassthrough': 'Environment passthrough',
  'settings.sandbox.envPassthroughDesc': 'Environment variables forwarded into the sandbox.',
  'settings.sandbox.noEnvVars': 'No environment variables configured.',

  'settings.approvalHistory.title': 'Approval history',
  'settings.approvalHistory.subtitle': 'Recent tool-approval decisions, newest first.',
  'settings.approvalHistory.refresh': 'Refresh',
  'settings.approvalHistory.loading': 'Loading approval history…',
  'settings.approvalHistory.retry': 'Retry',
  'settings.approvalHistory.emptyState': 'No approval decisions recorded yet.',
  'settings.approvalHistory.errorGeneric': 'Unable to load approval history. Try again.',
  'settings.approvalHistory.decidedAt': 'Decided {date}',
  'settings.approvalHistory.decision.approveOnce': 'Approved once',
  'settings.approvalHistory.decision.approveAlways': 'Always allowed',
  'settings.approvalHistory.decision.deny': 'Denied',
  'settings.theme.title': 'Theme Studio',
  'settings.theme.menuDesc': 'Fully customize colours and fonts, or pick a preset theme.',
  'settings.theme.presetsHeading': 'Themes',
  'settings.theme.variantLight': 'Light',
  'settings.theme.variantDark': 'Dark',
  'settings.theme.variantAuto': 'Auto',
  'settings.theme.variantAria': 'Theme variant',
  'settings.theme.backdropHeading': 'Background',
  'settings.theme.backdrop.mesh': 'Mesh',
  'settings.theme.backdrop.solid': 'Solid',
  'settings.theme.backdrop.image': 'Image',
  'settings.theme.backdropImageUrl': 'Background image URL',
  'settings.theme.backdropDots': 'Show background dots',
  'settings.theme.backdropHint':
    'Mesh shows the animated gradient; Solid uses a flat background; Image paints your own.',
  'settings.theme.builtInBadge': 'Preset',
  'settings.theme.customBadge': 'Custom',
  'settings.theme.customizeHint':
    'Built-in presets are read-only. Duplicate this theme to edit its colours and fonts.',
  'settings.theme.autoForkHint':
    'Editing a preset automatically saves your changes as a new custom theme.',
  'settings.theme.duplicate': 'Duplicate & customize',
  'settings.theme.copyName': '{name} (custom)',
  'settings.theme.importedName': 'Imported theme',
  'settings.theme.contrastWarn':
    'Low contrast between text and background — this theme may be hard to read.',
  'settings.theme.group.surfaces': 'Surfaces',
  'settings.theme.group.text': 'Text',
  'settings.theme.group.borders': 'Borders',
  'settings.theme.group.accents': 'Accent colours',
  'settings.theme.showShades': 'Show all accent shades',
  'settings.theme.hideShades': 'Hide all accent shades',
  'settings.theme.fontsHeading': 'Fonts',
  'settings.theme.fontRole.title': 'Title',
  'settings.theme.fontRole.heading': 'Heading',
  'settings.theme.fontRole.body': 'Body',
  'settings.theme.fontRole.mono': 'Monospace',
  'settings.theme.fontRole.serif': 'Serif',
  'settings.theme.fontCurrent': 'Current',
  'settings.theme.actions': 'Manage theme',
  'settings.theme.reset': 'Reset overrides',
  'settings.theme.delete': 'Delete theme',
  'settings.theme.export': 'Copy JSON',
  'settings.theme.copied': 'Copied!',
  'settings.theme.import': 'Import theme',
  'settings.theme.importHint': 'Paste exported theme JSON to add it as a custom theme.',
  'settings.theme.importApply': 'Import',
  'settings.theme.importError': 'Could not parse that theme JSON.',
  'settings.appearance.title': 'Appearance',
  'settings.appearance.themeHeading': 'Theme',
  'settings.appearance.themeAria': 'Theme',
  'settings.appearance.modeLight': 'Light',
  'settings.appearance.modeLightDesc': 'Bright surfaces, dark text.',
  'settings.appearance.modeDark': 'Dark',
  'settings.appearance.modeDarkDesc': 'Dim surfaces, easier on the eyes after dusk.',
  'settings.appearance.modeSystem': 'Match system',
  'settings.appearance.modeSystemDesc': 'Follow your OS appearance setting.',
  'settings.appearance.helperText':
    'Dark mode switches the entire app — chat, settings, panels — to a dim palette. "Match system" follows your OS appearance and updates live.',
  'settings.appearance.fontSizeHeading': 'Font size',
  'settings.appearance.fontSizeAria': 'Font size',
  'settings.appearance.fontSizeSmall': 'Small',
  'settings.appearance.fontSizeSmallDesc': 'Compact text — fit more on screen.',
  'settings.appearance.fontSizeMedium': 'Medium',
  'settings.appearance.fontSizeMediumDesc': 'The default, balanced size.',
  'settings.appearance.fontSizeLarge': 'Large',
  'settings.appearance.fontSizeLargeDesc': 'Bigger text for easier reading.',
  'settings.appearance.fontSizeXLarge': 'Extra large',
  'settings.appearance.fontSizeXLargeDesc': 'The largest text, for maximum readability.',
  'settings.appearance.fontSizeHelperText':
    'Scales text across the whole app — chat, settings and panels — independently of your system font setting.',
  'settings.appearance.tabBarHeading': 'Bottom tab bar',
  'settings.appearance.tabBarAlwaysShowLabels': 'Always show labels',
  'settings.appearance.tabBarAlwaysShowLabelsDesc':
    'When off, labels only appear on hover or for the active tab.',
  'settings.appearance.chatHeading': 'Chat',
  'settings.appearance.assistantTextMode': 'Plain assistant responses',
  'settings.appearance.assistantTextModeDesc':
    'Render assistant replies as unframed text while keeping your messages in bubbles.',
  'settings.appearance.hideAgentInsights': 'Hide agent thinking',
  'settings.appearance.hideAgentInsightsDesc':
    'Collapse the live step-by-step agent timeline in chat. A blinking “Processing” link still lets you open the full run.',
  'settings.mascot.active': 'Active',
  'settings.mascot.characterDesc': 'Choose your OpenHuman character.',
  'settings.mascot.characterDraft': 'Draft',
  'settings.mascot.characterHeading': 'Character',
  'settings.mascot.customGifError':
    'Enter an HTTPS .gif URL, loopback HTTP .gif URL, file:// .gif URL, or local .gif path.',
  'settings.mascot.customGifHeading': 'Custom GIF avatar',
  'settings.mascot.customGifLabel': 'Custom GIF avatar URL',
  'settings.mascot.customGifPlaceholder': 'https://example.com/avatar.gif',
  'settings.mascot.characterPreview': 'Preview',
  'settings.mascot.characterStates': 'states',
  'settings.mascot.characterVisemes': 'visemes',
  'settings.mascot.colorAria': 'OpenHuman color',
  'settings.mascot.colorDesc': 'Pick a color theme for your character.',
  'settings.mascot.colorHeading': 'Color',
  'settings.mascot.colorBlack': 'Black',
  'settings.mascot.colorBurgundy': 'Burgundy',
  'settings.mascot.colorCustom': 'Custom',
  'settings.mascot.colorNavy': 'Navy',
  'settings.mascot.primaryColor': 'Primary color',
  'settings.mascot.secondaryColor': 'Secondary color',
  'settings.mascot.colorYellow': 'Yellow',
  'settings.mascot.libraryUnavailable': 'OpenHuman library unavailable',
  'settings.mascot.title': 'OpenHuman',
  'settings.mascot.loadingLibrary': 'Loading OpenHuman library…',
  'settings.mascot.loadDetailError': 'Could not load mascot.',
  'settings.mascot.loadLibraryError': 'Could not load mascot library.',
  'settings.mascot.localDefault': 'Local OpenHuman (default)',
  'settings.mascot.menuTitle': 'Mascot',
  'settings.mascot.menuDesc': 'Pick the mascot color used across the app',
  'settings.mascot.noCharacters': 'No OpenHuman characters are available yet',
  'settings.mascot.noColorVariants': 'No color variants',
  'settings.mascot.voice.current': 'current',
  'settings.mascot.voice.customDesc':
    'Find voice ids at api.elevenlabs.io/v1/voices or your ElevenLabs dashboard. Only the id is stored — your API key stays on the backend.',
  'settings.mascot.voice.customHeading': 'Custom voice id',
  'settings.mascot.voice.customOption': 'Other (paste voice id)…',
  'settings.mascot.voice.customPlaceholder': 'e.g. 21m00Tcm4TlvDq8ikWAM',
  'settings.mascot.voice.desc':
    'Pick the ElevenLabs voice the mascot uses for spoken replies. Filter by gender, pick from the curated list, paste a custom id, or let the app pick a voice that matches your interface language.',
  'settings.mascot.voice.genderFemale': 'Female',
  'settings.mascot.voice.genderHeading': 'Voice gender',
  'settings.mascot.voice.genderMale': 'Male',
  'settings.mascot.voice.heading': 'Voice',
  'settings.mascot.voice.preset': 'Voice preset',
  'settings.mascot.voice.presetHeading': 'Voice preset',
  'settings.mascot.voice.preview': 'Preview voice',
  'settings.mascot.voice.previewError': 'Voice preview failed',
  'settings.mascot.voice.previewText': "Hi, I'm your assistant. This is a voice preview.",
  'settings.mascot.voice.previewing': 'Previewing…',
  'settings.mascot.voice.reset': 'Reset to default',
  'settings.mascot.voice.useLocaleDefault': 'Match the app language',
  'settings.mascot.voice.useLocaleDefaultDesc':
    'Auto-pick a voice for the current interface language.',
  'settings.persona.title': 'Persona',
  'settings.persona.menuTitle': 'Persona',
  'settings.persona.menuDesc':
    'Name, personality, avatar, and voice — your assistant as one identity',
  'settings.persona.identityHeading': 'Identity',
  'settings.persona.identityDesc':
    'A display name and short description for your assistant. Shown in the app; does not change how the assistant reasons.',
  'settings.persona.displayNameLabel': 'Display name',
  'settings.persona.displayNamePlaceholder': 'e.g. Nova',
  'settings.persona.descriptionLabel': 'Description',
  'settings.persona.descriptionPlaceholder': 'e.g. A calm, concise assistant for my team.',
  'settings.persona.soul.heading': 'Personality (SOUL.md)',
  'settings.persona.soul.desc':
    'The personality prompt the assistant follows in every conversation. Edits are saved to your workspace and take effect on the next reply.',
  'settings.persona.soul.editorLabel': 'SOUL.md contents',
  'settings.persona.soul.reset': 'Reset to default',
  'settings.persona.soul.usingDefault': 'Using the bundled default',
  'settings.persona.soul.loadError': 'Could not load SOUL.md',
  'settings.persona.soul.saveError': 'Could not save SOUL.md',
  'settings.persona.soul.resetError': 'Could not reset SOUL.md',
  'settings.persona.appearanceHeading': 'Avatar & Voice',
  'settings.persona.appearanceDesc':
    'Mascot color, custom GIF avatar, and reply voice are configured in Mascot settings.',
  'settings.persona.openMascotSettings': 'Open Mascot settings',
  'settings.memoryWindow.balanced.badge': 'Recommended',
  'settings.memoryWindow.balanced.hint':
    'Sensible default — good continuity without burning extra tokens on every run.',
  'settings.memoryWindow.balanced.label': 'Balanced',
  'settings.memoryWindow.description':
    'How much remembered context OpenHuman injects into every new agent run. Larger windows feel more aware of past conversations but use more tokens — and cost more — on every run.',
  'settings.memoryWindow.extended.badge': 'More context',
  'settings.memoryWindow.extended.hint':
    'More long-term memory injected into each run. Higher token cost per turn.',
  'settings.memoryWindow.extended.label': 'Extended',
  'settings.memoryWindow.maximum.badge': 'Highest cost',
  'settings.memoryWindow.maximum.hint':
    'The largest safe window. Best continuity, meaningfully higher token bill on every run.',
  'settings.memoryWindow.maximum.label': 'Maximum',
  'settings.memoryWindow.minimal.badge': 'Cheapest',
  'settings.memoryWindow.minimal.hint':
    'Smallest memory window. Cheapest, fastest, least continuity between runs.',
  'settings.memoryWindow.minimal.label': 'Minimal',
  'settings.memoryWindow.title': 'Long-term memory window',
  'settings.agentbox.title': 'AgentBox',
  'settings.agentbox.desc': 'GMI Cloud marketplace adapter status and provider wiring',
  'settings.agentbox.intro':
    'Read-only status of the AgentBox marketplace adapter. Mode and the GMI MaaS provider are set by environment variables when the core starts.',
  'settings.agentbox.modeLabel': 'Marketplace mode',
  'settings.agentbox.providerHeading': 'GMI MaaS provider',
  'settings.agentbox.slug': 'Provider slug',
  'settings.agentbox.baseUrl': 'Base URL',
  'settings.agentbox.model': 'Model',
  'settings.agentbox.notConfigured':
    'Not configured. Set the GMI_MAAS_BASE_URL, GMI_MAAS_API_KEY, and GMI_MODELS environment variables.',
  'settings.agentbox.unavailable': 'AgentBox status unavailable',
  'settings.modelHealth.title': 'Model Health',
  'settings.modelHealth.desc':
    'Per-model quality, hallucination rate, and cost comparison across active models',
  'settings.modelHealth.allStatuses': 'All statuses',
  'settings.modelHealth.models': 'models',
  'settings.modelHealth.loading': 'Loading model data...',
  'settings.modelHealth.empty': 'No models registered',
  'settings.modelHealth.col.model': 'Model',
  'settings.modelHealth.col.quality': 'Quality',
  'settings.modelHealth.col.halluc': 'Halluc. Rate',
  'settings.modelHealth.col.cost': 'Cost / 1M out',
  'settings.modelHealth.col.agents': 'Agents',
  'settings.modelHealth.col.status': 'Status',
  'settings.modelHealth.badge.keep': 'Keep',
  'settings.modelHealth.badge.replace': 'Replace',
  'settings.modelHealth.badge.staging': 'Staging test',
  'settings.modelHealth.badge.vision': 'Vision only',
  'settings.modelHealth.swap': 'Swap?',
  'settings.modelHealth.modal.title': 'Replace Model?',
  'settings.modelHealth.modal.hallucRate': 'Hallucination rate',
  'settings.modelHealth.modal.cancel': 'Cancel',
  'settings.modelHealth.modal.apply': 'Apply Replacement',
  'settings.modelHealth.tag.cheaper': 'CHEAPER',
  'settings.modelHealth.tag.better': 'BETTER',
  'settings.desktopAgent.title': 'Desktop Agent',
  'settings.desktopAgent.beta':
    'Beta — the desktop agent is experimental and may not always work as expected.',
  'settings.desktopAgent.wakeWordHint': 'Say “Hey Tiny” before your command to wake the agent.',
  'settings.desktopAgent.description': 'Check and grant the permissions the desktop agent needs.',
  'settings.desktopAgent.microphone': 'Microphone',
  'settings.desktopAgent.grant': 'Grant',
  'settings.desktopAgent.notRequiredOnOs': 'Not required on this OS',
  'settings.desktopAgent.allGranted': 'All set — the desktop agent has every permission it needs.',
  'settings.desktopAgent.recheck': 'Recheck',
  'settings.desktopAgent.restartAndRecheck': 'Restart core & recheck',
  'settings.desktopAgent.seamless.title': 'Agent actions',
  'settings.desktopAgent.seamless.label': 'Let the agent act without asking',
  'settings.desktopAgent.seamless.description':
    'Grant Full access and auto-approve desktop actions (opening apps, controlling app interfaces) so the agent runs them without an approval prompt.',
  'settings.desktopAgent.seamless.note':
    'Only desktop actions skip the prompt — running shell commands, editing files, network requests, and installing software still ask. Turning this off stops auto-approving desktop actions but leaves the access level unchanged.',
  'settings.screenIntel.permissions.accessibility': 'Accessibility',
  'settings.screenIntel.permissions.grantHint':
    'Grant these permissions in System Settings, then restart the core.',
  'settings.screenIntel.permissions.inputMonitoring': 'Input Monitoring',
  'settings.screenIntel.permissions.macosAppliesPrivacy':
    'macOS controls these under System Settings → Privacy & Security.',
  'settings.screenIntel.permissions.openInputMonitoring': 'Open Input Monitoring',
  'settings.screenIntel.permissions.refreshStatus': 'Refreshing…',
  'settings.screenIntel.permissions.refreshing': 'Refreshing…',
  'settings.screenIntel.permissions.requestAccessibility': 'Request Accessibility',
  'settings.screenIntel.permissions.requestScreenRecording': 'Request Screen Recording',
  'settings.screenIntel.permissions.requesting': 'Requesting…',
  'settings.screenIntel.permissions.restartRefresh': 'Restarting core…',
  'settings.screenIntel.permissions.restartingCore': 'Restarting core…',
  'settings.screenIntel.permissions.screenRecording': 'Screen Recording',
  'settings.screenIntel.permissions.title': 'Permissions',
  'skills.card.moreActions': 'More actions',
  'skills.channelIcon.discord': 'Discord',
  'skills.channelIcon.imessage': 'iMessage',
  'skills.channelIcon.telegram': 'Telegram',
  'skills.channelIcon.web': 'Web',
  'skills.channelIcon.yuanbao': 'Yuanbao',
  'skills.composio.poweredBy': 'Powered by Composio',
  'skills.composio.staleStatusTitle': 'Connections are showing stale status',
  'skills.create.allowedTools': 'Allowed tools',
  'skills.create.allowedToolsHelp': 'Rendered into the SKILL.md frontmatter as',
  'skills.create.allowedToolsPlaceholder': 'node_exec, fetch',
  'skills.create.author': 'Author',
  'skills.create.authorPlaceholder': 'Your name',
  'skills.create.commaSeparated': '(comma-separated)',
  'skills.create.createBtn': 'Create skill',
  'skills.create.createError': 'Could not create skill',
  'skills.create.creating': 'Creating…',
  'skills.create.description': 'Description',
  'skills.create.descriptionPlaceholder': 'What does this workflow do?',
  'skills.create.optional': '(optional)',
  'skills.create.whenToUse': 'When to use',
  'skills.create.whenToUsePlaceholder': 'e.g. when the user asks to triage their inbox',
  'skills.create.whenToUseHelp':
    'The trigger an agent matches on to decide to run this workflow. Leave blank to reuse the description.',
  'skills.create.inputs.heading': 'Inputs',
  'skills.create.inputs.help':
    'Declare parameters the workflow needs. Adding inputs is optional, but every input you add needs a description — it is shown to the agent and in the run form. Inputs are optional to fill unless you mark them Required.',
  'skills.create.inputs.add': 'Add input',
  'skills.create.inputs.row.name': 'Input name',
  'skills.create.inputs.row.namePlaceholder': 'e.g. repo',
  'skills.create.inputs.row.nameError':
    'Letters, digits, underscores, and dashes only; must start with a letter.',
  'skills.create.inputs.row.description': 'Input description',
  'skills.create.inputs.row.descriptionPlaceholder': 'What goes in this field?',
  'skills.create.inputs.row.descriptionError': 'A description is required for each input.',
  'skills.create.inputs.row.type': 'Type',
  'skills.create.inputs.row.required': 'Required',
  'skills.create.inputs.row.remove': 'Remove input',
  'skills.create.inputs.type.string': 'Text',
  'skills.create.inputs.type.integer': 'Number',
  'skills.create.inputs.type.boolean': 'Yes / No',
  'skills.create.license': 'License',
  'skills.create.licensePlaceholder': 'MIT',
  'skills.create.name': 'Name',
  'skills.create.namePlaceholder': 'e.g. Trade Journal',
  'skills.create.scope': 'Scope',
  'skills.create.scopeProjectHint': '/.openhuman/skills/',
  'skills.create.scopeUserHint':
    'Written to ~/.openhuman/skills/<slug>/SKILL.md — available across all workspaces.',
  'skills.create.slugLabel': 'Slug',
  'skills.create.subtitle': 'SKILL.md',
  'skills.create.tags': 'Tags',
  'skills.create.tagsPlaceholder': 'trading, research',
  'skills.create.title': 'New skill',
  'skills.detail.allowedTools': 'Allowed tools',
  'skills.detail.author': 'Author',
  'skills.detail.license': 'License',
  'skills.detail.description': 'Description',
  'skills.detail.bundledResources': 'Bundled resources',
  'skills.detail.run': 'Run',
  'skills.detail.runAriaLabel': 'Run this workflow',
  'skills.run.title': 'Workflow',
  'skills.detail.closeAriaLabel': 'Close skill details',
  'skills.detail.location': 'Location',
  'skills.detail.noBundledResources': 'No bundled resources.',
  'skills.detail.platforms': 'Platforms',
  'skills.detail.relatedSkills': 'Related skills',
  'skills.detail.source': 'Source URL',
  'skills.detail.sourceFormat': 'Format',
  'skills.detail.stars': 'Stars',
  'skills.detail.tags': 'Tags',
  'skills.detail.version': 'Version',
  'skills.detail.warnings': 'Warnings',
  'skills.install.errors.alreadyInstalledHint':
    'A skill with this slug already exists in the workspace. Remove it first or change the frontmatter `metadata.id` / `name`.',
  'skills.install.errors.alreadyInstalledTitle': 'Skill already installed',
  'skills.install.errors.fetchFailedHint':
    'The request did not complete successfully. Check the URL points at a reachable public file, and that the host returned a 2xx response.',
  'skills.install.errors.fetchFailedTitle': 'Fetch failed',
  'skills.install.errors.fetchTimedOutHint':
    'The remote host did not respond in time. Try again or raise the timeout (1-600 s).',
  'skills.install.errors.fetchTimedOutTitle': 'Fetch timed out',
  'skills.install.errors.fetchTooLargeHint':
    'The SKILL.md must be under 1 MiB. Split bundled resources into `references/` or `scripts/` files instead of inlining them.',
  'skills.install.errors.fetchTooLargeTitle': 'SKILL.md too large',
  'skills.install.errors.genericHint':
    'The backend returned an error. The raw message is shown below.',
  'skills.install.errors.genericTitle': 'Could not install skill',
  'skills.install.errors.invalidSkillHint':
    'The frontmatter must be valid YAML with non-empty `name` and `description` fields, terminated by `---`.',
  'skills.install.errors.invalidSkillTitle': 'SKILL.md did not parse',
  'skills.install.errors.invalidUrlHint':
    'Only public HTTPS URLs are allowed. Private, loopback, and metadata hosts are blocked.',
  'skills.install.errors.invalidUrlTitle': 'URL rejected',
  'skills.install.errors.unsupportedUrlHint':
    'Only direct `.md` links work. For GitHub, link to a file (github.com/owner/repo/blob/.../SKILL.md) - tree and repo roots are not installed.',
  'skills.install.errors.unsupportedUrlTitle': 'URL form not supported',
  'skills.install.errors.writeFailedHint':
    'The workspace skills directory was not writable. Check filesystem permissions for `<workspace>/.openhuman/skills/`.',
  'skills.install.errors.writeFailedTitle': 'Could not write SKILL.md',
  'skills.install.fetchLog': 'Fetch log',
  'skills.install.fetchingPrefix': 'Fetching',
  'skills.install.fetchingSuffix': 'this can take up to the timeout you configured.',
  'skills.install.installBtn': 'Install skill',
  'skills.install.installComplete': 'Install complete',
  'skills.install.installing': 'Installing…',
  'skills.install.parseWarnings': 'Parse warnings',
  'skills.install.rawError': 'Raw error',
  'skills.install.subtitleMiddle': 'over HTTPS and installs it under',
  'skills.install.subtitlePrefix': 'Fetches a single',
  'skills.install.subtitleSuffix': 'HTTPS only; private and loopback hosts are blocked.',
  'skills.install.successDiscovered': 'Discovered {count} new skill(s).',
  'skills.install.successNoNewIds':
    'Skill installed, but no new skill ids appeared - the catalog may already contain a skill with the same slug.',
  'skills.install.timeoutHint': '(seconds, optional)',
  'skills.install.timeoutHelp':
    'Defaults to 60 seconds. Values outside 1-600 are clamped server-side.',
  'skills.install.timeoutInvalid': 'Must be an integer between 1 and 600.',
  'skills.install.timeoutLabel': 'Timeout',
  'skills.install.timeoutPlaceholder': '60',
  'skills.install.title': 'Install skill from URL',
  'skills.install.urlHelpMiddle': 'file.',
  'skills.install.urlHelpPrefix': 'Direct link to a',
  'skills.install.urlHelpSuffix': 'URLs auto-rewrite to',
  'skills.install.urlInvalidPrefix': 'URL must be a well-formed',
  'skills.install.urlInvalidSuffix': 'link.',
  'skills.install.urlLabel': 'Skill URL',
  'skills.install.urlPlaceholder': 'https://raw.githubusercontent.com/owner/repo/main/SKILL.md',
  'skills.meetingBots.bannerDesc':
    'OpenHuman joins calls silently and handles notes and follow-ups automatically.',
  'skills.meetingBots.bannerTitle': 'Send OpenHuman to your next meeting',
  'skills.meetingBots.busyTitle': 'OpenHuman is busy',
  'skills.meetingBots.comingSoon': 'coming soon',
  'skills.meetingBots.couldNotLeaveTitle': 'Couldn’t leave the meeting',
  'skills.meetingBots.couldNotStartTitle': 'Could not start OpenHuman',
  'skills.meetingBots.displayName': 'Display name',
  'skills.meetingBots.failedToStart': 'Failed to start OpenHuman.',
  'skills.meetingBots.joiningMessage': 'It should appear as a participant in a few seconds.',
  'skills.meetingBots.joiningTitle': 'OpenHuman is joining the meeting',
  'skills.meetingBots.meetingLink': 'Meeting link',
  'skills.meetingBots.modalAriaLabel': 'Send OpenHuman to a meeting',
  'skills.meetingBots.modalDesc':
    'OpenHuman will join as a silent participant and help with notes and follow-ups.',
  'skills.meetingBots.modalTitle': 'Send OpenHuman to a meeting',
  'skills.meetingBots.newBadge': 'New',
  'skills.meetingBots.platformComingSoon': '{label} support is coming soon.',
  'skills.meetingBots.platformHints.gmeet': 'meet.google.com/abc-defg-hij',
  'skills.meetingBots.platformHints.teams': 'teams.microsoft.com/...',
  'skills.meetingBots.platformHints.webex': 'webex.com/meet/...',
  'skills.meetingBots.platformHints.zoom': 'zoom.us/j/...',
  'skills.meetingBots.platforms.gmeet': 'Google Meet',
  'skills.meetingBots.platforms.teams': 'Microsoft Teams',
  'skills.meetingBots.platforms.webex': 'Webex',
  'skills.meetingBots.platforms.zoom': 'Zoom',
  'skills.meetingBots.sendTo': 'Send to {label}',
  'skills.meetingBots.serverOverloaded':
    'OpenHuman is under heavy load right now. Please try again in a few minutes.',
  'skills.meetingBots.soonSuffix': 'soon',
  'skills.meetingBots.starting': 'Starting…',
  'skills.meetingBots.recentCallsAriaLabel': 'Recent meeting calls',
  'skills.meetingBots.recentCallsHeading': 'Recent calls',
  'skills.meetingBots.recentCallsEmpty':
    'No previous calls yet — your meeting history will appear here.',
  'skills.meetingBots.recentCallsLoading': 'Loading\u2026',
  'skills.meetingBots.recentCallAddedBy': 'Added by {name}',
  'skills.meetingBots.recentCallParticipants': 'With {names}',
  'skills.meetingBots.recentCallTurnSingular': '{count} turn',
  'skills.meetingBots.recentCallTurnPlural': '{count} turns',
  'skills.meetingBots.recentCallDuration': '{seconds}s on call',
  'skills.meetingBots.callDetailLoading': 'Loading transcript…',
  'skills.meetingBots.callDetailError': 'Couldn’t load the transcript.',
  'skills.meetingBots.callDetailRetry': 'Retry',
  'skills.meetingBots.callDetailEmpty': 'No transcript or summary was captured for this call.',
  'skills.meetingBots.callSummaryHeading': 'Summary',
  'skills.meetingBots.callKeyPointsHeading': 'Key points',
  'skills.meetingBots.callActionItemsHeading': 'Action items',
  'skills.meetingBots.callTranscriptHeading': 'Transcript',
  'skills.meetingBots.liveBadge': 'Live',
  'skills.meetingBots.liveTitle': 'In Meeting',
  'skills.meetingBots.liveStatusJoining': 'Joining\u2026',
  'skills.meetingBots.liveStatusActive': 'Live in meeting',
  'skills.meetingBots.liveStatusListening': 'Listening (muted)',
  'skills.meetingBots.liveStatusEnded': 'Meeting ended',
  'skills.meetingBots.liveStatusError': 'Failed to join',
  'skills.meetingBots.liveTranscriptHeading': 'Live transcript',
  'skills.meetingBots.liveTranscriptEmpty': 'Waiting for speech…',
  'skills.meetingBots.leaveButton': 'Leave',
  'skills.meetingBots.leavingButton': 'Leaving…',
  'skills.meetingBots.respondToParticipant': 'Your Name in This Meeting',
  'skills.meetingBots.respondToParticipantHint': 'e.g. Alice (your display name in the call)',
  'skills.meetingBots.respondToParticipantDesc':
    'Enter your exact display name from the meeting. The bot only responds when you say its name (wake phrase).',
  'skills.meetingBots.wakePhrase': 'Wake Phrase',
  'skills.meetingBots.wakePhraseHint': 'Hey OpenHuman',
  'skills.meetingBots.wakePhraseDesc': 'Participant must say this before the bot responds.',
  'skills.meetingBots.activeMode': 'Respond when I address it',
  'skills.meetingBots.activeModeDesc':
    'When on, the bot speaks a reply after you say its wake phrase. When off, it only listens and transcribes.',
  'skills.meetingBots.history.allPlatforms': 'All platforms',
  'skills.meetingBots.history.copyTranscript': 'Copy',
  'skills.meetingBots.history.downloadTranscript': 'Download',
  'skills.meetingBots.history.earlier': 'Earlier',
  'skills.meetingBots.history.participantCount': '{count} participant',
  'skills.meetingBots.history.participantCountPlural': '{count} participants',
  'skills.meetingBots.history.runWithOpenHuman': 'Run with OpenHuman',
  'skills.meetingBots.history.searchPlaceholder': 'Search calls…',
  'skills.meetingBots.history.selectPrompt': 'Select a call to see its summary and transcript.',
  'skills.meetingBots.history.today': 'Today',
  'skills.meetingBots.history.yesterday': 'Yesterday',
  'skills.meetingBots.upcoming.heading': 'Upcoming',
  'skills.meetingBots.upcoming.when': 'When',
  'skills.meetingBots.upcoming.meeting': 'Meeting',
  'skills.meetingBots.upcoming.platform': 'Platform',
  'skills.meetingBots.upcoming.people': 'People',
  'skills.meetingBots.upcoming.joinPolicy': 'Join Policy',
  'skills.meetingBots.upcoming.joinNow': 'Join now',
  'skills.meetingBots.upcoming.joinNowAriaLabel': 'Join {title}',
  'skills.meetingBots.upcoming.join': 'Join',
  'skills.meetingBots.upcoming.auto': 'Auto',
  'skills.meetingBots.upcoming.ask': 'Ask',
  'skills.meetingBots.upcoming.skip': 'Skip',
  'skills.meetingBots.upcoming.today': 'Today',
  'skills.meetingBots.upcoming.tomorrow': 'Tomorrow',
  'skills.meetingBots.upcoming.empty':
    'No upcoming meetings — connect Google Calendar to see them here.',
  'skills.meetingBots.upcoming.error': 'Couldn’t load upcoming meetings.',
  'skills.meetingBots.upcoming.retry': 'Retry',
  'skills.meetingBots.upcoming.refresh': 'Refresh',
  'skills.meetingBots.upcoming.filterAll': 'All platforms',
  'skills.meetingBots.upcoming.participants': '{count} participants',
  'skills.meetingBots.upcoming.imminent': 'Starting soon',
  'skills.meetingBots.upcoming.autoJoinsAt': 'Auto-joins ~at {time}',
  'skills.meetingBots.upcoming.asksAtStart': 'Asks at start',
  'skills.meetingBots.relative.now': 'now',
  'skills.meetingBots.relative.inMinutes': 'in {count}m',
  'skills.meetingBots.relative.inHours': 'in {count}h',
  'skills.meetingBots.relative.minutesAgo': '{count}m ago',
  'skills.meetingBots.relative.hoursAgo': '{count}h ago',
  'skills.meetingBots.relative.daysAgo': '{count}d ago',
  'skills.meetingBots.relative.yesterday': 'yesterday',
  'skills.meetingBots.defaults.drawerTitle': 'Meeting Defaults',
  'skills.meetingBots.defaults.closeDrawer': 'Close defaults',
  'skills.meetingBots.defaults.openDefaults': 'Meeting defaults',
  'skills.meetingBots.defaults.watchCalendar': 'Watch my calendar',
  'skills.meetingBots.defaults.watchCalendarDesc':
    'Let OpenHuman watch your connected calendar so it can auto-join or prompt for meetings based on the policies below. This is separate from meeting reminder notifications.',
  'skills.meetingBots.defaults.globalPolicy': 'Global auto-join policy',
  'skills.meetingBots.defaults.perPlatformTitle': 'Per-platform overrides',
  'skills.meetingBots.defaults.perPlatformDesc':
    'Override the global policy for specific platforms.',
  'skills.meetingBots.defaults.useDefault': 'Use default',
  'skills.meetingBots.upcoming.watchCalendarHint':
    "Turn on 'Watch my calendar' in Defaults (gear icon) for Auto/Ask to take effect — otherwise these policies are saved but won't trigger.",
  'skills.resource.preview.closeAriaLabel': 'Close preview',
  'skills.resource.preview.failed': 'Preview failed',
  'skills.resource.preview.loading': 'Loading preview…',
  'skills.resource.tree.assets': 'Assets',
  'skills.resource.tree.empty': 'No bundled resources.',
  'skills.resource.tree.examples': 'Examples',
  'skills.resource.tree.other': 'Other',
  'skills.resource.tree.prompts': 'Prompts',
  'skills.resource.tree.references': 'References',
  'skills.resource.tree.scripts': 'Scripts',
  'skills.resource.tree.templates': 'Templates',
  'skills.search.placeholder': 'Search skills…',
  'skills.setup.autocomplete.acceptKey': 'Accept key',
  'skills.setup.autocomplete.activeDesc': 'Inline completions are running and ready.',
  'skills.setup.autocomplete.activeTitle': 'Auto-Complete is Active',
  'skills.setup.autocomplete.customizeSettings': 'Customize settings',
  'skills.setup.autocomplete.debounce': 'Debounce',
  'skills.setup.autocomplete.description': 'AI-powered inline text completions as you type.',
  'skills.setup.autocomplete.enableBtn': 'Enabling...',
  'skills.setup.autocomplete.enableError': 'Failed to enable autocomplete',
  'skills.setup.autocomplete.enabling': 'Enabling...',
  'skills.setup.autocomplete.notSupported': 'Not supported',
  'skills.setup.autocomplete.stepEnable': 'Enable inline completions',
  'skills.setup.autocomplete.stepSuccess': 'Ready to go',
  'skills.setup.autocomplete.stylePreset': 'Style preset',
  'skills.setup.autocomplete.stylePresetValue': 'Balanced (configurable later)',
  'skills.setup.autocomplete.title': 'Text Auto-Complete',
  'skills.setup.screenIntel.activeDesc':
    'Screen Intelligence is running and reading your active window.',
  'skills.setup.screenIntel.activeTitle': 'Screen Intelligence is Enabled',
  'skills.setup.screenIntel.advancedSettings': 'Advanced settings',
  'skills.setup.screenIntel.allGranted': 'All permissions granted',
  'skills.setup.screenIntel.captureMode': 'Capture mode',
  'skills.setup.screenIntel.captureModeValue': 'All windows (configurable later)',
  'skills.setup.screenIntel.deniedHint':
    'After granting permissions in System Settings, click below to restart and pick up the changes.',
  'skills.setup.screenIntel.enableBtn': 'Enabling...',
  'skills.setup.screenIntel.enableDesc':
    'Reads what is on your screen and feeds useful context into your agent.',
  'skills.setup.screenIntel.enableError': 'Failed to enable Screen Intelligence',
  'skills.setup.screenIntel.enabling': 'Enabling...',
  'skills.setup.screenIntel.grant': 'Opening...',
  'skills.setup.screenIntel.granted': 'Granted',
  'skills.setup.screenIntel.macosOnly': 'macOS only',
  'skills.setup.screenIntel.opening': 'Opening...',
  'skills.setup.screenIntel.panicHotkey': 'Panic hotkey',
  'skills.setup.screenIntel.permAccessibility': 'Accessibility',
  'skills.setup.screenIntel.permInputMonitoring': 'Input Monitoring',
  'skills.setup.screenIntel.permScreenRecording': 'Screen Recording',
  'skills.setup.screenIntel.permissionsDesc':
    'Screen Intelligence requires accessibility, input monitoring, and screen recording permissions.',
  'skills.setup.screenIntel.permissionPathLabel': 'macOS applies privacy to:',
  'skills.setup.screenIntel.refreshStatus': 'Refresh status',
  'skills.setup.screenIntel.restartRefresh': 'Restarting...',
  'skills.setup.screenIntel.restarting': 'Restarting...',
  'skills.setup.screenIntel.stepEnable': 'Enable the skill',
  'skills.setup.screenIntel.stepPermissions': 'Grant permissions',
  'skills.setup.screenIntel.stepSuccess': 'Ready to go',
  'skills.setup.screenIntel.title': 'Screen Intelligence',
  'skills.setup.screenIntel.visionModel': 'Vision model',
  'skills.setup.voice.activation': 'Activation',
  'skills.setup.voice.activeDescPrefix': 'Fn',
  'skills.setup.voice.activeDescSuffix': 'Fn',
  'skills.setup.voice.activeTitle': 'Voice Intelligence is Active',
  'skills.setup.voice.customizeSettings': 'Customize settings',
  'skills.setup.voice.downloadSttBtn': 'Download STT model',
  'skills.setup.voice.enableDesc': 'Dictate text hands-free using your microphone.',
  'skills.setup.voice.hotkey': 'Hotkey',
  'skills.setup.voice.startBtn': 'Starting...',
  'skills.setup.voice.startError': 'Failed to start voice server',
  'skills.setup.voice.starting': 'Starting...',
  'skills.setup.voice.stepEnable': 'Start voice server',
  'skills.setup.voice.stepSetup': 'Model download required',
  'skills.setup.voice.stepSuccess': 'Ready to go',
  'skills.setup.voice.sttNotReady': 'Speech-to-text model not ready',
  'skills.setup.voice.sttNotReadyDesc':
    'Voice Intelligence requires a local Whisper model for transcription. Download it from the Local Model settings.',
  'skills.setup.voice.sttReady': 'Speech-to-text model ready',
  'skills.setup.voice.sttReturnHint': 'The speech-to-text model is loading. Come back in a moment.',
  'skills.setup.voice.title': 'Voice Intelligence',
  'skills.uninstall.couldNotUninstall': 'Could not uninstall',
  'skills.uninstall.description':
    'This permanently deletes the skill directory and all its bundled resources. The agent will stop seeing it at the next turn.',
  'skills.uninstall.title': 'Uninstall',
  'skills.uninstall.uninstallBtn': 'Uninstall',
  'skills.uninstall.uninstalling': 'Uninstalling…',
  'upsell.global.limitMessage': 'Upgrade your plan or top up credits to continue',
  'upsell.global.limitTitle': 'Usage limit reached',
  'upsell.global.nearLimitMessage':
    "You've used {pct}% of your usage limit. Upgrade for higher limits.",
  'upsell.global.nearLimitTitle': 'Approaching usage limit',
  'upsell.usageLimit.bodyBudget': "You've hit your weekly limit. {resetTime}",
  'upsell.usageLimit.bodyRate': "You've hit your 10-hour inference rate limit. {resetTime}",
  'upsell.usageLimit.heading': 'Usage Limit Reached',
  'upsell.usageLimit.notNow': 'Not now',
  'upsell.usageLimit.perWindow': '{amount}',
  'upsell.usageLimit.planIncludes': '{plan}',
  'upsell.usageLimit.resetsIn': 'Resets in {time}',
  'upsell.usageLimit.upgradePlan': 'Upgrade plan',
  'upsell.usageLimit.weeklyInference': '{amount}',
  'walkthrough.steps.startChat.title': 'Start in chat',
  'walkthrough.steps.startChat.content':
    'Chat is your starting point. New windows open with the same greeting and quick actions you saw after setup.',
  'walkthrough.steps.sayHello.title': 'Say hello',
  'walkthrough.steps.sayHello.content':
    'Tap here to start a conversation with your AI assistant anytime.',
  'walkthrough.steps.meetAi.title': 'Meet your AI',
  'walkthrough.steps.meetAi.content':
    'This is where conversations happen. Ask questions, get summaries, or brainstorm. Everything stays searchable.',
  'walkthrough.steps.connectWorld.title': 'Connect your world',
  'walkthrough.steps.connectWorld.content':
    'Gmail, Slack, WhatsApp, and more - each connection gives your assistant superpowers.',
  'walkthrough.steps.messagingApps.title': 'Chat where you already are',
  'walkthrough.steps.messagingApps.content':
    'WhatsApp, Telegram, Slack, Discord - connect your messaging apps so your assistant can reach you anywhere.',
  'walkthrough.steps.settings.title': 'Make it yours',
  'walkthrough.steps.settings.content':
    'Preferences, privacy, notifications - everything is here. You can restart this tour anytime from this page.',
  'walkthrough.steps.chatTab.title': 'Jump back to chat',
  'walkthrough.steps.chatTab.content':
    'Use the Chat tab whenever you want to return to conversations.',
  'walkthrough.steps.humanTab.title': 'Meet your human profile',
  'walkthrough.steps.humanTab.content':
    'Human is where your personal context, identity, and assistant-facing profile come together.',
  'walkthrough.steps.brainTab.title': 'Open your Brain',
  'walkthrough.steps.brainTab.content':
    'Brain is the memory graph: the place to inspect what OpenHuman knows and how ideas connect.',
  'walkthrough.steps.agentWorldTab.title': 'Explore Agent World',
  'walkthrough.steps.agentWorldTab.content':
    'Agent World is where reusable agents and shared automations live.',
  'walkthrough.steps.connectionsTab.title': 'Manage connections',
  'walkthrough.steps.connectionsTab.content':
    'Connections is always available from the main nav when you want to add or adjust services.',
  'walkthrough.steps.feedbackTab.title': 'Send feedback',
  'walkthrough.steps.feedbackTab.content':
    'Feedback gives you a direct place to report rough edges or ask for improvements.',
  'walkthrough.steps.allSet.title': "You're all set!",
  'walkthrough.steps.allSet.content':
    'Your assistant left you a welcome note - this is your space to chat, ask questions, or brainstorm. Have fun!',
  'walkthrough.tooltip.letsGo': "Let's go!",
  'walkthrough.tooltip.next': 'Next →',
  'walkthrough.tooltip.skip': 'Skip tour',
  'walkthrough.tooltip.stepCounter': '{n} of {total}',
  'webhooks.activity.empty': 'No recent activity',
  'webhooks.activity.title': 'Recent Activity',
  'webhooks.composioHistory.empty': 'Empty',
  'webhooks.composioHistory.metadataId': 'Metadata ID',
  'webhooks.composioHistory.metadataUuid': 'Metadata UUID',
  'webhooks.composioHistory.payload': 'Payload',
  'webhooks.composioHistory.title': 'Composio Trigger History',
  'webhooks.tunnels.active': 'Active',
  'webhooks.tunnels.createFailed': 'Failed to create tunnel',
  'webhooks.tunnels.creating': 'Creating...',
  'webhooks.tunnels.deleteFailed': 'Failed to delete tunnel',
  'webhooks.tunnels.descriptionPlaceholder': 'Description (optional)',
  'webhooks.tunnels.echo': 'Echo',
  'webhooks.tunnels.empty': 'No tunnels configured',
  'webhooks.tunnels.enableEcho': 'Enable Echo',
  'webhooks.tunnels.inactive': 'Inactive',
  'webhooks.tunnels.namePlaceholder': 'Tunnel name (e.g. telegram-bot)',
  'webhooks.tunnels.newTunnel': 'New tunnel',
  'webhooks.tunnels.removeEcho': 'Remove Echo',
  'webhooks.tunnels.title': 'Webhook Tunnels',
  'webhooks.tunnels.toggleFailed': 'Failed to toggle echo',
  'composio.directModeRequiresKey': 'Failed to save. Direct mode requires a non-empty API key.',
  'composio.integrationSlugsHelp': 'Comma-separated integration slugs, e.g.',
  'composio.integrationSlugsExample': 'gmail, slack',
  'composio.integrationSlugsCaseInsensitive': 'Case-insensitive.',
  'composio.integrationSlugsPlaceholder': 'gmail, slack, ...',
  'composio.notYetRouted': 'not yet routed',
  'composio.triggers.loading': 'Loading…',
  'conversations.taskKanban.todo': 'To do',
  'chat.addReaction': 'Add reaction',
  'chat.agentProfile.create': 'Create agent profile',
  'chat.agentProfile.createFailed': 'Could not create agent profile.',
  'chat.agentProfile.customDescription': 'Custom agent profile',
  'chat.agentProfile.defaultAgentLabel': 'Orchestrator',
  'chat.agentProfile.exists': 'Agent profile "{name}" already exists.',
  'chat.agentProfile.label': 'Agent profile',
  'chat.agentProfile.quick': 'Quick',
  'chat.agentProfile.reasoning': 'Reasoning',
  'chat.agentProfile.namePlaceholder': 'Profile name',
  'chat.agentProfile.promptStylePlaceholder': 'Prompt style',
  'chat.agentProfile.allowedToolsPlaceholder': 'Allowed tools',
  'chat.backToThread': 'back to {title}',
  'chat.parentThread': 'parent thread',
  'chat.removeReaction': 'Remove {emoji}',
  'settings.composio.loading': 'Loading…',
  'settings.mascot.noCharactersAvailable': 'No OpenHuman characters are available yet',
  'skills.uninstall.confirmTitle': 'Uninstall {name}?',
  'conversations.taskKanban.blocked': 'Blocked',
  'conversations.taskKanban.done': 'Done',
  'conversations.taskKanban.pending': 'Pending',
  'conversations.taskKanban.working': 'Working',
  'conversations.taskKanban.awaitingApproval': 'Awaiting approval',
  'conversations.taskKanban.ready': 'Ready',
  'conversations.taskKanban.rejected': 'Rejected',
  'conversations.taskKanban.inProgress': 'In progress',
  'conversations.taskKanban.awaitingApprovalColumn': 'Awaiting Approval',
  'conversations.taskKanban.blockedColumn': 'Blocked',
  'conversations.taskKanban.evidenceBadge': 'Evidence ({count})',
  'conversations.taskKanban.needsInput': 'These tasks need your input',
  'conversations.taskKanban.emptyColumn': 'No tasks',
  'conversations.taskKanban.dragHint': 'Drag to move between columns',
  'conversations.taskKanban.movingCard': 'Moving…',
  'conversations.taskKanban.statusBadge.ready': 'Ready to start',
  'conversations.taskKanban.statusBadge.rejected': 'Rejected',
  'intelligence.memoryChunk.detail.copiedHint': 'copied',
  'settings.composio.notYetRouted': 'not yet routed',
  'settings.localModel.download.manageExternal': 'Manage this model in your external runtime.',
  'settings.localModel.status.manageOllamaExternal':
    'Manage the Ollama process and model pulls outside OpenHuman, then rerun diagnostics.',
  'settings.localModel.status.ollamaDocs': 'Ollama docs',
  'settings.localModel.status.thenRetry':
    'for setup instructions, then retry after your runtime is reachable.',
  // Developer options menu items (#2225)
  'devOptions.menuAi': 'AI Configuration',
  'devOptions.menuAiDesc': 'Cloud providers, local Ollama models, and per-workload routing',
  'devOptions.menuScreenAware': 'Screen Awareness',
  'devOptions.menuScreenAwareDesc':
    'Screen capture permissions, monitoring policy, and session controls',
  'devOptions.menuMessaging': 'Messaging Channels',
  'devOptions.menuMessagingDesc':
    'Configure Telegram/Discord auth modes and default channel routing',
  'devOptions.menuTools': 'Tools',
  'devOptions.menuToolsDesc': 'Enable or disable capabilities OpenHuman can use on your behalf',
  'devOptions.menuAgentChat': 'Agent Chat',
  'devOptions.menuAgentChatDesc': 'Test agent conversation with model and temperature overrides',
  'devOptions.menuCronJobs': 'Cron Jobs',
  'devOptions.menuCronJobsDesc': 'View and configure scheduled jobs for runtime skills',
  'devOptions.menuLocalModelDebug': 'Local Model Debug',
  'devOptions.menuLocalModelDebugDesc':
    'Ollama config, asset downloads, model tests, and diagnostics',
  'devOptions.menuWebhooksDebug': 'Webhooks',
  'devOptions.menuWebhooksDebugDesc':
    'Inspect runtime webhook registrations and captured request logs',
  'devOptions.menuIntelligence': 'Intelligence',
  'devOptions.menuIntelligenceDesc': 'Memory workspace, subconscious engine, dreams, and settings',
  'devOptions.menuNotificationRouting': 'Notification Routing',
  'devOptions.menuNotificationRoutingDesc':
    'AI importance scoring and orchestrator escalation for integration alerts',
  'devOptions.menuComposeIOTriggers': 'ComposeIO Triggers',
  'devOptions.menuComposeIOTriggersDesc': 'View ComposeIO trigger history and archive',
  'devOptions.menuComposioRouting': 'Composio Routing (Direct Mode)',
  'devOptions.menuComposioRoutingDesc':
    'Bring your own Composio API key and route calls directly to backend.composio.dev',
  'devOptions.menuComposioTriggers': 'Integration Triggers',
  'devOptions.menuComposioTriggersDesc':
    'Configure AI triage settings for Composio integration triggers',
  'memory.sourceFilterAria': 'Filter by source',
  'calls.comingSoonDescription': 'AI-assisted calls are coming soon. Stay tuned.',
  'whatsapp.title': 'WhatsApp',
  'subconscious.priority.critical': 'critical',
  'subconscious.priority.important': 'important',
  'subconscious.priority.normal': 'normal',
  'subconscious.durationSeconds': '{seconds}s',
  'subconscious.durationMilliseconds': '{milliseconds}ms',
  // Settings menu: Appearance + Mascot (#2225)
  'settings.appearance': 'Appearance',
  'settings.appearanceDesc': 'Pick light, dark, or match your system theme',
  'settings.mascot': 'Mascot',
  'settings.mascotDesc': 'Pick the mascot color used across the app',
  // Settings > Account > Wallet Balances
  'pages.settings.account.walletBalances': 'Wallet Balances',
  'pages.settings.account.walletBalancesDesc': 'View multi-chain balances for your local wallet',
  // WalletBalancesPanel strings
  'walletBalances.title': 'Wallet Balances',
  'walletBalances.refresh': 'Refresh',
  'walletBalances.loading': 'Loading balances…',
  'walletBalances.retry': 'Retry',
  'walletBalances.emptyState': 'No wallet accounts yet — set up a wallet in Recovery Phrase.',
  'walletBalances.copyAddress': 'Copy address',
  'walletBalances.providerMissing': 'provider unavailable',
  'walletBalances.rawBalance': 'Raw: {raw}',
  'walletBalances.errorGeneric':
    'Unable to load wallet balances. Set up your wallet in Recovery Phrase and try again.',
  'walletBalances.setupHint':
    "Your recovery phrase isn't set up yet. Set it up to enable your wallet and see live balances.",
  'walletBalances.setupCta': 'Set up recovery phrase',
  'walletBalances.notSetUp': 'Not set up',
  'walletBalances.send': 'Send',
  'walletBalances.receive': 'Receive',
  // Receive modal
  'walletReceive.scanHint': 'Scan this code or copy the address below to receive funds.',
  'walletReceive.addressLabel': '{network} address',
  'walletReceive.onlyChainWarning':
    'Only send {network} assets to this address. Sending assets from another network may result in permanent loss.',
  // Send modal
  'walletSend.available': 'Available',
  'walletSend.recipient': 'Recipient address',
  'walletSend.recipientPlaceholder': 'Paste the destination address',
  'walletSend.recipientRequired': 'Enter a recipient address',
  'walletSend.amount': 'Amount',
  'walletSend.invalidAmount': 'Enter a valid amount',
  'walletSend.review': 'Review',
  'walletSend.preparing': 'Preparing…',
  'walletSend.confirmHint':
    'Review the details below. Signing happens locally — nothing is broadcast until you confirm.',
  'walletSend.estimatedFee': 'Estimated network fee',
  'walletSend.confirmSend': 'Confirm & send',
  'walletSend.sending': 'Sending…',
  'walletSend.sent': 'Transaction sent',
  'walletSend.txHash': 'Transaction hash',
  'walletSend.viewExplorer': 'View on explorer',
  'walletSend.done': 'Done',
  'walletSend.genericError': 'Could not complete the transfer. Please try again.',
  // Task sources (#task-sources)
  'settings.taskSources.title': 'Task Sources',
  'settings.integrations.title': 'Integrations',
  'settings.integrations.menuDesc': 'Task sources, Composio routing, and webhook triggers',
  'settings.taskSources.subtitle': 'Pull tasks from your tools onto the agent todo board',
  'settings.taskSources.description':
    'Collect work items from GitHub, Notion, Linear, and ClickUp, enrich them, and route them onto the agent todo board.',
  'settings.taskSources.connectHint':
    'Task sources use your connected accounts. Connect them under Integrations first.',
  'settings.taskSources.disabledBanner':
    'Task sources are disabled in settings. Enable them to poll automatically.',
  'settings.taskSources.loadError': 'Failed to load task sources',
  'settings.taskSources.addTitle': 'Add a task source',
  'settings.taskSources.provider': 'Provider',
  'settings.taskSources.name': 'Name (optional)',
  'settings.taskSources.namePlaceholder': 'e.g. My open issues',
  'settings.taskSources.github.repo': 'Repository (owner/name, optional)',
  'settings.taskSources.github.labels': 'Labels (comma-separated)',
  'settings.taskSources.notion.database': 'Database (board) ID',
  'settings.taskSources.notion.browseDatabases': 'Browse databases',
  'settings.taskSources.notion.loadingDatabases': 'Loading databases…',
  'settings.taskSources.notion.selectDatabase': 'Select a database…',
  'settings.taskSources.notion.noDatabases': 'No databases found for this connection.',
  'settings.taskSources.linear.team': 'Team ID (optional)',
  'settings.taskSources.clickup.team': 'Workspace (team) ID (optional)',
  'settings.taskSources.assignedToMe': 'Only items assigned to me',
  'settings.taskSources.add': 'Add source',
  'settings.taskSources.adding': 'Adding…',
  'settings.taskSources.preview': 'Preview',
  'settings.taskSources.previewResult': '{count} task(s) match this filter',
  'settings.taskSources.fetchNow': 'Fetch now',
  'settings.taskSources.fetching': 'Fetching…',
  'settings.taskSources.fetchResult':
    'Routed {routed} of {fetched} task(s); removed {pruned} stale task(s)',
  'settings.taskSources.syncAll': 'Sync all',
  'settings.taskSources.syncing': 'Syncing…',
  'settings.taskSources.configured': 'Configured sources',
  'settings.taskSources.empty': 'No task sources configured yet.',
  'settings.taskSources.proactive': 'Proactive',
  'settings.taskSources.lastFetch': 'Last fetch',
  'settings.taskSources.never': 'Never',
  'settings.taskSources.statusEnabled': 'Enabled',
  'settings.taskSources.statusDisabled': 'Disabled',
  'settings.taskSources.enable': 'Enable',
  'settings.taskSources.disable': 'Disable',
  'settings.taskSources.remove': 'Remove',
  'settings.taskSources.removeConfirm':
    'Remove this task source? All ingested task history will be deleted and cannot be undone.',
  'settings.taskSources.refresh': 'Refresh',
  // Task sources provider labels (#task-sources)
  'settings.taskSources.providers.github': 'GitHub',
  'settings.taskSources.providers.notion': 'Notion',
  'settings.taskSources.providers.linear': 'Linear',
  'settings.taskSources.providers.clickup': 'ClickUp',

  // Scheduled-workflow card controls (ScheduledCronCard on the workflow
  // runner page). The standalone scheduled-workflows dashboard was phased
  // out; only these per-card labels remain in use.
  'skills.dashboard.enable': 'Enable scheduled workflow',
  'skills.dashboard.disable': 'Disable scheduled workflow',
  'skills.dashboard.lastRun': 'Last run',
  'skills.dashboard.nextRun': 'Next run',
  'skills.dashboard.cardOpenRunner': 'Open in runner',
  'skills.new.title': 'Create a workflow',
  'settings.agents.title': 'Agents',
  'settings.agents.subtitle':
    'Manage the agents available for delegation — built-in defaults and your own custom agents.',
  'settings.agents.menuDesc': 'Manage built-in and custom agents',
  'settings.agents.newAgent': 'New agent',
  'settings.agents.loadError': "Couldn't load agents",
  'settings.agents.empty': 'No agents yet',
  'settings.agents.sourceDefault': 'Built-in',
  'settings.agents.sourceCustom': 'Custom',
  'settings.agents.enable': 'Enable agent',
  'settings.agents.disable': 'Disable agent',
  'settings.agents.edit': 'Edit',
  'settings.agents.delete': 'Delete',
  'settings.agents.reset': 'Reset to default',
  'settings.agents.modelLabel': 'Model',
  'settings.agents.toolsLabel': 'Tools',
  'settings.agents.toolsAll': 'All tools',
  'settings.agents.toolsCount': '{count} tools',
  'settings.agents.actionFailed': "Couldn't update the agent",
  'settings.agents.orchestratorLocked': 'The orchestrator is always enabled.',
  'settings.agents.editor.createTitle': 'New agent',
  'settings.agents.editor.editTitle': 'Edit agent',
  'settings.agents.editor.id': 'ID',
  'settings.agents.editor.idHint': 'Lowercase letters, numbers, _ and - only.',
  'settings.agents.editor.name': 'Name',
  'settings.agents.editor.description': 'Description',
  'settings.agents.editor.model': 'Model (optional)',
  'settings.agents.editor.modelPlaceholder': 'e.g. inherit, hint:fast, or a model id',
  'settings.agents.editor.systemPrompt': 'System prompt (optional)',
  'settings.agents.editor.tools': 'Allowed tools',
  'settings.agents.editor.toolsHint': 'One tool name per line. Use * for all tools.',
  'settings.agents.editor.defaultsNote':
    'Editing a built-in agent saves an override you can reset later.',
  'settings.agents.editor.save': 'Save',
  'settings.agents.editor.create': 'Create agent',
  'settings.agents.editor.saving': 'Saving…',

  // ── Agent Profiles ───────────────────────────────────────────────────────
  'settings.profiles.title': 'Agent Profiles',
  'settings.profiles.subtitle':
    'Flavoured agents — each with its own soul, memory, connectors, and skills.',
  'settings.profiles.menuDesc': 'Create and manage agent profiles',
  'settings.profiles.new': 'New profile',
  'settings.profiles.empty': 'No agent profiles yet',
  'settings.profiles.loadError': "Couldn't load profiles",
  'settings.profiles.active': 'Active',
  'settings.profiles.setActive': 'Set as active',
  'settings.profiles.sourceBuiltIn': 'Built-in',
  'settings.profiles.sourceCustom': 'Custom',
  'settings.profiles.deleteConfirm': 'Delete this profile? This cannot be undone.',
  'settings.profiles.editor.createTitle': 'New profile',
  'settings.profiles.editor.editTitle': 'Edit profile',
  'settings.profiles.editor.name': 'Name',
  'settings.profiles.editor.id': 'ID',
  'settings.profiles.editor.idHint': 'Lowercase letters, numbers, and dashes.',
  'settings.profiles.editor.description': 'Description',
  'settings.profiles.editor.soul': 'Soul (SOUL.md)',
  'settings.profiles.editor.soulHint':
    'Custom identity for this profile. Empty falls back to the workspace SOUL.md.',
  'settings.profiles.editor.baseAgent': 'Base agent',
  'settings.profiles.editor.baseAgentHint':
    'Which agent definition this profile runs as (e.g. orchestrator).',
  'settings.profiles.editor.model': 'Model',
  'settings.profiles.editor.modelHint': 'Optional model override. Empty inherits the default.',
  'settings.profiles.editor.temperature': 'Temperature',
  'settings.profiles.editor.systemPromptSuffix': 'System prompt suffix',
  'settings.profiles.editor.agentConversations': 'Recall agent conversations',
  'settings.profiles.editor.agentConversationsHint':
    'Include prior-chat and cross-chat memory in this profile’s context.',
  'settings.profiles.editor.memorySources': 'Memory sources',
  'settings.profiles.editor.memorySourcesHint': 'Memory sources this profile recalls from.',
  'settings.profiles.editor.connectors': 'Connectors',
  'settings.profiles.editor.connectorsHint': 'Composio toolkits this profile can use.',
  'settings.profiles.editor.skills': 'Skills',
  'settings.profiles.editor.skillsHint': 'Workflows this profile can list and run.',
  'settings.profiles.editor.mcpServers': 'MCP servers',
  'settings.profiles.editor.mcpServersHint': 'MCP servers this profile can reach.',
  'settings.profiles.editor.all': 'All',
  'settings.profiles.editor.selected': 'Selected',
  'settings.profiles.editor.addPlaceholder': 'Type an id, press Enter',
  'settings.profiles.editor.removeAria': 'Remove {item}',
  'settings.profiles.editor.notFound': 'Profile not found',
  'settings.profiles.editor.idRequired': 'Profile id cannot be empty',
  'settings.profiles.editor.saving': 'Saving…',

  // ── Agent Workflows ──────────────────────────────────────────────────────
  'nav.workflows': 'Workflows',
  'workflows.title': 'Workflows',
  'workflows.subtitle':
    'Reusable, runnable procedures — a goal plus the steps to reach it. Create one, install from a URL, or open a workflow to run it.',
  'workflows.createNew': 'New workflow',
  'workflows.installFromUrl': 'Install from URL',
  'workflows.listHeading': 'Workflows',
  'workflows.delete': 'Delete Workflow',
  'workflows.deleteError': 'Failed to delete workflow',
  'workflows.warnings': '{count} warning(s)',
  'workflows.empty.title': 'No workflows yet',
  'workflows.empty.body':
    'Create a workflow to define rules and scripts for task lifecycle phases.',
  'workflows.create.title': 'New Workflow',
  'workflows.create.subtitle': 'Define a lifecycle-bound rule set for the agent.',
  'workflows.create.name': 'Name',
  'workflows.create.namePlaceholder': 'e.g. Python project workflow',
  'workflows.create.description': 'Description',
  'workflows.create.descriptionPlaceholder': 'What does this workflow do?',
  'workflows.create.whenToUse': 'When to use',
  'workflows.create.whenToUsePlaceholder': 'When should the agent pick up this workflow?',
  'workflows.create.optional': '(optional)',
  'workflows.create.createBtn': 'Create workflow',
  'workflows.create.creating': 'Creating…',
  'workflows.create.createError': 'Could not create workflow',
  'workflows.create.successTitle': 'Workflow created',
  'workflows.create.successMessage': 'was created successfully.',
  'workflows.deleteConfirm.title': 'Delete workflow',
  'workflows.deleteConfirm.body': 'Remove "{name}"? This cannot be undone.',
  'workflows.detail.tags': 'Tags',
  'workflows.detail.location': 'Location',
  'workflows.detail.warnings': 'Warnings',
  'workflows.detail.phases': 'Phases',
  'workflows.detail.noPhases': 'No phases defined.',
  'workflows.detail.loadError': 'Failed to load full workflow',
  'workflows.phase.rules': 'Rules',
  'workflows.phase.rules.empty': 'No rules.',
  'workflows.phase.scripts': 'Scripts',
  'workflows.phase.scripts.empty': 'No scripts.',
  'workflows.phase.toolScope': 'Tool scope',
  'workflows.phase.toolScope.allow': 'Allow',
  'workflows.phase.toolScope.deny': 'Deny',
  'workflows.phase.toolScope.inherited': 'Inherited from workflow default.',
  'workflows.phase.toolScope.empty': 'No tool restrictions.',
  'workflows.phase.context': 'Context',
  'workflows.phase.context.empty': 'No context providers.',
  'settings.agentsSection.title': 'Agents',
  'settings.agentsSection.description':
    'Manage your agents, their autonomy, and what they can access on this computer.',
  'settings.agentsSection.menuDesc': 'Registry, autonomy & OS access',
  'settings.cryptoSection.title': 'Crypto',
  'settings.cryptoSection.description':
    'Manage your recovery phrase and view balances across your wallet accounts.',
  'settings.cryptoSection.menuDesc': 'Recovery phrase & wallet balances',
  'settings.notificationsHub.title': 'Notifications',
  'settings.notificationsHub.description':
    'View your alerts inbox and manage notification preferences and routing.',
  'settings.notificationsHub.menuDesc': 'Alerts inbox & notification preferences',
  'settings.notificationsHub.settingsItem': 'Notification settings',
  'settings.notificationsHub.settingsItemDesc': 'Preferences & routing',
  'settings.agents.editor.notFound': 'Agent not found.',
  'settings.agents.editor.modelInherit': 'Inherit (platform default)',
  'settings.agents.editor.modelHints': 'Route hints',
  'settings.agents.editor.modelTiers': 'Model tiers',
  'settings.agents.editor.modelCustom': 'Custom model id…',
  'settings.agents.editor.modelCustomPlaceholder': 'e.g. anthropic/claude-sonnet-4',
  'settings.agents.editor.selectTools': 'Add tools',
  'settings.agents.editor.toolsAllSelected': 'All tools',
  'settings.agents.editor.toolsNoneSelected': 'No tools selected',
  'settings.agents.editor.removeToolAria': 'Remove {tool}',
  'settings.agents.editor.toolsModalTitle': 'Allowed tools',
  'settings.agents.editor.toolsSelectedCount': '{count} selected',
  'settings.agents.editor.toolsSearchPlaceholder': 'Search tools…',
  'settings.agents.editor.toolsAllowAll': 'Allow all tools (*)',
  'settings.agents.editor.toolsAllowAllHint': 'This agent can use every available tool.',
  'settings.agents.editor.toolsLoading': 'Loading tools…',
  'settings.agents.editor.toolsLoadError': "Couldn't load tools",
  'settings.agents.editor.toolsEmpty': 'No tools match your search.',
  'settings.agents.editor.toolsDone': 'Done',
  'settings.agents.editor.builtInReadonly':
    "Built-in agents can't be edited. You can enable, disable, or reset them from the agents list.",

  // Chat — agent-generated artifacts (#2779)
  'chat.artifact.aria': 'Artifact: {title}',
  'chat.artifact.generating': 'Generating {kind}…',
  'chat.artifact.ready': 'Ready',
  'chat.artifact.failed': 'Generation failed',
  'chat.artifact.download': 'Download',
  'chat.artifact.downloading': 'Downloading…',
  'chat.artifact.downloaded': 'Saved to {path}',
  'chat.artifact.download_failed': 'Download failed: {reason}',
  'chat.artifact.retry': 'Retry',
  'chat.artifact.reveal': 'Show in folder',
  'chat.artifact.show_more': 'Show more',
  'chat.artifact.show_less': 'Show less',

  // Chat — files panel (#3024)
  'chat.files.chip.aria.one': '{count} file in this chat',
  'chat.files.chip.aria.other': '{count} files in this chat',
  'chat.files.panel.aria': 'Files in this chat',
  'chat.files.panel.title': 'Files ({count})',
  'chat.files.panel.empty': 'No files yet. Ask the agent to generate one.',
  'chat.files.panel.close': 'Close files panel',
  'chat.files.delete.aria': 'Delete {title}',
  'chat.files.delete.confirm': 'Delete this file?',
  'chat.files.delete.cancel': 'Cancel',
  'chat.files.delete.action': 'Delete',
  'chat.files.delete.failed': 'Couldn’t delete the file. Try again.',
  // Error labels for download/delete outcomes (#3024). Keyed off
  // `ArtifactErrorCode` returned by artifactDownloadService.
  'chat.files.error.not_desktop': 'Downloads are only available in the desktop app.',
  'chat.files.error.missing_artifact_id': 'Missing artifact id.',
  'chat.files.error.missing_artifact_path': 'The artifact path is missing from the core response.',
  'chat.files.error.resolve_failed': 'Couldn’t resolve the artifact. Please try again.',
  'chat.files.error.download_failed': 'Download failed. Please try again.',
  'chat.files.error.delete_failed': 'Couldn’t delete the file. Please try again.',

  // First-run initialization (harness_init)
  'harnessInit.title': 'Setting things up',
  'announcement.gotIt': 'Got it',
  'harnessInit.subtitle': 'OpenHuman is preparing components it needs on first launch.',
  'harnessInit.stepPython': 'Python runtime',
  'harnessInit.stepSpacy': 'Language model',
  'harnessInit.stepNode': 'Node.js runtime',
  'harnessInit.statePending': 'Waiting',
  'harnessInit.stateRunning': 'Installing…',
  'harnessInit.stateDone': 'Ready',
  'harnessInit.stateSkipped': 'Skipped',
  'harnessInit.stateFailed': 'Failed',
  'harnessInit.failedMessage':
    'Some setup steps did not finish. You can retry, or continue — OpenHuman will use a built-in fallback.',
  'harnessInit.retry': 'Retry',
  'harnessInit.continueAnyway': 'Continue anyway',
  'harnessInit.runInBackground': 'Run in background',
  'harnessInit.backgroundHint': 'You can keep using OpenHuman while this finishes.',

  // Keyring consent & security
  'keyring.consent.title': 'Secure Storage Unavailable',
  'keyring.consent.description':
    'Your operating system keychain is not accessible. OpenHuman needs your permission to store secrets using local encrypted storage instead.',
  'keyring.consent.reasonPrefix': 'Reason:',
  'keyring.consent.showDetails': 'What does this mean?',
  'keyring.consent.hideDetails': 'Hide details',
  'keyring.consent.tradeoffTitle': 'Security tradeoff',
  'keyring.consent.tradeoffBody':
    'With local encrypted storage, your secrets are encrypted on disk using a master key stored alongside the data. This is less secure than the OS keychain, which uses hardware-backed protection. Backups or file syncing may include the encrypted data.',
  'keyring.consent.consentButton': 'Use Local Encrypted Storage',
  'keyring.consent.retryButton': 'Retry OS Keychain',
  'keyring.consent.declineButton': 'Skip',
  'keyring.consent.retrying': 'Retrying…',
  'keyring.consent.error': 'Failed to save preference. Please try again.',
  'keyring.consent.retryFailed': 'Keychain is still unavailable.',
  'keyring.settings.title': 'Security',
  'keyring.settings.storageMode': 'Secret storage mode',
  'keyring.settings.mode.osKeychain': 'OS Keychain',
  'keyring.settings.mode.encryptedFile': 'Local Encrypted',
  'keyring.settings.mode.consentPending': 'Not configured',
  'keyring.settings.mode.declined': 'Declined',
  'keyring.settings.availability': 'Keychain availability',
  'keyring.settings.available': 'OS keychain is available',
  'keyring.settings.unavailable': 'OS keychain is unavailable',
  'keyring.settings.backend': 'Backend',
  'keyring.settings.retryButton': 'Retry keychain detection',
  'keyring.settings.retryFailed': 'Retry failed. Keychain is still unavailable.',
  'keyring.settings.consentTitle': 'Storage consent',
  'keyring.settings.consentDescription':
    'Choose how secrets are stored when the OS keychain is not available.',
  'keyring.settings.grantConsent': 'Allow local encrypted storage',
  'keyring.settings.revokeConsent': 'Decline local storage',
  'pages.settings.account.security': 'Security',
  'pages.settings.account.securityDesc': 'Secret storage mode and keychain status',

  // Chat — agent-generated artifacts (#2779)
  // Chat composer toolbar
  'composer.attachFile': 'Attach file',
  'composer.modelSelector': 'Model',
  'composer.voiceMode': 'Voice mode',
  'composer.qualityHigh': 'High',
  // Sync budget dialog
  'syncBudget.title': 'Sync budget',
  'syncBudget.maxTokens': 'Max tokens per sync',
  'syncBudget.maxTokensHelp': 'Stop syncing once this many tokens are consumed.',
  'syncBudget.maxCost': 'Max cost per sync (USD)',
  'syncBudget.maxCostHelp': 'Hard dollar cap per sync run.',
  'syncBudget.syncDepth': 'Sync depth',
  'syncBudget.syncDepthHelp': 'Only fetch items from this time window.',
  'syncBudget.days7': 'Last 7 days',
  'syncBudget.days30': 'Last 30 days',
  'syncBudget.days90': 'Last 90 days',
  'syncBudget.allTime': 'All time',
  'syncBudget.unlimited': 'Unlimited',
  'syncBudget.saved': 'Budget saved.',

  // Sync confirm dialog
  'syncConfirm.title': 'Confirm sync',
  'syncConfirm.message': 'This sync will process ~{items} items (~{tokens} tokens, est. ${cost}).',
  'syncConfirm.budgetNote': 'Budget cap: ${max}',
  'syncConfirm.proceed': 'Proceed',
  'syncConfirm.cancel': 'Cancel',
  'syncConfirm.estimating': 'Estimating cost...',

  // Monthly cost badge
  'monthlyCost.badge': '${amount} this month',
  'monthlyCost.noData': 'No syncs this month',

  // Security banner (approval-gate host-aware boot state)
  'security.approvalGateDisabled.title': 'Approval gate disabled',
  'security.approvalGateDisabled.body':
    'OPENHUMAN_APPROVAL_GATE=0 is set in your environment. External-effect tools will run without asking for confirmation.',
  'security.approvalGateOverrideIgnored.title': 'Override blocked',
  'security.approvalGateOverrideIgnored.body':
    'An OPENHUMAN_APPROVAL_GATE=0 override was detected but ignored: the desktop app always keeps the approval gate on.',

  // Run queue
  'runQueue.mode.interrupt': 'Interrupt',
  'runQueue.mode.steer': 'Steer',
  'runQueue.mode.followup': 'Follow-up',
  'runQueue.mode.collect': 'Add context',
  'runQueue.queued': 'Message queued',
  'runQueue.steerHint': 'Steer the current turn',
  'runQueue.followupHint': 'Queue as follow-up',
  'runQueue.collectHint': 'Add as extra context',
  'runQueue.status': '{total} queued',
  'runQueue.cleared': 'Queue cleared',
  'notch.ready': 'Ready',
  'notch.processing': 'Processing…',
  'notch.listening': 'Listening…',
  'notch.thinking': 'Thinking…',
  'notch.speaking': 'Speaking…',
  'notch.transcribing': 'Transcribing…',
  'notch.executing': 'Executing…',

  // ── Agent World: Jobs apply modal ─────────────────────────────────────────
  'agentworld.jobs.applyModal.title': 'Apply for Job',
  'agentworld.jobs.applyModal.successHeading': 'Proposal submitted successfully!',
  'agentworld.jobs.applyModal.successBody': 'The job poster will review your application.',
  'agentworld.jobs.applyModal.coverLetterLabel': 'Cover Letter',
  'agentworld.jobs.applyModal.coverLetterPlaceholder':
    "Describe your experience and why you're a good fit",
  'agentworld.jobs.applyModal.bidAmountLabel': 'Bid Amount',
  'agentworld.jobs.applyModal.bidAmountPlaceholder': 'e.g. 450 USDC',
  'agentworld.jobs.applyModal.deliveryLabel': 'Estimated Delivery',
  'agentworld.jobs.applyModal.deliveryPlaceholder': 'e.g. 2 weeks',
  'agentworld.jobs.applyModal.cancel': 'Cancel',
  'agentworld.jobs.applyModal.submit': 'Submit Application',
  'agentworld.jobs.applyModal.submitting': 'Applying…',
  'agentworld.messaging.missingSignalBundle':
    "This user hasn't enabled encrypted messaging yet. Ask them to open Agent World and enable secure DMs before sending a message.",

  // Code block chrome
  'codeBlock.copy': 'Copy',
  'codeBlock.copied': 'Copied!',

  // User-actionable runtime errors (#3931)
  'userErrors.title': 'Action needed',
  'userErrors.dismiss': 'Dismiss',
  'userErrors.action.openBilling': 'Open billing',
  'userErrors.action.openProviderSettings': 'Provider settings',
  'userErrors.budgetExceeded.title': 'Managed budget reached',
  'userErrors.budgetExceeded.body':
    'Your managed AI budget is used up. Add budget or change your plan to continue.',
  'userErrors.insufficientCredits.title': 'Provider credits required',
  'userErrors.insufficientCredits.body':
    'Your AI provider is out of credits. Top it up or update its API key to continue.',
  'userErrors.apiKeyMissing.title': 'API key required',
  'userErrors.apiKeyMissing.body':
    'Your AI provider has no API key set. Add one in provider settings to continue.',
  'userErrors.scope.chat': 'Chat',
  'userErrors.scope.cron': 'Scheduled job',
};

export default en;
