import { FIELD_DESCRIPTIONS, FIELD_LABELS } from '@/app/settings/constants'

import type { Translations } from './types'

export const en: Translations = {
  common: {
    apply: 'Apply',
    back: 'Back',
    save: 'Save',
    saving: 'Saving…',
    cancel: 'Cancel',
    change: 'Change',
    choose: 'Choose',
    clear: 'Clear',
    close: 'Close',
    collapse: 'Collapse',
    confirm: 'Confirm',
    connect: 'Connect',
    connecting: 'Connecting',
    continue: 'Continue',
    copied: 'Copied',
    copy: 'Copy',
    copyFailed: 'Copy failed',
    delete: 'Delete',
    docs: 'Docs',
    done: 'Done',
    error: 'Error',
    failed: 'Failed',
    free: 'Free',
    loading: 'Loading…',
    notSet: 'Not set',
    refresh: 'Refresh',
    remove: 'Remove',
    replace: 'Replace',
    retry: 'Retry',
    run: 'Run',
    send: 'Send',
    set: 'Set',
    skip: 'Skip',
    update: 'Update',
    on: 'On',
    off: 'Off'
  },

  boot: {
    ready: 'Hermes Desktop is ready',
    desktopBootFailedWithMessage: message => `Desktop boot failed: ${message}`,
    steps: {
      connectingGateway: 'Connecting live desktop gateway',
      loadingSettings: 'Loading Hermes settings',
      loadingSessions: 'Loading recent sessions',
      startingDesktopConnection: 'Starting desktop connection',
      startingHermesDesktop: 'Starting Hermes Desktop…'
    },
    errors: {
      backgroundExited: 'Hermes background process exited.',
      backgroundExitedDuringStartup: 'Hermes background process exited during startup.',
      backendStopped: 'Backend stopped',
      desktopBootFailed: 'Desktop boot failed',
      gatewayConnectionLost: 'Lost connection to the gateway',
      gatewaySignInRequired: 'Gateway sign-in required',
      ipcBridgeUnavailable: 'Desktop IPC bridge is unavailable.'
    },
    failure: {
      title: "Hermes couldn't start",
      description:
        "The background gateway didn't come up. Try one of the recovery steps below. Nothing here deletes your chats or settings.",
      remoteTitle: 'Remote gateway sign-in required',
      remoteDescription:
        'Your remote gateway session has expired. Sign in again to reconnect. Nothing here deletes your chats or settings.',
      retry: 'Retry',
      repairInstall: 'Repair install',
      useLocalGateway: 'Use local gateway',
      openLogs: 'Open logs',
      repairHint: 'Repair re-runs the installer and can take a few minutes on a fresh machine.',
      remoteSignInHint: 'Opens the gateway login window. Use local gateway to switch to the bundled backend instead.',
      hideRecentLogs: 'Hide recent logs',
      showRecentLogs: 'Show recent logs',
      signedInTitle: 'Signed in',
      signedInMessage: 'Reconnecting to the remote gateway…',
      signInIncompleteTitle: 'Sign-in incomplete',
      signInIncompleteMessage: 'The login window closed before authentication finished.',
      signInFailed: 'Sign-in failed',
      signInToRemoteGateway: 'Sign in to remote gateway',
      signInWithProvider: provider => `Sign in with ${provider}`,
      identityProvider: 'your identity provider'
    }
  },

  notifications: {
    region: 'Notifications',
    hide: 'Hide',
    show: 'Show',
    more: count => `${count} more ${count === 1 ? 'notification' : 'notifications'}`,
    clearAll: 'Clear all',
    dismiss: 'Dismiss notification',
    details: 'Details',
    copyDetail: 'Copy detail',
    copyDetailFailed: 'Could not copy notification detail',
    backendOutOfDateTitle: 'Backend out of date',
    backendOutOfDateMessage:
      'Your Hermes backend is older than this desktop build and may not work correctly. Update to align them.',
    updateHermes: 'Update Hermes',
    updateReadyTitle: 'Update ready',
    updateReadyMessage: count => `${count} new change${count === 1 ? '' : 's'} available.`,
    seeWhatsNew: "See what's new",
    errors: {
      elevenLabsNeedsKey: 'ElevenLabs STT needs ELEVENLABS_API_KEY.',
      elevenLabsRejectedKey: 'ElevenLabs rejected the API key (401).',
      methodNotAllowed:
        'The desktop backend rejected that request (405 Method Not Allowed). Try restarting Hermes Desktop.',
      microphonePermission: 'Microphone permission was denied.',
      openaiRejectedApiKey: 'OpenAI rejected the API key.',
      openaiRejectedApiKeyWithStatus: status => `OpenAI rejected the API key (${status} invalid_api_key).`,
      openaiTtsNeedsKey: 'OpenAI TTS needs VOICE_TOOLS_OPENAI_KEY or OPENAI_API_KEY.'
    },
    voice: {
      configureSpeechToText: 'Configure speech-to-text to use voice mode.',
      couldNotStartSession: 'Could not start voice session',
      microphoneAccessDenied: 'Microphone access denied.',
      microphoneConstraintsUnsupported: 'Microphone constraints are not supported by this device.',
      microphoneFailed: 'Microphone failed',
      microphoneInUse: 'Microphone is already in use by another app.',
      microphonePermissionDenied: 'Microphone permission was denied.',
      microphoneStartFailed: 'Could not start microphone recording.',
      microphoneUnsupported: 'This runtime does not support microphone recording.',
      noMicrophone: 'No microphone was found.',
      noSpeechDetected: 'No speech detected',
      playbackFailed: 'Voice playback failed',
      recordingFailed: 'Voice recording failed',
      transcriptionFailed: 'Voice transcription failed',
      transcriptionUnavailable: 'Voice transcription is not available yet.',
      tryRecordingAgain: 'Try recording again.',
      unavailable: 'Voice unavailable'
    },
    native: {
      approvalTitle: 'Approval needed',
      approveAction: 'Approve',
      rejectAction: 'Reject',
      inputTitle: 'Input needed',
      inputBody: 'Hermes is waiting for your response.',
      turnDoneTitle: 'Hermes finished',
      turnDoneBody: 'The response is ready.',
      turnErrorTitle: 'Turn failed',
      backgroundDoneTitle: 'Background task finished',
      backgroundFailedTitle: 'Background task failed'
    }
  },

  remoteDisplayBanner: {
    message: reason =>
      `Software rendering active — remote display detected (${reason}). GPU acceleration is disabled to prevent flickering.`,
    dismiss: 'Dismiss'
  },

  titlebar: {
    hideSidebar: 'Hide sidebar',
    showSidebar: 'Show sidebar',
    search: 'Search',
    searchTitle: 'Search sessions, views, and actions',
    swapSidebarSides: 'Swap sidebar sides',
    swapSidebarSidesTitle: 'Swap the sessions and file browser sides',
    hideRightSidebar: 'Hide right sidebar',
    showRightSidebar: 'Show right sidebar',
    muteHaptics: 'Mute haptics',
    unmuteHaptics: 'Unmute haptics',
    openSettings: 'Open settings',
    openKeybinds: 'Keyboard shortcuts'
  },

  keybinds: {
    title: 'Keyboard shortcuts',
    subtitle: open => `Click a shortcut to rebind it · ${open} reopens this panel.`,
    rebind: 'Rebind',
    reset: 'Reset to default',
    resetAll: 'Reset all',
    pressKey: 'Press a key…',
    set: 'set',
    conflictWith: label => `Also bound to “${label}”`,
    categories: {
      composer: 'Composer',
      profiles: 'Profiles',
      session: 'Session',
      navigation: 'Navigation',
      view: 'View'
    },
    actions: {
      'keybinds.openPanel': 'Open keyboard shortcuts',
      'nav.commandPalette': 'Open command palette',
      'nav.commandCenter': 'Open command center',
      'nav.settings': 'Open settings',
      'nav.profiles': 'Open profiles',
      'nav.skills': 'Open skills',
      'nav.messaging': 'Open messaging',
      'nav.artifacts': 'Open artifacts',
      'nav.cron': 'Open scheduled jobs',
      'nav.agents': 'Open agents',
      'session.new': 'New session',
      'session.newWindow': 'New session in window',
      'session.next': 'Next session',
      'session.prev': 'Previous session',
      'session.slot.1': 'Switch to recent session 1',
      'session.slot.2': 'Switch to recent session 2',
      'session.slot.3': 'Switch to recent session 3',
      'session.slot.4': 'Switch to recent session 4',
      'session.slot.5': 'Switch to recent session 5',
      'session.slot.6': 'Switch to recent session 6',
      'session.slot.7': 'Switch to recent session 7',
      'session.slot.8': 'Switch to recent session 8',
      'session.slot.9': 'Switch to recent session 9',
      'session.focusSearch': 'Search sessions',
      'session.togglePin': 'Pin / unpin current session',
      'composer.focus': 'Focus composer',
      'composer.modelPicker': 'Open model picker',
      'composer.voice': 'Start / stop voice conversation',
      'view.toggleSidebar': 'Toggle sessions sidebar',
      'view.toggleRightSidebar': 'Toggle file browser',
      'view.showFiles': 'Show file browser',
      'view.showTerminal': 'Show terminal',
      'view.terminalSelection': 'Send terminal selection to composer',
      'view.closePreviewTab': 'Close preview tab',
      'view.flipPanes': 'Swap sidebar sides',
      'appearance.toggleMode': 'Toggle light / dark',
      'profile.default': 'Switch to default profile',
      'profile.switch.1': 'Switch to profile 1',
      'profile.switch.2': 'Switch to profile 2',
      'profile.switch.3': 'Switch to profile 3',
      'profile.switch.4': 'Switch to profile 4',
      'profile.switch.5': 'Switch to profile 5',
      'profile.switch.6': 'Switch to profile 6',
      'profile.switch.7': 'Switch to profile 7',
      'profile.switch.8': 'Switch to profile 8',
      'profile.switch.9': 'Switch to profile 9',
      'profile.switch.10': 'Switch to profile 10',
      'profile.switch.11': 'Switch to profile 11',
      'profile.switch.12': 'Switch to profile 12',
      'profile.switch.13': 'Switch to profile 13',
      'profile.switch.14': 'Switch to profile 14',
      'profile.switch.15': 'Switch to profile 15',
      'profile.switch.16': 'Switch to profile 16',
      'profile.switch.17': 'Switch to profile 17',
      'profile.switch.18': 'Switch to profile 18',
      'profile.next': 'Next profile',
      'profile.prev': 'Previous profile',
      'profile.toggleAll': 'Toggle all-profiles view',
      'profile.create': 'Create profile',
      'composer.send': 'Send message',
      'composer.newline': 'Insert newline',
      'composer.steer': 'Steer the running turn',
      'composer.sendQueued': 'Send next queued turn',
      'composer.mention': 'Reference files, folders, URLs',
      'composer.slash': 'Slash command palette',
      'composer.help': 'Quick help',
      'composer.history': 'Cycle popover / history',
      'composer.cancel': 'Close popover · cancel run'
    }
  },

  language: {
    label: 'Language',
    description: 'Choose the language for the desktop interface.',
    saving: 'Saving language…',
    saveError: 'Language update failed',
    switchTo: 'Switch language',
    searchPlaceholder: 'Search languages…',
    noResults: 'No languages found'
  },

  settings: {
    closeSettings: 'Close settings',
    exportConfig: 'Export config',
    importConfig: 'Import config',
    resetToDefaults: 'Reset to defaults',
    resetConfirm: 'Reset all settings to Hermes defaults?',
    exportFailed: 'Export failed',
    resetFailed: 'Reset failed',
    nav: {
      providers: 'Providers',
      providerAccounts: 'Accounts',
      providerApiKeys: 'API keys',
      gateway: 'Gateway',
      apiKeys: 'Tools & Keys',
      keysTools: 'Tools',
      keysSettings: 'Settings',
      mcp: 'MCP',
      archivedChats: 'Archived Chats',
      about: 'About',
      notifications: 'Notifications'
    },
    notifications: {
      title: 'Notifications',
      intro:
        'Native desktop notifications, separate from in-app toasts. These are device-local — each computer keeps its own settings.',
      enableAll: 'Enable notifications',
      enableAllDesc: 'Master switch. Turn this off to silence every notification below.',
      focusedHint: 'Completion alerts only fire while Hermes is in the background.',
      kinds: {
        approval: {
          label: 'Approval needed',
          description: 'A command is waiting for you to approve or reject it.'
        },
        input: {
          label: 'Input needed',
          description: 'Hermes asked a question or needs a password or secret.'
        },
        turnDone: {
          label: 'Response ready',
          description: 'A turn finished while Hermes was in the background.'
        },
        turnError: {
          label: 'Turn failed',
          description: 'A turn ended with an error.'
        },
        backgroundDone: {
          label: 'Background task finished',
          description: 'A backgrounded terminal command completed.'
        }
      },
      test: 'Send test notification',
      testTitle: 'Hermes',
      testBody: 'Notifications are working.',
      testSent: 'Test sent. If nothing appears, check your OS notification permissions and Focus/Do Not Disturb.',
      testUnsupported: 'This system does not support native notifications.',
      completionSoundTitle: 'Completion Sound',
      completionSoundDesc: 'Plays when an agent turn finishes. Pick a preset and preview it here.',
      completionSoundPreview: 'Preview'
    },
    sections: {
      model: 'Model',
      chat: 'Chat',
      appearance: 'Appearance',
      workspace: 'Workspace',
      safety: 'Safety',
      memory: 'Memory & Context',
      voice: 'Voice',
      advanced: 'Advanced'
    },
    searchPlaceholder: {
      about: 'About Hermes Desktop',
      config: 'Search settings...',
      gateway: 'Gateway connection...',
      keys: 'Search API keys...',
      mcp: 'Search MCP servers...',
      sessions: 'Search archived sessions...'
    },
    modeOptions: {
      light: { label: 'Light', description: 'Bright desktop surfaces' },
      dark: { label: 'Dark', description: 'Low-glare workspace' },
      system: { label: 'System', description: 'Follow OS appearance' }
    },
    appearance: {
      title: 'Appearance',
      intro:
        'These are desktop-only display preferences. Mode controls brightness; theme controls the accent palette and chat surface styling.',
      colorMode: 'Color Mode',
      colorModeDesc: 'Pick a fixed mode or let Hermes follow your system setting.',
      toolViewTitle: 'Tool Call Display',
      toolViewDesc: 'Product hides raw tool payloads; Technical shows full input/output.',
      translucencyTitle: 'Window Translucency',
      translucencyDesc: 'See your desktop through the whole window. macOS and Windows only.',
      product: 'Product',
      productDesc: 'Human-friendly tool activity with concise summaries.',
      technical: 'Technical',
      technicalDesc: 'Include raw tool args/results and low-level details.',
      themeTitle: 'Theme',
      themeDesc: 'Desktop palettes only. The selected mode is applied on top.',
      themeProfileNote: profile => `Saved for the ${profile} profile — each profile keeps its own theme.`,
      installTitle: 'Install from VS Code',
      installDesc:
        'Paste a Marketplace extension id (e.g. dracula-theme.theme-dracula) to convert its color theme into a desktop palette.',
      installPlaceholder: 'publisher.extension',
      installButton: 'Install',
      installing: 'Installing…',
      installError: 'Could not install that theme.',
      installed: name => `Installed “${name}”.`,
      removeTheme: 'Remove theme',
      importedBadge: 'Imported',
      pet: {
        title: 'Pet',
        intro:
          'Adopt an animated petdex mascot that floats over the app and reacts to what Hermes is doing — running while tools execute, celebrating on success, sulking on errors.',
        restartHint:
          'Pets need a quick restart — the running app started before this feature was added. Quit and reopen Hermes, then come back here.',
        on: 'On',
        off: 'Off',
        scaleTitle: 'Size',
        scaleDesc: 'Resize the floating mascot. Applies everywhere instantly.',
        chooseTitle: 'Choose a pet',
        chooseDesc: 'Picking one installs it (if needed) and makes it active.',
        searchPlaceholder: 'Search pets…',
        unreachable: "Couldn't reach the petdex gallery. Check your connection and reopen this page.",
        noMatch: query => `No pets match "${query}".`,
        installedTag: 'installed',
        generatedTag: 'Generated',
        countCapped: (cap, total) => `Showing ${cap} of ${total} — type to narrow it down.`,
        count: n => `${n} pet${n === 1 ? '' : 's'}.`,
        uninstall: name => `Uninstall ${name}`,
        delete: name => `Delete ${name}`,
        deleteTitle: name => `Delete ${name}?`,
        deleteBody: "This permanently deletes the pet — it can't be reinstalled.",
        deleteConfirm: 'Delete',
        rename: name => `Rename ${name}`,
        renameTitle: 'Rename pet',
        renamePlaceholder: 'Name your pet',
        renameSave: 'Save',
        exportPet: name => `Export ${name}`,
        adoptFailed: slug => `Could not adopt ${slug}`,
        uninstallFailed: slug => `Could not uninstall ${slug}`,
        renameFailed: slug => `Could not rename ${slug}`,
        exportFailed: slug => `Could not export ${slug}`,
        noneAvailable: 'No pets available to turn on right now.',
        turnOnFailed: 'Could not turn the pet on.',
        turnOffFailed: 'Could not turn the pet off.'
      }
    },
    fieldLabels: FIELD_LABELS,
    fieldDescriptions: FIELD_DESCRIPTIONS,
    about: {
      heading: 'Hermes Desktop',
      version: value => `Version ${value}`,
      versionUnavailable: 'Version unavailable',
      updates: 'Updates',
      checkNow: 'Check now',
      checking: 'Checking…',
      seeWhatsNew: "See what's new",
      updateNow: 'Update now',
      releaseNotes: 'Release notes',
      onLatest: "You're on the latest version.",
      installing: 'An update is currently installing.',
      cantUpdate: "This build can't update itself from inside the app.",
      cantReach: "We couldn't reach the update server.",
      tapCheck: 'Tap "Check now" to look for updates.',
      updateReady: count => `A new update is ready (${count} change${count === 1 ? '' : 's'} included).`,
      lastChecked: age => `Last checked ${age}`,
      justNowSuffix: ' · just now',
      automaticUpdates: 'Automatic updates',
      automaticUpdatesDesc:
        'Hermes checks for updates automatically in the background and lets you know when one is ready.',
      branchCommit: (branch, commit) => `Branch ${branch} · Commit ${commit}`,
      never: 'never',
      justNow: 'just now',
      minAgo: count => `${count} min ago`,
      hoursAgo: count => `${count} hours ago`,
      daysAgo: count => `${count} days ago`
    },
    config: {
      none: 'None',
      noneParen: '(none)',
      notSet: 'Not set',
      commaSeparated: 'comma-separated values',
      loading: 'Loading Hermes configuration...',
      emptyTitle: 'Nothing to configure',
      emptyDesc: 'This section has no adjustable settings.',
      failedLoad: 'Settings failed to load',
      autosaveFailed: 'Autosave failed',
      imported: 'Config imported',
      invalidJson: 'Invalid config JSON'
    },
    credentials: {
      pasteKey: 'Paste key',
      pasteLabelKey: label => `Paste ${label} key`,
      optional: 'Optional',
      enterValueFirst: 'Enter a value first.',
      couldNotSave: 'Could not save credential.',
      remove: 'Remove',
      or: 'or',
      escToCancel: 'esc to cancel',
      getKey: 'Get a key',
      saving: 'Saving'
    },
    envActions: {
      actionsFor: label => `Actions for ${label}`,
      credentialActions: 'Credential actions',
      docs: 'Docs',
      hideValue: 'Hide value',
      revealValue: 'Reveal value',
      replace: 'Replace',
      set: 'Set',
      clear: 'Clear'
    },
    gateway: {
      loading: 'Loading gateway settings...',
      unavailableTitle: 'Gateway settings unavailable',
      unavailableDesc: 'The desktop IPC bridge does not expose gateway settings.',
      title: 'Gateway Connection',
      envOverride: 'env override',
      intro:
        'Hermes Desktop starts its own local gateway by default. Use a remote gateway when you want this app to control an already-running Hermes backend on another machine or behind a trusted proxy. Pick a profile below to give it its own remote host.',
      appliesTo: 'Applies to',
      allProfiles: 'All profiles',
      defaultConnection: 'Default connection for every profile that has no override of its own.',
      profileConnection: profile =>
        `Connection used only when “${profile}” is the active profile. Set it to Local to inherit the default.`,
      envOverrideTitle: 'Environment variables are controlling this desktop session.',
      envOverrideDesc:
        'Unset HERMES_DESKTOP_REMOTE_URL and HERMES_DESKTOP_REMOTE_TOKEN to use the saved setting below.',
      localTitle: 'Local gateway',
      localDesc: 'Start a private Hermes backend on localhost. This is the default and works offline.',
      remoteTitle: 'Remote gateway',
      remoteDesc:
        'Connect this desktop shell to a remote Hermes backend. Hosted gateways use OAuth or a username and password; self-hosted ones may use a session token.',
      remoteUrlTitle: 'Remote URL',
      remoteUrlDesc: 'Base URL for the remote dashboard backend. Path prefixes are supported, for example /hermes.',
      probing: 'Checking how this gateway authenticates…',
      probeError: 'Could not reach this gateway yet. Check the URL — the auth method will appear once it responds.',
      signedIn: 'Signed in',
      signIn: 'Sign in',
      signOut: 'Sign out',
      signInWith: provider => `Sign in with ${provider}`,
      authTitle: 'Authentication',
      authSignedInPassword:
        'This gateway uses a username and password. You are signed in; the session refreshes automatically.',
      authSignedInOauth: 'This gateway uses OAuth. You are signed in; the session refreshes automatically.',
      authNeedsPassword: 'This gateway uses a username and password. Sign in to authorize this desktop app.',
      authNeedsOauth: provider => `This gateway uses OAuth. Sign in with ${provider} to authorize this desktop app.`,
      tokenTitle: 'Session token',
      tokenDesc: 'The dashboard session token used for REST and WebSocket access. Leave blank to keep the saved token.',
      existingToken: value => `Existing token ${value}`,
      savedToken: 'saved',
      pasteSessionToken: 'Paste session token',
      testRemote: 'Test remote',
      saveForRestart: 'Save for next restart',
      saveAndReconnect: 'Save and reconnect',
      diagnostics: 'Diagnostics',
      diagnosticsDesc: 'Reveal desktop.log in your file manager — useful when the gateway fails to start.',
      openLogs: 'Open logs',
      incompleteTitle: 'Remote gateway incomplete',
      incompleteSignIn: 'Enter a remote URL and sign in before switching to remote.',
      incompleteToken: 'Enter a remote URL and session token before switching to remote.',
      incompleteSignInTest: 'Enter a remote URL and sign in before testing.',
      incompleteTokenTest: 'Enter a remote URL and session token before testing.',
      enterUrlFirst: 'Enter a remote URL first.',
      restartingTitle: 'Gateway connection restarting',
      savedTitle: 'Gateway settings saved',
      restartingMessage: 'Hermes Desktop will reconnect using the saved settings.',
      savedMessage: 'Saved for the next restart.',
      connectedTo: (baseUrl, version) => `Connected to ${baseUrl}${version ? ` · Hermes ${version}` : ''}`,
      reachableTitle: 'Remote gateway reachable',
      signedOutTitle: 'Signed out',
      signedOutMessage: 'Cleared the remote gateway session.',
      failedLoad: 'Gateway settings failed to load',
      signInFailed: 'Sign-in failed',
      signOutFailed: 'Sign-out failed',
      testFailed: 'Remote gateway test failed',
      applyFailed: 'Could not apply gateway settings',
      saveFailed: 'Could not save gateway settings'
    },
    keys: {
      loading: 'Loading API keys and credentials...',
      failedLoad: 'API keys failed to load',
      empty: 'Nothing configured in this category yet.'
    },
    mcp: {
      loading: 'Loading MCP servers...',
      failedLoad: 'MCP config failed to load',
      nameRequiredTitle: 'Name required',
      nameRequiredMessage: 'Give this MCP server a config key.',
      objectRequired: 'Server config must be a JSON object',
      invalidJson: 'Invalid MCP JSON',
      saveFailed: 'Save failed',
      removeFailed: 'Remove failed',
      gatewayUnavailableTitle: 'Gateway unavailable',
      gatewayUnavailableMessage: 'Reconnect the gateway before reloading MCP.',
      reloadedTitle: 'MCP tools reloaded',
      reloadedMessage: 'New tool schemas apply to fresh turns.',
      reloadFailed: 'MCP reload failed',
      savedTitle: 'MCP server saved',
      savedMessage: name => `${name} applies after MCP reload.`,
      newServer: 'New server',
      reload: 'Reload MCP',
      reloading: 'Reloading...',
      emptyTitle: 'No MCP servers',
      emptyDesc: 'Add a stdio or HTTP server to expose MCP tools.',
      disabled: 'disabled',
      editServer: 'Edit server',
      name: 'Name',
      serverJson: 'Server JSON',
      remove: 'Remove',
      saveServer: 'Save server'
    },
    model: {
      loading: 'Loading model configuration...',
      appliesDesc: 'Applies to new sessions. Use the model picker in the composer to hot-swap the active chat.',
      provider: 'Provider',
      model: 'Model',
      applying: 'Applying...',
      defaultsLabel: 'Defaults',
      reasoning: 'Reasoning',
      reasoningOff: 'Off',
      defaultsFailed: 'Failed to save model defaults',
      auxiliaryTitle: 'Auxiliary models',
      resetAllToMain: 'Reset all to main',
      auxiliaryDesc: 'Helper tasks run on the main model by default. Assign a dedicated model to any task to override.',
      setToMain: 'Set to main',
      change: 'Change',
      autoUseMain: 'auto · use main model',
      providerDefault: '(provider default)',
      tasks: {
        vision: { label: 'Vision', hint: 'Image analysis' },
        web_extract: { label: 'Web extract', hint: 'Page summarization' },
        compression: { label: 'Compression', hint: 'Context compaction' },
        skills_hub: { label: 'Skills hub', hint: 'Skill search' },
        approval: { label: 'Approval', hint: 'Smart auto-approve' },
        mcp: { label: 'MCP', hint: 'MCP tool routing' },
        title_generation: { label: 'Title gen', hint: 'Session titles' },
        curator: { label: 'Curator', hint: 'Skill-usage review' }
      }
    },
    providers: {
      connectAccount: 'Connect an account',
      haveApiKey: 'Have an API key instead?',
      intro:
        'Sign in with a subscription — no API key to copy. Hermes runs the browser sign-in for you, right here in the app.',
      connected: 'Connected',
      collapse: 'Collapse',
      connectAnother: 'Connect another provider',
      otherProviders: 'Other providers',
      disconnect: 'Disconnect',
      disconnectInTerminal: 'Disconnect (runs the removal command in the terminal)',
      removeConfirm: provider => `Remove ${provider}?`,
      removeExternalGeneric: provider => `${provider} is managed by its own CLI — remove it there.`,
      removeKeyManaged: provider => `${provider} is configured from an API key. Remove it from API Keys.`,
      removeTerminalConfirm: (provider, command) =>
        `Disconnect ${provider}? This runs "${command}" in the terminal to clear the credential.`,
      removeTerminalRunning: provider => `Running ${provider} disconnect in the terminal…`,
      removedTitle: 'Account removed',
      removedMessage: provider => `${provider} was removed.`,
      failedRemove: provider => `Could not remove ${provider}`,
      noProviderKeys: 'No provider API keys available.',
      searchKeys: 'Search providers…',
      noKeysMatch: 'No providers match your search.',
      loading: 'Loading providers...'
    },
    sessions: {
      loading: 'Loading archived sessions…',
      archivedTitle: 'Archived sessions',
      archivedIntro:
        'Archived chats are hidden from the sidebar but keep all their messages. Ctrl/⌘-click a chat in the sidebar to archive it.',
      emptyArchivedTitle: 'Nothing archived',
      emptyArchivedDesc: 'Archive a chat to hide it here.',
      unarchive: 'Unarchive',
      deletePermanently: 'Delete permanently',
      messages: count => `${count} ${count === 1 ? 'message' : 'messages'}`,
      restored: 'Restored',
      deleteConfirm: title => `Permanently delete "${title}"? This cannot be undone.`,
      defaultDirTitle: 'Default project directory',
      defaultDirDesc:
        'New sessions start in this folder unless you pick another. Leave it unset to use your home directory.',
      defaultDirUpdated: 'Default project directory updated — start a new chat (Ctrl/⌘+N) for it to take effect',
      defaultsTo: label => `Defaults to ${label}.`,
      change: 'Change',
      choose: 'Choose',
      clear: 'Clear',
      notSet: 'Not set',
      failedLoad: 'Could not load archived sessions',
      unarchiveFailed: 'Unarchive failed',
      deleteFailed: 'Delete failed',
      updateDirFailed: 'Could not update default directory',
      clearDirFailed: 'Could not clear default directory'
    },
    toolsets: {
      loadingConfig: 'Loading configuration',
      savedTitle: 'Credential saved',
      savedMessage: key => `${key} updated.`,
      removedTitle: 'Credential removed',
      removedMessage: key => `${key} removed.`,
      failedSave: key => `Failed to save ${key}`,
      failedRemove: key => `Failed to remove ${key}`,
      failedReveal: key => `Failed to reveal ${key}`,
      removeConfirm: key => `Remove ${key} from .env?`,
      set: 'Set',
      notSet: 'Not set',
      selectedTitle: 'Provider selected',
      selectedMessage: provider => `${provider} is now active.`,
      failedSelect: provider => `Failed to select ${provider}`,
      failedLoad: 'Tool configuration failed to load',
      noProviderOptions: 'This toolset has no provider options — enable it and it works with your current setup.',
      noProviders: 'No providers are available for this toolset right now.',
      ready: 'Ready',
      nousIncluded: 'Included with a Nous subscription — sign in to Nous Portal to activate.',
      noApiKeyRequired: 'No API key required.',
      postSetupHint: step =>
        `This backend needs a one-time install (${step}). Runs on this machine — may take a few minutes.`,
      postSetupRun: 'Run setup',
      postSetupRunning: 'Installing…',
      postSetupStarting: 'Starting…',
      postSetupCompleteTitle: 'Setup complete',
      postSetupCompleteMessage: step => `${step} installed.`,
      postSetupErrorTitle: 'Setup finished with errors',
      postSetupErrorMessage: step => `Check the ${step} log.`,
      postSetupFailed: step => `Failed to run ${step} setup`
    }
  },

  skills: {
    tabSkills: 'Skills',
    tabToolsets: 'Toolsets',
    all: 'All',
    searchSkills: 'Search skills...',
    searchToolsets: 'Search toolsets...',
    refresh: 'Refresh skills',
    refreshing: 'Refreshing skills',
    loading: 'Loading capabilities...',
    noSkillsTitle: 'No skills found',
    noSkillsDesc: 'Try a broader search or different category.',
    noToolsetsTitle: 'No toolsets found',
    noToolsetsDesc: 'Try a broader search query.',
    noDescription: 'No description.',
    configured: 'Configured',
    needsKeys: 'Needs keys',
    toolsetsEnabled: (enabled, total) => `${enabled}/${total} toolsets enabled`,
    configureToolset: label => `Configure ${label}`,
    toggleToolset: label => `Toggle ${label} toolset`,
    skillsLoadFailed: 'Skills failed to load',
    toolsetsRefreshFailed: 'Toolsets failed to refresh',
    skillEnabled: 'Skill enabled',
    skillDisabled: 'Skill disabled',
    toolsetEnabled: 'Toolset enabled',
    toolsetDisabled: 'Toolset disabled',
    appliesToNewSessions: name => `${name} applies to new sessions.`,
    failedToUpdate: name => `Failed to update ${name}`
  },

  agents: {
    close: 'Close agents',
    title: 'Spawn tree',
    subtitle: 'Live subagent activity for the current turn.',
    emptyTitle: 'No live subagents',
    emptyDesc: 'When a turn delegates work, child agents stream their progress here.',
    running: 'Running',
    failed: 'Failed',
    done: 'Done',
    streaming: 'Streaming',
    files: 'Files',
    moreFiles: count => `+${count} more files`,
    delegation: index => `Delegation ${index}`,
    workers: count => `${count} workers`,
    workersActive: count => `${count} active`,
    agentsCount: count => `${count} ${count === 1 ? 'agent' : 'agents'}`,
    activeCount: count => `${count} active`,
    failedCount: count => `${count} failed`,
    toolsCount: count => `${count} tools`,
    filesCount: count => `${count} files`,
    updatedAgo: age => `updated ${age}`,
    ageNow: 'now',
    ageSeconds: seconds => `${seconds}s ago`,
    ageMinutes: minutes => `${minutes}m ago`,
    ageHours: hours => `${hours}h ago`,
    durationSeconds: seconds => `${seconds}s`,
    durationMinutes: (minutes, seconds) => `${minutes}m ${seconds}s`,
    tokensK: k => `${k}k tok`,
    tokens: value => `${value} tok`
  },

  commandCenter: {
    close: 'Close command center',
    paletteTitle: 'Command palette',
    back: 'Back',
    searchPlaceholder: 'Search sessions, views, and actions',
    goTo: 'Go to',
    goToSession: 'Go to session',
    commandCenter: 'Command Center',
    appearance: 'Appearance',
    settings: 'Settings',
    changeTheme: 'Change theme',
    changeColorMode: 'Change color mode...',
    pets: {
      title: 'Pets',
      placeholder: 'Search pets…',
      loading: 'Loading petdex gallery…',
      error: 'Could not reach the petdex gallery.',
      staleBackend: 'Restart Hermes to use pets — the backend predates this feature.',
      empty: 'No matching pets.',
      turnOff: 'Turn off',
      turnOn: 'Turn on',
      installed: 'Installed',
      generatedTag: 'Generated',
      adoptFailed: 'Could not adopt that pet.',
      toggleFailed: 'Could not toggle the pet.',
      noneAvailable: 'No pets available — pick one below to install.'
    },
    generatePet: {
      title: 'Generate a pet',
      placeholder: 'Describe a pet to generate…',
      promptHint: 'Type a description, then press Enter to draft four looks.',
      readyHint: 'Press Enter to draft four looks from your description.',
      generate: 'Generate',
      generating: 'Generating…',
      retry: 'Retry',
      hatch: 'Hatch',
      spawning: 'Spawning…',
      hatching: 'Hatching your pet…',
      hatchingSub: 'Bringing it to life…',
      hatched: 'It hatched!',
      hatchRow: (_state, done, total) => `Sketching frame ${done} of ${total}…`,
      hatchComposing: 'Piecing it together…',
      hatchSaving: 'Almost there…',
      namePlaceholder: 'Name your pet',
      staleBackend: 'Update Hermes to generate pets.',
      backgroundHint: 'You can close this — Hermes will notify you when it’s done.',
      genericError: 'Generation failed — try again or pick a suggestion.',
      referenceImageTooLarge: 'Reference image is too large. Use one under 16 MB.',
      referenceImageInvalid: 'Could not read that reference image. Try a PNG, JPG, WebP, or GIF.',
      adopt: 'Adopt',
      startOver: 'Start over'
    },
    installTheme: {
      title: 'Install theme...',
      placeholder: 'Search the VS Code Marketplace...',
      loading: 'Searching the Marketplace...',
      error: 'Could not reach the Marketplace.',
      empty: 'No matching themes.',
      install: 'Install',
      installing: 'Installing...',
      installed: 'Installed',
      installs: count => `${count} installs`
    },
    settingsFields: 'Settings fields',
    mcpServers: 'MCP servers',
    archivedChats: 'Archived chats',
    sections: { sessions: 'Sessions', system: 'System', usage: 'Usage' },
    sectionDescriptions: {
      sessions: 'Search and manage sessions',
      system: 'Status, logs, and system actions',
      usage: 'Token, cost, and skill activity over time'
    },
    nav: {
      newChat: { title: 'New session', detail: 'Start a fresh session' },
      settings: { title: 'Settings', detail: 'Configure Hermes desktop' },
      skills: { title: 'Skills & Tools', detail: 'Enable skills, toolsets, and providers' },
      messaging: { title: 'Messaging', detail: 'Set up Telegram, Slack, Discord, and more' },
      artifacts: { title: 'Artifacts', detail: 'Browse generated outputs' }
    },
    sectionEntries: {
      sessions: { title: 'Sessions panel', detail: 'Search, pin, and manage sessions' },
      system: { title: 'System panel', detail: 'Gateway status, logs, restart/update' },
      usage: { title: 'Usage panel', detail: 'Token, cost, and skill activity' }
    },
    providerNavigate: 'Navigate',
    providerSessions: 'Sessions',
    refresh: 'Refresh',
    refreshing: 'Refreshing...',
    noResults: 'No matching results found.',
    pinSession: 'Pin session',
    unpinSession: 'Unpin session',
    exportSession: 'Export session',
    deleteSession: 'Delete session',
    noSessions: 'No sessions yet.',
    gatewayRunning: 'Messaging gateway running',
    gatewayStopped: 'Messaging gateway stopped',
    hermesActiveSessions: (version, count) => `Hermes ${version} · Active sessions ${count}`,
    restartGateway: 'Restart gateway',
    gatewayRestartFailed: 'Gateway restart failed.',
    updateHermes: 'Update Hermes',
    actionRunning: 'running',
    actionDone: 'done',
    actionFailed: 'failed',
    actionStartedWaiting: 'Action started, waiting for status...',
    loadingStatus: 'Loading status...',
    recentLogs: 'Recent logs',
    noLogs: 'No logs loaded yet.',
    days: count => `${count}d`,
    statSessions: 'Sessions',
    statApiCalls: 'API calls',
    statTokens: 'Tokens in/out',
    statCost: 'Est. cost',
    actualCost: cost => `actual ${cost}`,
    loadingUsage: 'Loading usage...',
    noUsage: period => `No usage in the last ${period} days.`,
    retry: 'Retry',
    dailyTokens: 'Daily tokens',
    input: 'input',
    output: 'output',
    noDailyActivity: 'No daily activity.',
    topModels: 'Top models',
    noModelUsage: 'No model usage yet.',
    topSkills: 'Top skills',
    noSkillActivity: 'No skill activity yet.',
    actions: count => `${count} actions`
  },

  messaging: {
    search: 'Search messaging...',
    loading: 'Loading messaging platforms...',
    loadFailed: 'Messaging platforms failed to load',
    states: {
      connected: 'Connected',
      connecting: 'Connecting',
      disabled: 'Disabled',
      fatal: 'Error',
      gateway_stopped: 'Messaging gateway stopped',
      not_configured: 'Needs setup',
      pending_restart: 'Restart needed',
      retrying: 'Retrying',
      startup_failed: 'Startup failed'
    },
    unknown: 'Unknown',
    hintPendingRestart: 'Restart the gateway from the status bar to apply this change.',
    hintGatewayStopped: 'Start the gateway from the status bar to connect.',
    credentialsSet: 'Credentials set',
    needsSetup: 'Needs setup',
    gatewayStopped: 'Messaging gateway stopped',
    getCredentials: 'Get your credentials',
    openSetupGuide: 'Open setup guide',
    required: 'Required',
    recommended: 'Recommended',
    advanced: count => `Advanced (${count})`,
    noTokenNeeded: 'This platform does not need a token here. Use the setup guide above, then enable it below.',
    enabled: 'Enabled',
    disabled: 'Disabled',
    unsavedChanges: 'Unsaved changes',
    saving: 'Saving...',
    saveChanges: 'Save changes',
    saved: 'Saved',
    replaceValue: 'Replace current value',
    openDocs: 'Open docs',
    clearField: key => `Clear ${key}`,
    enableAria: name => `Enable ${name}`,
    disableAria: name => `Disable ${name}`,
    platformEnabled: name => `${name} enabled`,
    platformDisabled: name => `${name} disabled`,
    restartToApply: 'This change takes effect after a gateway restart.',
    setupSaved: name => `${name} setup saved`,
    restartToReconnect: 'New credentials take effect after a gateway restart.',
    keyCleared: key => `${key} cleared`,
    setupUpdated: name => `${name} setup was updated.`,
    failedUpdate: name => `Failed to update ${name}`,
    failedSave: name => `Failed to save ${name}`,
    failedClear: key => `Failed to clear ${key}`,
    fieldCopy: {
      TELEGRAM_BOT_TOKEN: {
        label: 'Bot token',
        help: 'Create a bot with @BotFather, then paste the token it gives you.',
        placeholder: 'Paste Telegram bot token'
      },
      TELEGRAM_ALLOWED_USERS: {
        label: 'Allowed Telegram user IDs',
        help: 'Recommended. Comma-separated numeric IDs from @userinfobot. Without this, anyone can DM your bot.'
      },
      TELEGRAM_PROXY: { label: 'Proxy URL', help: 'Only needed on networks where Telegram is blocked.' },
      DISCORD_BOT_TOKEN: {
        label: 'Bot token',
        help: 'Create an application in the Discord Developer Portal, add a bot, then paste its token.'
      },
      DISCORD_ALLOWED_USERS: {
        label: 'Allowed Discord user IDs',
        help: 'Recommended. Comma-separated Discord user IDs.'
      },
      DISCORD_REPLY_TO_MODE: { label: 'Reply style', help: 'first, all, or off.' },
      DISCORD_ALLOW_ALL_USERS: {
        label: 'Allow all Discord users',
        help: 'Development only. When true, anyone can DM the bot without an allowlist.'
      },
      DISCORD_HOME_CHANNEL: {
        label: 'Home channel ID',
        help: 'Channel where the bot sends proactive messages (cron output, reminders).'
      },
      DISCORD_HOME_CHANNEL_NAME: {
        label: 'Home channel name',
        help: 'Display name for the home channel in logs and status output.'
      },
      BLUEBUBBLES_ALLOW_ALL_USERS: {
        label: 'Allow all iMessage users',
        help: 'When true, skip the BlueBubbles allowlist.'
      },
      MATTERMOST_ALLOW_ALL_USERS: { label: 'Allow all Mattermost users' },
      MATTERMOST_HOME_CHANNEL: { label: 'Home channel' },
      QQ_ALLOW_ALL_USERS: { label: 'Allow all QQ users' },
      QQBOT_HOME_CHANNEL: { label: 'QQ home channel', help: 'Default channel or group for cron delivery.' },
      QQBOT_HOME_CHANNEL_NAME: { label: 'QQ home channel name' },
      SLACK_BOT_TOKEN: {
        label: 'Slack bot token',
        help: 'Use the bot token from OAuth & Permissions after installing your Slack app.',
        placeholder: 'Paste Slack bot token'
      },
      SLACK_APP_TOKEN: {
        label: 'Slack app token',
        help: 'Use the app-level token required for Socket Mode.',
        placeholder: 'Paste Slack app token'
      },
      SLACK_ALLOWED_USERS: { label: 'Allowed Slack user IDs', help: 'Recommended. Comma-separated Slack user IDs.' },
      MATTERMOST_URL: { label: 'Server URL', placeholder: 'https://mattermost.example.com' },
      MATTERMOST_TOKEN: { label: 'Bot token' },
      MATTERMOST_ALLOWED_USERS: {
        label: 'Allowed user IDs',
        help: 'Recommended. Comma-separated Mattermost user IDs.'
      },
      MATRIX_HOMESERVER: { label: 'Homeserver URL', placeholder: 'https://matrix.org' },
      MATRIX_ACCESS_TOKEN: { label: 'Access token' },
      MATRIX_USER_ID: { label: 'Bot user ID', placeholder: '@hermes:example.org' },
      MATRIX_ALLOWED_USERS: {
        label: 'Allowed Matrix user IDs',
        help: 'Recommended. Comma-separated user IDs in @user:server format.'
      },
      SIGNAL_HTTP_URL: {
        label: 'Signal bridge URL',
        placeholder: 'http://127.0.0.1:8080',
        help: 'URL of a running signal-cli REST bridge.'
      },
      SIGNAL_ACCOUNT: { label: 'Phone number', help: 'The number registered with your signal-cli bridge.' },
      SIGNAL_ALLOWED_USERS: { label: 'Allowed Signal users', help: 'Recommended. Comma-separated Signal identifiers.' },
      WHATSAPP_ENABLED: {
        label: 'Enable WhatsApp bridge',
        help: 'Set automatically by the toggle below. Leave alone unless you know you need it.'
      },
      WHATSAPP_MODE: { label: 'Bridge mode' },
      WHATSAPP_ALLOWED_USERS: {
        label: 'Allowed WhatsApp users',
        help: 'Recommended. Comma-separated phone numbers or WhatsApp IDs.'
      }
    },
    platformIntro: {}
  },

  profiles: {
    close: 'Close profiles',
    nameHint: 'Lowercase letters, digits, hyphens, and underscores. Must start with a letter or digit.',
    title: 'Profiles',
    count: count => `${count} ${count === 1 ? 'profile' : 'profiles'}`,
    loading: 'Loading profiles...',
    newProfile: 'New profile',
    allProfiles: 'All profiles',
    showAllProfiles: 'Show all profiles',
    switchToProfile: name => `Switch to ${name}`,
    manageProfiles: 'Manage profiles...',
    actionsFor: name => `Actions for ${name}`,
    color: 'Color...',
    colorFor: name => `Color for ${name}`,
    setColor: color => `Set color ${color}`,
    autoColor: 'Auto',
    noProfiles: 'No profiles yet.',
    selectPrompt: 'Select a profile to view its details.',
    refresh: 'Refresh profiles',
    refreshing: 'Refreshing profiles',
    default: 'default',
    skills: count => `${count} ${count === 1 ? 'skill' : 'skills'}`,
    env: 'env',
    defaultBadge: 'Default',
    rename: 'Rename',
    copySetup: 'Copy setup',
    copying: 'Copying...',
    modelLabel: 'Model',
    skillsLabel: 'Skills',
    notSet: 'Not set',
    soulDesc: 'The system prompt and persona instructions baked into this profile.',
    soulOptional: 'optional',
    soulPlaceholder: mode => `The system prompt / persona for this profile.\nLeave blank to keep the ${mode} default.`,
    soulPlaceholderCloned: 'cloned',
    soulPlaceholderEmpty: 'empty',
    unsavedChanges: 'Unsaved changes',
    loadingSoul: 'Loading SOUL.md...',
    emptySoul: 'Empty SOUL.md — start writing the persona...',
    saving: 'Saving...',
    saveSoul: 'Save SOUL.md',
    deleteTitle: 'Delete profile?',
    deleteDescPrefix: 'This will delete ',
    deleteDescMid: ' and remove its ',
    deleteDescSuffix: ' directory. This cannot be undone.',
    deleting: 'Deleting...',
    createDesc: 'Profiles are independent Hermes environments: separate config, skills, and SOUL.md.',
    nameLabel: 'Name',
    cloneFrom: 'Clone from',
    cloneFromNone: 'None (blank)',
    cloneFromDesc: 'Copies config, skills, and SOUL.md from the selected source profile.',
    cloneFromDefault: 'Clone from default',
    cloneFromDefaultDesc: 'Copy config, skills, and SOUL.md from your default profile.',
    invalidName: hint => `Invalid name. ${hint}`,
    nameRequired: 'Name is required.',
    creating: 'Creating...',
    createAction: 'Create profile',
    renameTitle: 'Rename profile',
    renameDescPrefix: 'Renaming updates the profile directory and any wrapper scripts in ',
    renameDescSuffix: '.',
    newNameLabel: 'New name',
    renaming: 'Renaming...',
    created: 'Profile created',
    renamed: 'Profile renamed',
    deleted: 'Profile deleted',
    setupCopied: 'Setup command copied',
    soulSaved: 'SOUL.md saved',
    failedLoad: 'Failed to load profiles',
    failedDelete: 'Failed to delete profile',
    failedCopy: 'Failed to copy setup command',
    failedLoadSoul: 'Failed to load SOUL.md',
    failedSaveSoul: 'Failed to save SOUL.md',
    failedCreate: 'Failed to create profile',
    failedRename: 'Failed to rename profile'
  },

  cron: {
    close: 'Close cron',
    search: 'Search cron jobs...',
    loading: 'Loading cron jobs...',
    states: {
      enabled: 'enabled',
      scheduled: 'scheduled',
      running: 'running',
      paused: 'paused',
      disabled: 'disabled',
      error: 'error',
      completed: 'completed'
    },
    deliveryLabels: {
      local: 'This desktop',
      telegram: 'Telegram',
      discord: 'Discord',
      slack: 'Slack',
      email: 'Email'
    },
    scheduleLabels: {
      daily: 'Daily',
      weekdays: 'Weekdays',
      weekly: 'Weekly',
      monthly: 'Monthly',
      hourly: 'Hourly',
      'every-15-minutes': 'Every 15 minutes',
      custom: 'Custom'
    },
    scheduleHints: {
      daily: 'Every day at 9:00 AM',
      weekdays: 'Monday through Friday at 9:00 AM',
      weekly: 'Every Monday at 9:00 AM',
      monthly: 'The first day of each month at 9:00 AM',
      hourly: 'At the top of every hour',
      'every-15-minutes': 'Every 15 minutes',
      custom: 'Cron syntax or natural language'
    },
    days: {
      '0': 'Sunday',
      '1': 'Monday',
      '2': 'Tuesday',
      '3': 'Wednesday',
      '4': 'Thursday',
      '5': 'Friday',
      '6': 'Saturday',
      '7': 'Sunday'
    },
    dayFallback: value => `day ${value}`,
    everyDayAt: time => `Every day at ${time}`,
    weekdaysAt: time => `Weekdays at ${time}`,
    everyDayOfWeekAt: (day, time) => `Every ${day} at ${time}`,
    monthlyOnDayAt: (dayOfMonth, time) => `Monthly on day ${dayOfMonth} at ${time}`,
    topOfHour: 'At the top of every hour',
    everyHourAt: minute => `Every hour at :${minute}`,
    newCron: 'New cron',
    emptyDescNew:
      'Schedule a prompt to run on a cron expression. Hermes will run it and deliver results to the destination you pick.',
    emptyDescSearch: 'Try a broader search query.',
    emptyTitleNew: 'No scheduled jobs yet',
    emptyTitleSearch: 'No matches',
    last: 'Last:',
    next: 'Next:',
    noRuns: 'No runs yet',
    manage: 'Manage',
    showRuns: 'Show runs',
    hideRuns: 'Hide runs',
    runHistory: 'Run history',
    actionsFor: title => `Actions for ${title}`,
    actionsTitle: 'Cron job actions',
    resume: 'Resume cron',
    pause: 'Pause cron',
    resumeTitle: 'Resume',
    pauseTitle: 'Pause',
    triggerNow: 'Trigger now',
    edit: 'Edit cron',
    deleteTitle: 'Delete cron job?',
    deleteDescPrefix: 'This will remove ',
    deleteDescSuffix: ' permanently. It will stop firing immediately.',
    deleting: 'Deleting...',
    resumed: 'Cron resumed',
    paused: 'Cron paused',
    triggered: 'Cron triggered',
    deleted: 'Cron deleted',
    created: 'Cron created',
    updated: 'Cron updated',
    failedLoad: 'Failed to load cron jobs',
    failedUpdate: 'Failed to update cron job',
    failedTrigger: 'Failed to trigger cron job',
    failedDelete: 'Failed to delete cron job',
    failedSave: 'Failed to save cron job',
    editTitle: 'Edit cron job',
    createTitle: 'New cron job',
    editDesc: 'Update the schedule, prompt, or delivery target. Changes apply on next run.',
    createDesc: 'Schedule a prompt to run automatically. Use cron syntax or a natural phrase like "every 15 minutes".',
    nameLabel: 'Name',
    namePlaceholder: 'Morning briefing',
    promptLabel: 'Prompt',
    promptPlaceholder: 'Summarize my unread Slack threads and email me the top 5...',
    frequencyLabel: 'Frequency',
    deliverLabel: 'Deliver to',
    customScheduleLabel: 'Custom schedule',
    customPlaceholder: '0 9 * * * or weekdays at 9am',
    customHint: 'Cron expression, or phrases like "every hour" or "weekdays at 9am".',
    optional: 'Optional',
    promptScheduleRequired: 'Prompt and schedule are required.',
    saveChanges: 'Save changes',
    createAction: 'Create cron'
  },

  artifacts: {
    search: 'Search artifacts...',
    refresh: 'Refresh artifacts',
    refreshing: 'Refreshing artifacts',
    indexing: 'Indexing recent session artifacts',
    tabAll: 'All',
    tabImages: 'Images',
    tabFiles: 'Files',
    tabLinks: 'Links',
    noArtifactsTitle: 'No artifacts found',
    noArtifactsDesc: 'Generated images and file outputs will appear here as sessions produce them.',
    failedLoad: 'Artifacts failed to load',
    openFailed: 'Open failed',
    itemsImage: 'images',
    itemsLink: 'links',
    itemsFile: 'files',
    itemsGeneric: 'items',
    zero: '0',
    rangeOf: (start, end, total) => `${start}-${end} of ${total}`,
    goToPage: (itemLabel, page) => `Go to ${itemLabel} page ${page}`,
    colTitleLink: 'Link title',
    colTitleFile: 'Name',
    colTitleDefault: 'Title / name',
    colLocationLink: 'URL',
    colLocationFile: 'Path',
    colLocationDefault: 'Location',
    colSession: 'Session',
    kindImage: 'image',
    kindFile: 'file',
    kindLink: 'link',
    chat: 'Chat',
    copyUrl: 'Copy URL',
    copyPath: 'Copy path'
  },

  sidebar: {
    nav: {
      'new-session': 'New session',
      skills: 'Skills & Tools',
      messaging: 'Messaging',
      artifacts: 'Artifacts'
    },
    searchAria: 'Search sessions',
    searchPlaceholder: 'Search sessions…',
    clearSearch: 'Clear search',
    noMatch: query => `No sessions match “${query}”.`,
    results: 'Results',
    pinned: 'Pinned',
    sessions: 'Sessions',
    cronJobs: 'Cron jobs',
    groupAriaGrouped: 'Show sessions as a single list',
    groupAriaUngrouped: 'Group sessions by workspace',
    groupTitleGrouped: 'Ungroup sessions',
    groupTitleUngrouped: 'Group by workspace',
    allPinned: 'Everything here is pinned. Unpin a chat to show it in recents.',
    shiftClickHint: 'Shift-click a chat to pin',
    noWorkspace: 'No workspace',
    newSessionIn: label => `New session in ${label}`,
    reorderWorkspace: label => `Reorder workspace ${label}`,
    showMoreIn: (count, label) => `Show ${count} more in ${label}`,
    loading: 'Loading…',
    loadMore: 'Load more',
    loadCount: step => `Load ${step} more`,
    row: {
      pin: 'Pin',
      unpin: 'Unpin',
      copyId: 'Copy ID',
      export: 'Export',
      rename: 'Rename',
      archive: 'Archive',
      newWindow: 'New window',
      copyIdFailed: 'Could not copy session ID',
      actionsFor: title => `Actions for ${title}`,
      sessionActions: 'Session actions',
      sessionRunning: 'Session running',
      needsInput: 'Needs your input',
      waitingForAnswer: 'Waiting for your answer',
      handoffOrigin: platform => `Handed off from ${platform}`,
      renamed: 'Renamed',
      renameFailed: 'Rename failed',
      renameTitle: 'Rename session',
      renameDesc: 'Give this chat a memorable title. Leave empty to clear.',
      untitledPlaceholder: 'Untitled session',
      ageNow: 'now',
      ageDay: 'd',
      ageHour: 'h',
      ageMin: 'm'
    }
  },

  composer: {
    message: 'Message',
    wakingProfile: profile => `Waking up ${profile}…`,
    placeholderStarting: 'Starting Hermes...',
    placeholderReconnecting: 'Reconnecting to Hermes…',
    placeholderFollowUp: 'Send follow-up',
    newSessionPlaceholders: [
      'What are we building?',
      'Give Hermes a task',
      "What's on your mind?",
      'Describe what you need',
      'What should we tackle?',
      'Ask anything',
      'Start with a goal'
    ],
    followUpPlaceholders: [
      'Send a follow-up',
      'Add more context',
      'Refine the request',
      "What's next?",
      'Keep it going',
      'Push it further',
      'Adjust or continue'
    ],
    startVoice: 'Start voice conversation',
    queueMessage: 'Queue message',
    steer: 'Steer the current run',
    stop: 'Stop',
    send: 'Send',
    speaking: 'Speaking',
    transcribing: 'Transcribing',
    thinking: 'Thinking',
    muted: 'Muted',
    listening: 'Listening',
    muteMic: 'Mute microphone',
    unmuteMic: 'Unmute microphone',
    stopListening: 'Stop listening and send',
    stopShort: 'Stop',
    endConversation: 'End voice conversation',
    endShort: 'End',
    stopDictation: 'Stop dictation',
    transcribingDictation: 'Transcribing dictation',
    voiceDictation: 'Voice dictation',
    lookupLoading: 'Looking up…',
    lookupNoMatches: 'No matches.',
    lookupTry: 'Try',
    lookupOr: 'or',
    commonCommands: 'Common commands',
    hotkeys: 'Hotkeys',
    helpFooter: 'opens the full panel · backspace dismisses',
    commandDescs: {
      '/help': 'full list of commands + hotkeys',
      '/clear': 'start a new session',
      '/resume': 'resume a prior session',
      '/details': 'control transcript detail level',
      '/copy': 'copy selection or last assistant message',
      '/quit': 'exit hermes'
    },
    hotkeyDescs: {
      'composer.mention': 'reference files, folders, urls, git',
      'composer.slash': 'slash command palette',
      'composer.help': 'this quick help (delete to dismiss)',
      'composer.sendNewline': 'send · Shift+Enter for newline',
      'composer.sendQueued': 'send next queued turn',
      'keybinds.openPanel': 'all keyboard shortcuts',
      'composer.cancel': 'close popover · cancel run',
      'composer.history': 'cycle popover / history'
    },
    attachUrlTitle: 'Attach a URL',
    attachUrlDesc: 'Hermes will fetch the page and include it as context for this turn.',
    urlPlaceholder: 'https://example.com/post',
    urlHintPre: 'Include the full URL, e.g. ',
    attach: 'Attach',
    queued: count => `${count} Queued`,
    attachmentOnly: 'Attachment-only turn',
    emptyTurn: 'Empty turn',
    attachments: count => `${count} attachment${count === 1 ? '' : 's'}`,
    editingInComposer: 'Editing in composer',
    editingQueuedInComposer: 'Editing queued turn in composer',
    queueEdit: 'Edit',
    queueSendNext: 'Next',
    queueSend: 'Send',
    queueDelete: 'Delete',
    queueStuckTitle: 'Queued message not sent',
    queueStuckBody: 'A queued turn kept failing to send. It is still in the queue — try sending it again.',
    previewUnavailable: 'Preview unavailable',
    previewLabel: label => `Preview ${label}`,
    couldNotPreview: label => `Could not preview ${label}`,
    removeAttachment: label => `Remove ${label}`,
    dictating: 'Dictating',
    preparingAudio: 'Preparing audio',
    speakingResponse: 'Speaking response',
    readingAloud: 'Reading aloud',
    themeSuggestions: 'Desktop theme suggestions',
    noMatchingThemes: 'No matching themes.',
    themeTryPre: 'Try ',
    themeTryPost: '.',
    attachLabel: 'Attach',
    files: 'Files…',
    folder: 'Folder…',
    images: 'Images…',
    pasteImage: 'Paste image',
    url: 'URL…',
    promptSnippets: 'Prompt snippets…',
    tipPre: 'Tip: type ',
    tipPost: ' to reference files inline.',
    snippetsTitle: 'Prompt snippets',
    snippetsDesc: 'Pick a starter prompt to drop into the composer.',
    dropFiles: 'Drop files to attach',
    dropSession: 'Drop to link this chat',
    snippets: {
      codeReview: {
        label: 'Code review',
        description: 'Audit the current change for regressions, dropped edge cases, and missing tests.',
        text: 'Please review this for bugs, regressions, and missing tests.'
      },
      implementationPlan: {
        label: 'Implementation plan',
        description: 'Outline an approach before touching code so the diff stays focused.',
        text: 'Please make a concise implementation plan before changing code.'
      },
      explainThis: {
        label: 'Explain this',
        description: 'Walk through how the selected code works and link to the key files.',
        text: 'Please explain how this works and point me to the key files.'
      }
    }
  },

  statusStack: {
    agents: 'Agents',
    background: count => `${count} Background`,
    subagents: count => `${count} Subagent${count === 1 ? '' : 's'}`,
    todos: (done, total) => `Tasks ${done}/${total}`,
    running: 'Running',
    stop: 'Stop',
    dismiss: 'Dismiss',
    exit: code => `exit ${code}`
  },

  updates: {
    stages: {
      idle: 'Getting ready…',
      prepare: 'Getting ready…',
      fetch: 'Downloading…',
      pull: 'Almost there…',
      pydeps: 'Finishing up…',
      update: 'Updating Hermes…',
      rebuild: 'Rebuilding the desktop app…',
      restart: 'Restarting Hermes…',
      done: 'Update complete',
      manual: 'Update from your terminal',
      guiSkew: 'Update the desktop app',
      error: 'Update paused'
    },
    checking: 'Looking for updates…',
    checkFailedTitle: 'Couldn’t check for updates',
    tryAgain: 'Try again',
    notAvailableTitle: 'Update not available',
    unsupportedMessage: 'This version of Hermes can’t update itself from inside the app.',
    connectionRetry: 'Check your connection and try again.',
    latestBody: 'You’re running the latest version.',
    latestBodyBackend: 'The backend is running the latest version.',
    allSetTitle: 'You’re all set',
    availableTitle: 'New update available',
    availableBody: 'A new version of Hermes is ready to install.',
    availableTitleBackend: 'Backend update available',
    availableBodyBackend: 'A newer version of the connected Hermes backend is ready to install.',
    availableBodyNoChangelog: 'A newer version is ready. Release notes aren’t available for this install type.',
    updateNow: 'Update now',
    maybeLater: 'Maybe later',
    moreChanges: count => `+ ${count} more change${count === 1 ? '' : 's'} included.`,
    manualTitle: 'Update from your terminal',
    manualBody: 'You installed Hermes from the command line, so updates run there too. Paste this into your terminal:',
    manualPickedUp: 'Hermes will pick up the new version next time you launch it.',
    guiSkewTitle: 'Update the desktop app',
    guiSkewBody:
      'The backend was updated, but this desktop app package wasn’t changed. Update or reinstall the Hermes desktop app (your AppImage / .deb / .rpm) to match.',
    copy: 'Copy',
    copied: 'Copied',
    done: 'Done',
    applyingBody:
      'The Hermes updater takes over in its own window and reopens Hermes automatically when it’s done. Please don’t reopen Hermes yourself while it’s updating.',
    applyingBodyBackend:
      'The remote backend is applying the update and will restart. Hermes reconnects automatically when it’s back.',
    applyingClose: 'This window will close while the update runs, then Hermes reopens on its own.',
    errorTitle: 'Update didn’t finish',
    errorBody: 'No worries — nothing was lost. You can try again now.',
    notNow: 'Not now',
    applyStatus: {
      preparing: 'Updating backend…',
      pulling: 'Backend updating…',
      restarting: 'Backend restarting to load the update…',
      notAvailable: 'Update not available for this backend.',
      failed: 'Backend update failed.',
      noReturn: 'Backend didn’t come back online. The update may not have completed — check the backend host.'
    }
  },

  install: {
    stageStates: {
      pending: 'Pending',
      running: 'Installing',
      succeeded: 'Done',
      skipped: 'Skipped',
      failed: 'Failed'
    },
    oneTimeTitle: 'Hermes needs a one-time install',
    unsupportedDesc: platform =>
      `Automated first-launch install isn’t available on ${platform} yet. Open Terminal and run the command below, then relaunch this app. Subsequent launches will skip this step.`,
    installCommand: 'Install command',
    copyCommand: 'Copy command',
    viewDocs: 'View install docs',
    installTo: 'Will install to',
    retryAfterRun: 'I’ve run it -- retry',
    failedTitle: 'Installation failed',
    settingUpTitle: 'Setting up Hermes Agent',
    finishingTitle: 'Finishing up',
    failedDesc:
      'One of the install steps failed. On Windows, this can happen if another Hermes CLI or desktop instance is running. Stop any running Hermes instances, then retry. Check the details below or the desktop log for the full transcript.',
    activeDesc:
      'This is a one-time setup. The Hermes installer is downloading dependencies and configuring your machine. Subsequent launches will skip this step.',
    progress: (completed, total) => `${completed} of ${total} steps complete`,
    currentStage: stage => ` -- now: ${stage}`,
    fetchingManifest: 'Fetching installer manifest...',
    error: 'Error',
    hideOutput: 'Hide installer output',
    showOutput: 'Show installer output',
    lines: count => `${count} line${count === 1 ? '' : 's'}`,
    noOutput: 'No output yet.',
    cancelling: 'Cancelling...',
    cancelInstall: 'Cancel install',
    transcriptSaved: 'Full transcript saved to',
    copiedOutput: 'Copied!',
    copyOutput: 'Copy output',
    reloadRetry: 'Reload and retry'
  },

  onboarding: {
    headerTitle: "Let's get you setup with Hermes Agent",
    headerDesc: 'Connect a model provider to start chatting. Most options take one click.',
    preparingInstall: 'Hermes is finishing install. This usually takes under a minute on first run.',
    starting: 'Starting Hermes…',
    lookingUpProviders: 'Looking up providers...',
    collapse: 'Collapse',
    otherProviders: 'Other providers',
    haveApiKey: 'I have an API key',
    chooseLater: "I'll choose a provider later",
    recommended: 'Recommended',
    connected: 'Connected',
    featuredPitch: 'One subscription, 300+ frontier models — the recommended way to run Hermes',
    openRouterPitch: 'One key, hundreds of models — a solid default',
    apiKeyOptions: {
      openrouter: {
        short: 'one key, many models',
        description: 'Hosts hundreds of models behind a single key. Good default for new installs.'
      },
      openai: { short: 'GPT-class models', description: 'Direct access to OpenAI models.' },
      gemini: { short: 'Gemini models', description: 'Direct access to Google Gemini models.' },
      xai: { short: 'Grok models', description: 'Direct access to xAI Grok models.' },
      local: {
        short: 'self-hosted',
        description: 'Point Hermes at a local or self-hosted OpenAI-compatible endpoint (vLLM, llama.cpp, Ollama, etc).'
      }
    },
    backToSignIn: 'Back to sign in',
    getKey: 'Get a key',
    replaceCurrent: 'Replace current value',
    pasteApiKey: 'Paste API key',
    localApiKeyPlaceholder: 'API key (optional — only if your endpoint requires one)',
    couldNotSave: 'Could not save credential.',
    connecting: 'Connecting',
    update: 'Update',
    flowSubtitles: {
      pkce: 'Opens your browser to sign in, then continues here',
      device_code: 'Opens a verification page in your browser — Hermes connects automatically',
      loopback: 'Opens your browser to sign in — Hermes connects automatically',
      external: 'Sign in once in your terminal, then come back to chat'
    },
    startingSignIn: provider => `Starting sign-in for ${provider}...`,
    verifyingCode: provider => `Verifying your code with ${provider}...`,
    connectedProvider: provider => `${provider} connected`,
    connectedPicking: provider => `${provider} connected. Picking a default model...`,
    signInFailed: 'Sign-in failed. Try again.',
    pickDifferentProvider: 'Pick a different provider',
    signInWith: provider => `Sign in with ${provider}`,
    openedBrowser: provider => `We opened ${provider} in your browser.`,
    authorizeThere: 'Authorize Hermes there.',
    copyAuthCode: 'Copy the authorization code and paste it below.',
    pasteAuthCode: 'Paste authorization code',
    reopenAuthPage: 'Re-open authorization page',
    autoBrowser: provider =>
      `We opened ${provider} in your browser. Authorize Hermes there and you'll be connected automatically — nothing to copy or paste.`,
    reopenSignInPage: 'Re-open sign-in page',
    waitingAuthorize: 'Waiting for you to authorize...',
    externalPending: provider =>
      `${provider} signs in through its own CLI. Run this command in a terminal, then come back and pick "I've signed in":`,
    signedIn: "I've signed in",
    deviceCodeOpened: provider => `We opened ${provider} in your browser. Enter this code there:`,
    reopenVerification: 'Re-open verification page',
    copy: 'Copy',
    defaultModel: 'Default model',
    freeTier: 'Free tier',
    pro: 'Pro',
    free: 'Free',
    price: (input, output) => `${input} in / ${output} out per Mtok`,
    change: 'Change',
    startChatting: 'Begin',
    docs: provider => `${provider} docs`
  },

  modelPicker: {
    title: 'Switch model',
    current: 'current:',
    unknown: '(unknown)',
    search: 'Filter providers and models...',
    noModels: 'No models found.',
    addProvider: 'Add provider',
    loadFailed: 'Could not load models',
    noAuthenticatedProviders: 'No authenticated providers.',
    pro: 'Pro',
    proNeedsSubscription: 'Pro models need a paid Nous subscription.',
    free: 'Free',
    freeTier: 'Free tier',
    priceTitle: 'Input / Output price per million tokens'
  },

  modelVisibility: {
    title: 'Models',
    search: 'Search models',
    noAuthenticatedProviders: 'No authenticated providers.',
    addProvider: 'Add provider…'
  },

  shell: {
    windowControls: 'Window controls',
    paneControls: 'Pane controls',
    appControls: 'App controls',
    modelMenu: {
      search: 'Search models',
      noModels: 'No models found',
      editModels: 'Edit Models…',
      refreshModels: 'Refresh Models',
      fast: 'Fast',
      medium: 'Med'
    },
    modelOptions: {
      noOptions: 'No options for this model',
      options: 'Options',
      thinking: 'Thinking',
      fast: 'Fast',
      effort: 'Effort',
      minimal: 'Minimal',
      low: 'Low',
      medium: 'Medium',
      high: 'High',
      max: 'Max',
      updateFailed: 'Model option update failed',
      fastFailed: 'Fast mode update failed'
    },
    gatewayMenu: {
      gateway: 'Gateway',
      connected: 'Connected',
      connecting: 'Connecting',
      offline: 'Offline',
      inferenceReady: 'Inference ready',
      inferenceNotReady: 'Inference not ready',
      checkingInference: 'Checking inference',
      disconnected: 'Disconnected',
      openSystem: 'Open system panel',
      connection: label => `Connection: ${label}`,
      recentActivity: 'Recent activity',
      viewAllLogs: 'View all logs →',
      messagingPlatforms: 'Messaging platforms'
    },
    statusbar: {
      unknown: 'unknown',
      restart: 'restart',
      update: 'update',
      updateInProgress: 'Update in progress',
      commitsBehind: (count, branch) => `${count} commit${count === 1 ? '' : 's'} behind ${branch}`,
      desktopVersion: version => `Hermes Desktop v${version}`,
      backendVersion: version => `Backend v${version}`,
      clientLabel: version => `client v${version}`,
      backendLabel: version => `backend v${version}`,
      commit: sha => `commit ${sha}`,
      branch: branch => `branch ${branch}`,
      closeCommandCenter: 'Close Command Center',
      openCommandCenter: 'Open Command Center',
      showTerminal: 'Show terminal',
      hideTerminal: 'Hide terminal',
      gateway: 'Gateway',
      gatewayReady: 'ready',
      gatewayNeedsSetup: 'needs setup',
      gatewayChecking: 'checking',
      gatewayConnecting: 'connecting',
      gatewayOffline: 'offline',
      gatewayRestarting: 'restarting…',
      gatewayTitle: 'Hermes inference gateway status',
      agents: 'Agents',
      closeAgents: 'Close agents',
      openAgents: 'Open agents',
      subagents: count => `${count} subagent${count === 1 ? '' : 's'}`,
      failed: count => `${count} failed`,
      running: count => `${count} running`,
      cron: 'Cron',
      openCron: 'Open cron jobs',
      turnRunning: 'Running',
      currentTurnElapsed: 'Current turn elapsed',
      contextUsage: 'Context usage',
      session: 'Session',
      runtimeSessionElapsed: 'Runtime session elapsed',
      yoloOn: 'YOLO on — auto-approving dangerous commands. Click to turn off. Shift+click toggles it globally.',
      yoloOff: 'YOLO off — click to auto-approve dangerous commands. Shift+click toggles it globally.',
      modelNone: 'none',
      noModel: 'no model',
      switchModel: 'Switch model',
      openModelPicker: 'Open model picker',
      modelTitle: (provider, model) => `Model · ${provider}: ${model}`,
      providerModelTitle: (provider, model) => `${provider} · ${model}`
    }
  },

  rightSidebar: {
    aria: 'Right sidebar',
    panelsAria: 'Right sidebar panels',
    files: 'File system',
    terminal: 'Terminal',
    noFolderSelected: 'No folder selected',
    changeCwdTitle: 'Change working directory',
    remotePickerTitle: 'Choose remote folder',
    remotePickerDescription: 'Browse folders on the connected backend.',
    remotePickerSelect: 'Select folder',
    folderTip: cwd => `${cwd} — click to change folder`,
    openFolder: 'Open folder',
    refreshTree: 'Refresh tree',
    collapseAll: 'Collapse all folders',
    previewUnavailable: 'Preview unavailable',
    couldNotPreview: path => `Could not preview ${path}`,
    noProjectTitle: 'No project',
    noProjectBody: 'Set a working directory from the status bar to browse files.',
    unreadableTitle: 'Unreadable',
    unreadableBody: error => `Could not read this folder (${error}).`,
    emptyTitle: 'Empty',
    emptyBody: 'This folder is empty.',
    treeErrorTitle: 'Tree error',
    treeErrorBody: 'The file tree hit an error rendering this folder.',
    tryAgain: 'Try again',
    loadingTree: 'Loading file tree',
    loadingFiles: 'Loading files',
    terminalHide: 'Hide terminal',
    addToChat: 'Add to chat'
  },

  preview: {
    tab: 'Preview',
    closeTab: label => `Close ${label}`,
    closePane: 'Close preview pane',
    loading: 'Loading preview',
    unavailable: 'Preview unavailable',
    opening: 'Opening...',
    hide: 'Hide',
    openPreview: 'Open preview',
    openInBrowser: 'Open in browser',
    sourceLineTitle: 'Click to select · shift-click to extend · drag to composer',
    source: 'SOURCE',
    renderedPreview: 'PREVIEW',
    unknownSize: 'unknown size',
    binaryTitle: 'This looks like a binary file',
    binaryBody: label => `Previewing ${label} may show unreadable text.`,
    largeTitle: 'This file is large',
    largeBody: (label, size) => `${label} is ${size}. Hermes will only show the first 512 KB.`,
    previewAnyway: 'Preview anyway',
    truncated: 'Showing first 512 KB.',
    noInlineTitle: 'No inline preview',
    noInlineBody: mimeType => `${mimeType || 'This file type'} can still be attached as context.`,
    console: {
      deselect: 'Deselect entry',
      select: 'Select entry',
      copyFailed: 'Could not copy console output',
      copyEntry: 'Copy this entry',
      sendEntry: 'Send this entry to chat',
      messages: count => `${count} console messages`,
      resize: 'Resize preview console',
      title: 'Preview Console',
      selected: count => `${count} selected`,
      sendToChat: 'Send to chat',
      copySelected: 'Copy selected to clipboard',
      copyAll: 'Copy all to clipboard',
      copy: 'Copy',
      clear: 'Clear',
      empty: 'No console messages yet.',
      promptHeader: 'Preview console:',
      sentTitle: 'Sent to chat',
      sentMessage: count => `${count} log entr${count === 1 ? 'y' : 'ies'} added to composer`
    },
    web: {
      appFailedToBoot: 'Preview app failed to boot',
      serverNotFound: 'Server not found',
      failedToLoad: 'Preview failed to load',
      tryAgain: 'Try again',
      restarting: 'Hermes is restarting...',
      askRestart: 'Ask Hermes to restart the server',
      lookingRestart: taskId => `Hermes is looking for a preview server to restart (${taskId})`,
      restartingTitle: 'Restarting preview server',
      restartingMessage: 'Hermes is working in the background. Watch the preview console for progress.',
      startRestartFailed: message => `Could not start server restart: ${message}`,
      restartFailed: 'Server restart failed',
      hideConsole: 'Hide preview console',
      showConsole: 'Show preview console',
      hideDevTools: 'Hide preview DevTools',
      openDevTools: 'Open preview DevTools',
      finishedRestarting: message => `Hermes finished restarting the preview server${message ? `: ${message}` : ''}`,
      failedRestarting: message => `Server restart failed: ${message}`,
      unknownError: 'unknown error',
      restartedTitle: 'Preview server restarted',
      reloadingNow: 'Reloading the preview now.',
      restartFailedTitle: 'Preview restart failed',
      restartFailedMessage: 'Hermes could not restart the server.',
      stillWorking:
        'Hermes is still working, but no restart result has arrived yet. The server command may be running in the foreground.',
      workspaceReloading: 'Workspace changed, reloading preview',
      fileChanged: url => `File changed, reloading preview: ${url}`,
      filesChanged: (count, url) => `${count} file changes, reloading preview: ${url}`,
      watchFailed: message => `Could not watch preview file: ${message}`,
      moduleMimeDescription:
        'Module scripts are being served with the wrong MIME type. This usually means a static file server is serving a Vite/React app instead of the project dev server.',
      loadFailedConsole: (code, message) => `Load failed${code ? ` (${code})` : ''}: ${message}`,
      unreachableDescription: 'The preview page could not be reached.',
      openTarget: url => `Open ${url}`,
      fallbackTitle: 'Preview'
    }
  },

  assistant: {
    thread: {
      loadingSession: 'Loading session',
      showEarlier: 'Show earlier messages',
      loadingResponse: 'Hermes is loading a response',
      thinking: 'Thinking',
      today: time => `Today, ${time}`,
      yesterday: time => `Yesterday, ${time}`,
      copy: 'Copy',
      refresh: 'Refresh',
      moreActions: 'More actions',
      branchNewChat: 'Branch in new chat',
      dismissError: 'Dismiss error',
      readAloudFailed: 'Read aloud failed',
      preparingAudio: 'Preparing audio...',
      stopReading: 'Stop reading',
      readAloud: 'Read aloud',
      editMessage: 'Edit message',
      scrollToBottom: 'Scroll to bottom',
      stop: 'Stop',
      restorePrevious: 'Restore previous checkpoint',
      restoreCheckpoint: 'Restore checkpoint',
      restoreFromHere: 'Restore checkpoint — rerun from this prompt',
      restoreTitle: 'Restore to this checkpoint?',
      restoreBody:
        'Everything after this prompt is removed from the conversation, and the prompt runs again from here.',
      restoreConfirm: 'Restore & rerun',
      restoreNext: 'Restore next checkpoint',
      goForward: 'Go forward',
      sendEdited: 'Send edited message',
      attachingFile: 'Attaching…'
    },
    approval: {
      gatewayDisconnected: 'Hermes gateway is not connected',
      sendFailed: 'Could not send approval response',
      run: 'Run',
      command: 'Command',
      moreOptions: 'More approval options',
      allowSession: 'Allow this session',
      alwaysAllowMenu: 'Always allow…',
      jumpToApproval: 'Approval needed',
      reject: 'Reject',
      alwaysTitle: 'Always allow this command?',
      alwaysDescription: pattern =>
        `This adds the “${pattern}” pattern to your permanent allowlist (~/.hermes/config.yaml). Hermes won’t ask again for commands like this — in this session or any future one.`,
      alwaysAllow: 'Always allow'
    },
    clarify: {
      notReady: 'Clarify request is not ready yet',
      gatewayDisconnected: 'Hermes gateway is not connected',
      sendFailed: 'Could not send clarify response',
      loadingQuestion: 'Loading question…',
      other: 'Other (type your answer)',
      placeholder: 'Type your answer…',
      shortcutSuffix: ' to send',
      back: 'Back',
      skip: 'Skip',
      send: 'Send'
    },
    tool: {
      code: 'Code',
      copyCode: 'Copy code',
      renderingImage: 'Rendering image',
      copyOutput: 'Copy output',
      copyCommand: 'Copy command',
      copyContent: 'Copy content',
      copyUrl: 'Copy URL',
      copyResults: 'Copy results',
      copyQuery: 'Copy query',
      copyFile: 'Copy file',
      copyPath: 'Copy path',
      outputAlt: 'Tool output',
      rawResponse: 'Raw response',
      copyActivity: 'Copy activity',
      recoveredOne: 'Recovered after 1 failed step',
      recoveredMany: count => `Recovered after ${count} failed steps`,
      failedOne: '1 step failed',
      failedMany: count => `${count} steps failed`,
      statusRunning: 'Running',
      statusError: 'Error',
      statusRecovered: 'Recovered',
      statusDone: 'Done',
      actions: {
        read: 'Read',
        reading: 'Reading',
        opened: 'Opened',
        opening: 'Opening',
        searched: 'Searched',
        searching: 'Searching',
        ran: 'Ran',
        running: 'Running',
        ranCode: 'Ran code',
        runningCode: 'Scripting'
      },
      prefixes: {
        browser: 'Browser',
        web: 'Web'
      },
      titleTemplates: {
        actionCommand: (action, command) => `${action} · ${command}`,
        actionQuoted: (action, value) => `${action} “${value}”`,
        actionTarget: (action, target) => `${action} ${target}`,
        prefixedDone: (prefix, action) => `${prefix} ${action}`,
        runningPrefixedTool: (prefix, action) => `Running ${prefix.toLowerCase()} ${action.toLowerCase()}`,
        runningTool: action => `Running ${action.toLowerCase()}`
      },
      titles: {
        browser_click: { done: 'Clicked page element', pending: 'Clicking page element', pendingAction: 'Clicking' },
        browser_fill: { done: 'Filled form field', pending: 'Filling form field', pendingAction: 'Filling' },
        browser_navigate: { done: 'Opened page', pending: 'Opening page', pendingAction: 'Opening' },
        browser_snapshot: {
          done: 'Captured page snapshot',
          pending: 'Capturing page snapshot',
          pendingAction: 'Capturing'
        },
        browser_take_screenshot: {
          done: 'Captured screenshot',
          pending: 'Capturing screenshot',
          pendingAction: 'Capturing'
        },
        browser_type: { done: 'Typed on page', pending: 'Typing on page', pendingAction: 'Typing' },
        clarify: { done: 'Asked a question', pending: 'Asking a question', pendingAction: 'Asking' },
        cronjob: { done: 'Cron job', pending: 'Scheduling cron job', pendingAction: 'Scheduling' },
        edit_file: { done: 'Edited file', pending: 'Editing file', pendingAction: 'Editing' },
        execute_code: { done: 'Ran code', pending: 'Scripting', pendingAction: 'Scripting' },
        image_generate: { done: 'Generated image', pending: 'Generating image', pendingAction: 'Generating' },
        list_files: { done: 'Listed files', pending: 'Listing files', pendingAction: 'Listing' },
        patch: { done: 'Patched file', pending: 'Patching file', pendingAction: 'Patching' },
        read_file: { done: 'Read file', pending: 'Reading file', pendingAction: 'Reading' },
        search_files: { done: 'Searched files', pending: 'Searching files', pendingAction: 'Searching' },
        session_search_recall: {
          done: 'Searched session history',
          pending: 'Searching session history',
          pendingAction: 'Searching'
        },
        terminal: { done: 'Ran command', pending: 'Running command', pendingAction: 'Running' },
        todo: { done: 'Updated todos', pending: 'Updating todos', pendingAction: 'Updating' },
        vision_analyze: { done: 'Analyzed image', pending: 'Analyzing image', pendingAction: 'Analyzing' },
        web_extract: { done: 'Read webpage', pending: 'Reading webpage', pendingAction: 'Reading' },
        web_search: { done: 'Searched web', pending: 'Searching web', pendingAction: 'Searching' },
        write_file: { done: 'Edited file', pending: 'Editing file', pendingAction: 'Editing' }
      }
    }
  },

  prompts: {
    gatewayDisconnected: 'Hermes gateway is not connected',
    sudoSendFailed: 'Could not send sudo password',
    secretSendFailed: 'Could not send secret',
    sudoTitle: 'Administrator password',
    sudoDesc: 'Hermes needs your sudo password to run a privileged command. It is sent only to your local agent.',
    sudoPlaceholder: 'sudo password',
    secretTitle: 'Secret required',
    secretDesc: 'Hermes needs a credential to continue.',
    secretPlaceholder: 'secret value'
  },

  desktop: {
    audioReadFailed: 'Could not read recorded audio',
    sessionUnavailable: 'Session unavailable',
    createSessionFailed: 'Could not create a new session',
    promptFailed: 'Prompt failed',
    providerCredentialRequired: 'Add a provider credential before sending your first message.',
    emptySlashCommand: 'empty slash command',
    desktopCommands: 'Desktop commands',
    skillCommandsAvailable: count => `${count} skill commands available.`,
    warningLine: message => `warning: ${message}`,
    yoloArmed: 'YOLO armed for this chat',
    yoloOff: 'YOLO off',
    yoloSystem: active => `YOLO ${active ? 'on' : 'off'} for this session`,
    yoloTitle: 'YOLO',
    yoloToggleFailed: 'Could not toggle YOLO',
    profileStatus: current =>
      `Profile: ${current}. Use /profile <name> or the "New session" picker to start a chat in another profile.`,
    unknownProfile: 'Unknown profile',
    noProfileNamed: (target, available) => `No profile named "${target}". Available: ${available}`,
    newChatsProfile: name => `New chats will use profile ${name}.`,
    setProfileFailed: 'Failed to set profile',
    sttDisabled: 'Speech-to-text is disabled in settings.',
    stopFailed: 'Stop failed',
    regenerateFailed: 'Regenerate failed',
    editFailed: 'Edit failed',
    resumeFailed: 'Resume failed',
    resumeStrandedTitle: "Couldn't load this session",
    resumeStrandedBody:
      'The connection to this session failed and automatic retries gave up. Check that the gateway is running, then try again.',
    resumeRetry: 'Retry',
    nothingToBranch: 'Nothing to branch',
    branchNeedsChat: 'Start or resume a chat before branching.',
    sessionBusy: 'Session busy',
    branchStopCurrent: 'Stop the current turn before branching this chat.',
    branchNoText: 'This message has no text to branch from.',
    branchTitle: 'Branch',
    branchFailed: 'Branch failed',
    deleteFailed: 'Delete failed',
    archived: 'Archived',
    archiveFailed: 'Archive failed',
    cwdChangeFailed: 'Working directory change failed',
    cwdStagedTitle: 'Working directory staged',
    cwdStagedMessage: 'Restart the desktop backend to apply cwd changes to this active session.',
    modelSwitchFailed: 'Model switch failed',
    sessionExported: 'Session exported',
    sessionExportFailed: 'Could not export session',
    imageSaved: 'Image saved',
    downloadStarted: 'Download started',
    restartToUseSaveImage: 'Restart Hermes Desktop to use Save Image.',
    restartToSaveImages: 'Restart Hermes Desktop to save images',
    imageDownloadFailed: 'Image download failed',
    openImage: 'Open image',
    downloadImage: 'Download image',
    savingImage: 'Saving image',
    imagePreviewFailed: 'Image preview failed',
    imageAttach: 'Image attach',
    imageWriteFailed: 'Failed to write image to disk.',
    imageAttachFailed: 'Image attach failed',
    attachImages: 'Attach images',
    clipboard: 'Clipboard',
    noClipboardImage: 'No image found in clipboard',
    clipboardPasteFailed: 'Clipboard paste failed',
    dropFiles: 'Drop files',
    handoff: {
      pickPlatform: 'Choose a destination',
      success: platform => `Handed off to ${platform}. Resume here anytime.`,
      systemNote: platform => `↻ Handed off to ${platform} — resume here anytime.`,
      failed: error => `Handoff failed: ${error}`,
      timedOut: 'Timed out waiting for the gateway. Is `hermes gateway` running?'
    }
  },

  errors: {
    genericFailure: 'Something went wrong',
    boundaryTitle: 'Something broke in the interface',
    boundaryDesc: 'The view hit an unexpected error. Your chats and settings are safe.',
    reloadWindow: 'Reload window',
    openLogs: 'Open logs'
  },

  ui: {
    search: {
      clear: 'Clear search'
    },
    pagination: {
      label: 'pagination',
      previous: 'Prev',
      previousAria: 'Go to previous page',
      next: 'Next',
      nextAria: 'Go to next page'
    },
    sidebar: {
      title: 'Sidebar',
      description: 'Displays the mobile sidebar.',
      toggle: 'Toggle Sidebar'
    }
  }
}
