{
  "channelsSettings": {
    "needToken": "Save a gateway token to edit channel settings.",
    "subtitle": "Telegram, Weixin, and Feishu inbound channels. Changes are written to the gateway config file.",
    "docsLink": "Channel documentation",
    "refresh": "Refresh",
    "loadError": "Failed to load channel settings",
    "loading": "Loading…",
    "save": "Save",
    "discard": "Discard",
    "saving": "Saving…",
    "saved": "Saved",
    "saveError": "Failed to save",
    "retry": "Retry",
    "unsavedHint": "You have unsaved changes.",
    "hubConfigureButton": "Configure",
    "hubConnectedBadge": "Connected",
    "hubStatusRunning": "Running",
    "hubStatusOffline": "Not connected",
    "hubStatusDisabled": "Disabled",
    "hubStatusNotConfigured": "Not configured",
    "hubManageButton": "Manage channel",
    "hubSetupButton": "Set up",
    "hubFixButton": "Check configuration",
    "hubPairingButton": "Review pairing",
    "hubSummaryDm": "DM: {{policy}}",
    "hubSummaryStream": "Streaming: {{mode}}",
    "hubSummaryConnection": "Connection: {{mode}}",
    "hubSummaryAccountCount": "{{count}} account(s)",
    "hubConnectionWebsocket": "WebSocket",
    "hubConnectionWebhook": "Webhook",
    "hubViewDocs": "View documentation",
    "hubExtensionSubtitle": "Extension channel registered on the gateway.",
    "hubExtensionConfiguredHint": "Configuration present in gateway config",
    "hubExtensionManageHint": "This channel is provided by an extension. Configure it in the extension settings or gateway config file.",
    "hubExtensionStatusLabel": "Status",
    "hubExtensionEnabledLabel": "Enabled in config",
    "hubExtensionConnectedLabel": "Runtime connected",
    "hubExtensionYes": "Yes",
    "hubExtensionNo": "No",
    "enableChannelAria": "Enable or disable this channel",
    "modalCancel": "Cancel",
    "telegramTitle": "Telegram",
    "telegramSubtitle": "Bot token, allowlists, and optional multi-account JSON.",
    "weixinTitle": "Weixin",
    "weixinSubtitle": "Sign in with WeChat via QR (browser or CLI), then enable below. Credentials stay on the gateway host.",
    "feishuTitle": "Feishu/Lark",
    "feishuSubtitle": "Feishu app credentials, policies, and optional multi-account JSON.",
    "enableTelegramAria": "Enable Telegram channel",
    "enableWeixinAria": "Enable Weixin channel",
    "enableFeishuAria": "Enable Feishu channel",
    "telegramToken": "Bot token",
    "telegramTokenDesc": "From BotFather. Stored in the gateway config.",
    "feishuAppId": "App ID",
    "feishuAppIdDesc": "From Feishu developer console (cli_xxx). Stored in the gateway config.",
    "feishuAppSecret": "App secret",
    "feishuAppSecretDesc": "From Feishu developer console. Stored in the gateway config.",
    "feishuDomain": "Domain",
    "connectionMode": "Connection mode",
    "connectionModeDesc": "websocket: Socket Mode. webhook: local HTTP server receives events.",
    "renderMode": "Render mode",
    "enableStreaming": "Enable streaming",
    "requireMention": "Require @mention in groups",
    "reactionNotifications": "Reaction notifications",
    "allowFromDm": "Allow from (DM)",
    "allowFromDmDesc": "Static allowlist in config (comma-separated user IDs). Paired users from credential files are listed below.",
    "pairingTitle": "DM pairing",
    "pairingSubtitle": "When DM policy is pairing, new users message the bot to receive a code. Approve here — no CLI required.",
    "pairingSetupHint": "Send any message to your bot in Telegram, then enter the 8-character code below.",
    "pairingPendingTitle": "Pending requests",
    "pairingPendingEmpty": "No pending requests. Message the bot to start pairing.",
    "pairingCodePlaceholder": "Pairing code",
    "pairingApprove": "Approve",
    "pairingApproving": "Approving…",
    "pairingApproved": "Approved user {{id}}.",
    "pairingInvalid": "Invalid or expired pairing code.",
    "pairingLoadError": "Could not load pairing state.",
    "pairingRefresh": "Refresh",
    "pairingExpiresHint": "Expires {{time}}",
    "pairingCodeHint": "Code ends with {{suffix}}",
    "pairedTitle": "Allowed users",
    "pairedFromConfig": "Config allowlist",
    "pairedFromCredentials": "Paired (credential store)",
    "pairedEmpty": "None",
    "pairingAccountLabel": "Bot account",
    "pairingAccountNotPairing": "Account \"{{account}}\" does not use pairing DM policy. Select another account or change its dmPolicy in Advanced JSON.",
    "pairingRevokeAria": "Revoke pairing for {{id}}",
    "pairingRevoked": "Revoked pairing for {{id}}.",
    "pairingRevokeError": "Could not revoke pairing.",
    "hubPairingPendingBadge": "{{count}} pending",
    "telegramSetupStepToken": "1. Save bot token and enable Telegram",
    "telegramSetupStepPairing": "2. Message your bot, then approve the pairing code below",
    "pairingQuickApprove": "Quick approve",
    "pairingQuickApproveHint": "Quick approve skips the pairing code — only use it when you have verified the user id matches someone who messaged your bot.",
    "pairingDismiss": "Dismiss",
    "pairingDismissing": "Dismissing…",
    "pairingDismissed": "Dismissed pending request for {{id}}.",
    "pairingDismissError": "Could not dismiss pending request.",
    "pairingStaleItem": "Stale",
    "advancedShow": "Advanced options",
    "advancedHide": "Hide advanced options",
    "apiRoot": "API root",
    "proxy": "Proxy",
    "dmPolicy": "DM policy",
    "groupPolicy": "Group policy",
    "replyToMode": "Reply-to mode",
    "streamMode": "Stream mode",
    "allowFromGroups": "Allow from (groups)",
    "allowFromGroupsDesc": "Comma-separated group chat IDs (when group policy is allowlist).",
    "historyLimit": "History limit",
    "textChunkLimit": "Text chunk limit",
    "telegramDebug": "Debug mode",
    "multiAccountJson": "Multi-account (JSON)",
    "multiAccountJsonDesc": "Optional. Per-account botToken or tokenFile, policies, and groups. Empty {} uses the single token above only.",
    "weixinQuickStartTitle": "Quick start",
    "weixinStepLogin": "Use “Sign in with WeChat (QR)” below in this console, or see Channel documentation for CLI login.",
    "weixinStepEnable": "Turn on Weixin below and save.",
    "weixinStepPairing": "After QR login, DMs work immediately. Use allowlist DM policy only if you want to restrict who can message the bot.",
    "weixinAdvancedHint": "Optional: allowlist, route tag, streaming, and per-account JSON—only if you need them.",
    "weixinAllowFrom": "Allow from",
    "weixinAllowFromDesc": "When DM policy is allowlist: comma-separated wxid / openid. Default pairing allows all contacts after QR login.",
    "weixinRouteTag": "Route tag",
    "weixinRouteTagDesc": "Optional tag for routing; numeric or string.",
    "routeTagPlaceholder": "e.g. tag name or number",
    "weixinDebug": "Debug mode",
    "weixinDebugDesc": "Extra logging for the Weixin channel.",
    "weixinAccountsJson": "Accounts (JSON)",
    "weixinAccountsJsonDesc": "Per-account name, CDN base URL, route tag, and policies.",
    "weixinQrLoginTitle": "Browser QR login",
    "weixinQrLoginDesc": "Starts a login on the gateway. Scan with WeChat; when it succeeds, settings refresh automatically.",
    "weixinQrLoginButton": "Sign in with WeChat (QR)",
    "weixinQrLoginBusy": "Starting…",
    "weixinQrLoginScanned": "Scanned — confirm in WeChat",
    "weixinQrLoginSuccess": "Weixin connected.",
    "weixinQrLoginCancel": "Dismiss QR",
    "weixinQrImageError": "Could not render the QR code here. You can open the link in a new tab, or tap Regenerate to try again.",
    "weixinQrOpenLink": "Open in new tab",
    "weixinQrEncoding": "Rendering QR…",
    "weixinQrModalTitle": "Scan to sign in",
    "weixinQrModalSubtitle": "Use WeChat to scan the QR code below to connect.",
    "weixinQrRegenerate": "Regenerate QR code",
    "weixinQrModalCloseAria": "Close",
    "feishuQrModalTitle": "Scan to create app",
    "feishuQrModalSubtitle": "Starts with China (Feishu). Use the switch below the QR to use International (Lark). Expand Advanced options for manual credentials and policies.",
    "feishuQrCloseAria": "Close",
    "feishuRegionSwitchAria": "Registration region",
    "feishuRegionChina": "China (Feishu)",
    "feishuRegionInternational": "International (Lark)",
    "feishuAdvancedHint": "Optional: App ID / Secret from the developer console, connection mode, webhook, tools, routing, and multi-account JSON. Save writes to the gateway config.",
    "feishuQrStarting": "Starting…",
    "feishuQrScanHint": "Scan this QR code with Feishu/Lark on your phone.",
    "feishuQrEncoding": "Generating QR…",
    "feishuQrImageError": "Could not generate QR image.",
    "feishuQrOpenLink": "Open link in browser",
    "feishuQrRegenerate": "Regenerate QR",
    "feishuQrSetupSuccess": "Feishu app created and configured.",
    "agentRoutingTitle": "Agent routing",
    "agentRoutingHint": "Maps each channel account to an agent via config `bindings`. Inbound messages use a session key for that agent.",
    "agentRoutingAccountLabel": "Account",
    "agentRoutingAgentLabel": "Agent",
    "jsonObjectAccounts": "Accounts must be a JSON object",
    "jsonInvalid": "Invalid JSON",
    "copy": "Copy",
    "copied": "Copied",
    "show": "Show",
    "hide": "Hide",
    "webhookTitle": "Webhook settings",
    "verificationToken": "Verification token",
    "verificationTokenDesc": "From Feishu event subscription settings (webhook mode).",
    "encryptKey": "Encrypt key",
    "encryptKeyDesc": "From Feishu event subscription settings (webhook mode).",
    "webhookHost": "Webhook host",
    "webhookPort": "Webhook port",
    "webhookPath": "Webhook path",
    "webhookPathDesc": "Request URL path configured in Feishu event subscription.",
    "feishuToolsTitle": "Feishu tools",
    "feishuToolsDesc": "Enable only what you need. Each tool may require additional app scopes.",
    "feishuToolDoc": "Doc (feishu_doc)",
    "feishuToolWiki": "Wiki (feishu_wiki)",
    "feishuToolDrive": "Drive (feishu_drive)",
    "feishuToolPerm": "Permissions (feishu_perm)",
    "feishuToolBitable": "Bitable (feishu_bitable_*)",
    "feishuToolScopes": "Scopes check (feishu_app_scopes)",
    "feishuActionsTitle": "Feishu actions",
    "feishuActionReactions": "Enable reaction actions",
    "policy": {
      "dm": {
        "pairing": "Pairing",
        "allowlist": "Allowlist",
        "open": "Open",
        "disabled": "Disabled"
      },
      "group": {
        "open": "Open",
        "disabled": "Disabled",
        "allowlist": "Allowlist"
      },
      "reply": {
        "off": "Off",
        "first": "First",
        "all": "All"
      },
      "stream": {
        "off": "Off",
        "partial": "Partial",
        "block": "Block"
      }
    }
  },
  "voiceSettings": {
    "needToken": "Save a gateway token to edit voice settings.",
    "subtitle": "Speech-to-text and text-to-speech for channels. Keys can also be set via environment variables.",
    "docsLink": "Voice documentation",
    "loadError": "Failed to load voice settings",
    "loading": "Loading…",
    "save": "Save",
    "discard": "Discard",
    "saving": "Saving…",
    "saved": "Saved",
    "saveError": "Failed to save",
    "retry": "Retry",
    "unsavedHint": "You have unsaved changes.",
    "apiKeyMaskedHelp": "Saved keys are hidden. Click the eye to load the key from your config file (not from environment variables).",
    "apiKeyCopy": "Copy",
    "apiKeyCopied": "Copied",
    "apiKeyShow": "Show",
    "apiKeyHide": "Hide",
    "apiKeyNotInConfigFile": "No key stored in the config file for this provider (check environment variables).",
    "apiKeyRevealFailed": "Could not load key from config.",
    "stt": {
      "title": "Speech-to-text (STT)",
      "description": "Transcribe inbound voice using Alibaba DashScope or OpenAI Whisper.",
      "enable": "Enable STT",
      "enableDesc": "When on, voice messages can be transcribed for the agent.",
      "provider": "STT provider",
      "alibaba": "Alibaba DashScope",
      "openai": "OpenAI",
      "apiKey": "API key",
      "apiKeyDesc": "Optional if the key is already in the environment.",
      "model": "Model",
      "fallback": "Fallback between providers",
      "fallbackDesc": "Try the other provider if the primary request fails."
    },
    "tts": {
      "title": "Text-to-speech (TTS)",
      "description": "Synthesize assistant replies as audio when enabled.",
      "enable": "Enable TTS",
      "enableDesc": "When on, TTS runs according to the trigger mode below.",
      "trigger": "Trigger",
      "triggerOff": "Off",
      "triggerAlways": "Always",
      "triggerInbound": "Inbound voice only",
      "triggerTagged": "Tagged ([[tts]])",
      "triggerDescOff": "TTS is completely disabled.",
      "triggerDescAlways": "Apply TTS to all assistant messages.",
      "triggerDescInbound": "Only reply with voice when the user sends voice.",
      "triggerDescTagged": "Only when the [[tts]] directive is used.",
      "provider": "TTS provider",
      "providerOpenai": "OpenAI TTS",
      "providerEdge": "Microsoft Edge (free)",
      "providerLocalCli": "Local CLI (offline)",
      "voice": "Voice",
      "edgeHint": "Microsoft Edge TTS — no API key required.",
      "localCli": {
        "command": "CLI command",
        "commandDesc": "Shell template; placeholders: {{Text}}, {{OutputBase}}.",
        "commandPlaceholder": "mlx_audio.tts.generate --text \"{{Text}}\" --file_prefix {{OutputBase}}",
        "cwd": "Working directory",
        "cwdDesc": "Optional. Defaults to the gateway working directory.",
        "outputFormat": "Output format",
        "outputFormatDesc": "File extension produced by the CLI (mp3, wav, opus, …).",
        "timeoutMs": "Timeout (ms)",
        "timeoutMsDesc": "Per-call timeout override; leave blank to inherit the TTS default.",
        "hint": "Provided by the bundled `tts-local-cli` extension. Enable the extension and configure the binary on PATH."
      }
    },
    "notes": {
      "title": "Note",
      "duration": "Long audio is split automatically; quality depends on provider and model.",
      "envVars": "Environment variables: DASHSCOPE_API_KEY, OPENAI_API_KEY (when not set in this form)."
    }
  },
  "gatewaySettings": {
    "needToken": "Save a gateway token to load and edit gateway options.",
    "subtitle": "HTTP API access token and listen address. Values are stored in the gateway config file.",
    "tabsAriaLabel": "Gateway settings categories",
    "tabNetwork": "Network",
    "tabAccess": "Access",
    "tabUpdates": "Updates",
    "tabSecurity": "Security",
    "tabAdvanced": "Advanced",
    "networkTabHint": "Configure listen address, port, and allowed CORS origins.",
    "accessTabHint": "Configure token, password, trusted proxy, and failed-auth rate limiting.",
    "updatesTabHint": "Configure release channel, startup checks, and automatic update policy.",
    "docsLink": "Gateway documentation",
    "loadError": "Failed to load gateway settings",
    "loading": "Loading…",
    "save": "Save",
    "discard": "Discard",
    "saving": "Saving…",
    "saved": "Saved",
    "saveError": "Failed to save",
    "retry": "Retry",
    "unsavedHint": "You have unsaved changes.",
    "tokenExpired": "Your session token was rejected. Update the client token or fix the access token in config.",
    "updateToken": "Update client token",
    "changeToken": "Open token dialog",
    "accessToken": "Gateway access token",
    "tokenPlaceholder": "Token stored in config (optional if using env)",
    "tokenHelp": "Used to authenticate HTTP/WebSocket API requests. You can also set XOPC_GATEWAY_TOKEN.",
    "copy": "Copy",
    "copied": "Copied",
    "show": "Show",
    "hide": "Hide",
    "listenHost": "Listen address",
    "bindMode": "Bind mode",
    "bindLoopback": "Loopback (127.0.0.1)",
    "bindLan": "LAN (0.0.0.0)",
    "bindAuto": "Auto",
    "bindCustom": "Custom IPv4",
    "bindTailnet": "Tailnet (Tailscale IP)",
    "customBindHost": "Custom bind address",
    "customBindHostPlaceholder": "192.168.1.10",
    "listenPort": "Port",
    "listenHint": "Bind mode controls which network interfaces the gateway listens on. Auto: binds to 0.0.0.0 inside containers, 127.0.0.1 on host machines. Use LAN only with token auth and explicit CORS origins. Restart after saving.",
    "restartHint": "Changes to listen address, authentication, or CORS require a gateway restart.",
    "restartGatewayButton": "Restart Gateway",
    "restartGatewayConfirm": "Restarting the gateway will interrupt all active connections. Continue?",
    "restartGatewayFailed": "Restart failed",
    "authMode": "Authentication mode",
    "authModeToken": "Token",
    "authModePassword": "Password",
    "authModeTrustedProxy": "Trusted proxy",
    "authModeNoneLabel": "None",
    "authModeNone": "Auth mode is set to none — API requests are not authenticated.",
    "authModeTrustedProxyHint": "Reverse proxy handles login and forwards user identity headers. Configure trusted proxy CIDRs and headers below. Restart after saving.",
    "authPassword": "Gateway password",
    "authPasswordPlaceholder": "Password stored in config (optional if using env)",
    "authPasswordHelp": "Used when auth mode is password. You can also set XOPC_GATEWAY_PASSWORD.",
    "rateLimitTitle": "Failed authentication rate limit",
    "rateLimitHint": "Limits repeated failed auth attempts per client IP.",
    "rateLimitEnabled": "Enable rate limiting",
    "rateLimitExemptLoopback": "Exempt loopback clients (127.0.0.1)",
    "rateLimitMaxAttempts": "Max attempts",
    "rateLimitWindowMinutes": "Window (minutes)",
    "rateLimitBlockMinutes": "Block duration (minutes)",
    "updateChannel": "Update channel",
    "channelStable": "Stable",
    "channelBeta": "Beta",
    "channelDev": "Dev",
    "updateChannelHint": "Beta and dev receive builds earlier; stable is recommended for daily use.",
    "updateAutoSection": "Automatic updates",
    "updateAutoSectionHint": "Controls npm/CLI update checks on gateway start and background auto-update scheduling.",
    "updateCheckOnStart": "Check for updates on start",
    "updateCheckOnStartHint": "When enabled, the gateway checks for newer packages when it starts.",
    "updateAutoEnabled": "Enable automatic updates",
    "updateAutoEnabledHint": "When enabled, eligible stable/beta builds may be applied automatically after the delay below.",
    "updateAutoStableDelayHours": "Stable delay (hours)",
    "updateAutoStableDelayHoursHint": "Minimum hours after a stable release before auto-update may run.",
    "updateAutoStableJitterHours": "Stable jitter (hours)",
    "updateAutoStableJitterHoursHint": "Random extra wait up to this many hours to spread update load.",
    "updateAutoBetaCheckIntervalHours": "Beta check interval (hours)",
    "updateAutoBetaCheckIntervalHoursHint": "How often to poll for beta builds when on the beta channel.",
    "corsOrigins": "CORS allowed origins",
    "corsOriginsHint": "Exact browser origins (scheme + host + port), e.g. http://localhost:5173. Leave empty to use built-in localhost defaults. Restart the gateway after saving.",
    "corsOriginsEmpty": "No custom origins — gateway uses localhost defaults for this port and Vite dev (3000).",
    "corsOriginsPlaceholder": "Add origin and press Enter",
    "corsOriginsWildcardWarning": "Wildcard \"*\" allows any website to call the API from a browser. Use only if you understand the risk.",
    "securitySection": "Network security",
    "securitySectionHint": "OpenClaw-aligned guards for LAN and reverse-proxy deployments. Restart after saving.",
    "securityStrict": "Strict security mode",
    "securityStrictHint": "When enabled, network-accessible binds require explicit failed-auth rate limiting configuration.",
    "dangerouslyAllowHostHeaderOriginFallback": "Allow Host-header origin fallback",
    "dangerouslyAllowHostHeaderOriginFallbackHint": "Dangerous: treat the HTTP Host header as an allowed browser origin when not listed in CORS. Prefer explicit corsOrigins.",
    "dangerouslyAllowHostHeaderOriginFallbackWarning": "Host-header fallback weakens browser origin checks. Use only behind a trusted reverse proxy with strict Host validation.",
    "trustedProxies": "Trusted proxy CIDRs",
    "trustedProxiesHint": "IP addresses or CIDR ranges of reverse proxies allowed to terminate trusted-proxy auth (e.g. 127.0.0.1/32, 10.0.0.0/8). Required on network binds.",
    "trustedProxiesEmpty": "No trusted proxies configured.",
    "trustedProxiesPlaceholder": "CIDR or IP and press Enter",
    "allowRealIpFallback": "Allow X-Real-IP fallback",
    "allowRealIpFallbackHint": "When X-Forwarded-For parsing fails, fall back to X-Real-IP. Default is fail-closed (disabled).",
    "trustedProxyUserHeader": "User identity header",
    "trustedProxyUserHeaderPlaceholder": "X-Forwarded-User",
    "trustedProxyUserHeaderHint": "HTTP header set by the reverse proxy with the authenticated user identity.",
    "trustedProxyRequiredHeaders": "Required proxy headers",
    "trustedProxyRequiredHeadersHint": "Additional headers that must be present on every request (e.g. X-Proxy-Auth).",
    "trustedProxyAllowUsers": "Allowed users",
    "trustedProxyAllowUsersHint": "When non-empty, only these user identities are accepted. Leave empty to allow any non-empty user header value.",
    "trustedProxyAllowLoopback": "Allow loopback proxy source",
    "trustedProxyAllowLoopbackHint": "Accept trusted-proxy auth when the TCP connection comes from 127.0.0.1 (same-host reverse proxy).",
    "validationErrorNetworkAuth": "Network-accessible gateway requires authentication.",
    "validationErrorTrustedProxies": "Trusted-proxy auth requires at least one trusted proxy CIDR on network binds.",
    "validationErrorUserHeader": "Trusted-proxy auth requires a user identity header name.",
    "validationErrorCors": "Network-accessible gateway requires CORS origins or Host-header fallback.",
    "validationErrorCorsWildcard": "CORS wildcard is not allowed on network binds.",
    "validationErrorCustomBind": "Custom bind mode requires a bind address.",
    "securityAuditTitle": "Security audit",
    "securityAuditSubtitle": "Live check of saved gateway configuration (same as xopc doctor --security).",
    "securityAuditSavedConfigHint": "Reflects the config file on disk. Save form changes and restart the gateway to update results.",
    "securityAuditRefresh": "Refresh",
    "securityAuditLoading": "Running security audit…",
    "securityAuditLoadError": "Security audit failed",
    "securityAuditStatusPass": "No critical issues",
    "securityAuditStatusWarn": "Recommendations",
    "securityAuditStatusFail": "Critical issues",
    "securityAuditStatusSkip": "Audit skipped",
    "securityAuditNoFindings": "No structured findings; configuration passes gateway security guards.",
    "securityAuditHintsTitle": "Additional notes",
    "securityAuditRemediation": "Fix:",
    "advancedSection": "Advanced",
    "advancedSectionHint": "Runtime limits and channel startup ordering. Restart the gateway after saving.",
    "maxSseConnections": "Max SSE connections",
    "maxSseConnectionsHint": "Upper bound for concurrent Server-Sent Events clients (`GET /api/events` and similar). Default 100.",
    "channelConnectDeferMode": "Channel connect defer",
    "channelConnectDeferModeAuto": "Auto (plugin default)",
    "channelConnectDeferModeOff": "Off (start all channels before listen)",
    "channelConnectDeferModeExplicit": "Explicit list",
    "channelConnectDeferModeHint": "Controls when outbound-heavy channels call `start()` relative to HTTP listen. Auto defers plugins that opt in (e.g. Telegram, Weixin, Feishu).",
    "channelConnectDeferIds": "Defer channel ids",
    "channelConnectDeferIdsHint": "Used when mode is Explicit. These plugin ids start after HTTP listen (max 24). Empty means defer none.",
    "channelConnectDeferSkipIds": "Skip defer ids",
    "channelConnectDeferSkipIdsHint": "Removed from the defer set after auto or explicit resolution (max 24). Example: keep Telegram on phase 1 but defer others.",
    "channelIdListPlaceholder": "Channel id and press Enter (e.g. telegram)",
    "channelIdListEmpty": "No ids configured."
  },
  "heartbeatSettings": {
    "needToken": "Save a gateway token to load and edit heartbeat options.",
    "subtitle": "Periodic agent wake, optional delivery to a channel, and HEARTBEAT.md under the default agent's profile directory. Stored in the gateway config file and agents/<id>/profile/.",
    "docsLink": "Heartbeat documentation",
    "loadError": "Failed to load heartbeat settings",
    "loading": "Loading…",
    "saveConfig": "Save",
    "discard": "Discard",
    "savingConfig": "Saving…",
    "savedConfig": "Configuration saved",
    "saveConfigError": "Failed to save configuration",
    "triggerNow": "Run now",
    "triggering": "Queuing…",
    "triggered": "Heartbeat queued",
    "triggerError": "Failed to trigger heartbeat",
    "triggerHint": "Queues one heartbeat run (same as the timer). Skipped if HEARTBEAT.md is empty, outside active hours, or heartbeat is disabled.",
    "saveDoc": "Save",
    "savingDoc": "Saving…",
    "savedDoc": "Document saved",
    "saveDocError": "Failed to save HEARTBEAT.md",
    "retry": "Retry",
    "unsavedConfig": "You have unsaved configuration changes.",
    "unsavedDoc": "You have unsaved changes to HEARTBEAT.md.",
    "workspaceLabel": "Workspace",
    "tabsAriaLabel": "Heartbeat settings categories",
    "tabSchedule": "Schedule",
    "tabDelivery": "Delivery",
    "tabPrompt": "Prompt",
    "tabDocument": "HEARTBEAT.md",
    "scheduleTabHint": "Control whether heartbeat runs, how often it runs, and active hours.",
    "deliveryTabHint": "Choose the channel and conversation to deliver replies to; leave empty to only log them.",
    "promptTabHint": "Tune the heartbeat system prompt, silent-reply threshold, and session isolation.",
    "documentTabHint": "Maintain the tasks and reminders read on each heartbeat.",
    "configSection": "Heartbeat configuration",
    "docSection": "HEARTBEAT.md",
    "docHint": "Tasks and reminders read by the agent on each heartbeat. Leave empty or comment-only to skip LLM calls and save tokens.",
    "enable": "Enable heartbeat",
    "includeSystemPromptSection": "Include heartbeat instructions in chat system prompt",
    "includeSystemPromptSectionHint": "When off, heartbeat instructions are only sent during scheduled heartbeat turns (saves tokens in normal chat).",
    "interval": "Interval",
    "intervalHint": "Minimum 1 second. Saved to the gateway as milliseconds.",
    "intervalHintPreset": "Quick preset or type seconds in the field.",
    "intervalSecondsLabel": "Seconds",
    "intervalPresets": {
      "custom": "Custom",
      "every30s": "Every 30 seconds",
      "every1min": "Every 1 minute",
      "every5min": "Every 5 minutes",
      "every10min": "Every 10 minutes",
      "every15min": "Every 15 minutes",
      "every30min": "Every 30 minutes",
      "every1h": "Every 1 hour",
      "every2h": "Every 2 hours"
    },
    "deliveryTitle": "Delivery (optional)",
    "channelNone": "— None —",
    "customChannelSuffix": "custom",
    "deliveryHint": "Both channel and chat id are required to send non-silent replies somewhere. Otherwise the reply is only logged.",
    "prompt": "Custom system prompt (optional)",
    "promptPlaceholder": "Override the default heartbeat instruction…",
    "promptHint": "Leave empty to use the built-in default prompt.",
    "ackMaxChars": "Max reply length before treating as silent (ackMaxChars)",
    "ackMaxCharsHint": "Leave empty for server default (300).",
    "ackDefaultPlaceholder": "Default",
    "isolatedSession": "Use a fresh session key each run",
    "isolatedSessionHint": "Avoids mixing heartbeat context with the main chat session.",
    "activeHoursTitle": "Active hours (optional)",
    "activeStart": "Start",
    "activeEnd": "End",
    "activeTimezone": "Timezone (IANA)",
    "activeHoursHint": "Restrict heartbeats to this window. Clear to run any time.",
    "addActiveHours": "Add active hours",
    "clearActiveHours": "Clear active hours"
  },
  "webSearchSettings": {
    "title": "Web search",
    "subtitle": "Configure region and search providers for the web_search tool. Without API keys, a built-in HTML fallback is used.",
    "docsLink": "Gateway documentation",
    "needToken": "Save a gateway token to edit web search settings.",
    "loading": "Loading…",
    "loadError": "Failed to load web search settings",
    "save": "Save",
    "discard": "Discard",
    "saving": "Saving…",
    "saved": "Saved",
    "saveError": "Failed to save",
    "unsavedHint": "You have unsaved changes.",
    "sectionRegion": "Region",
    "sectionRegionHint": "Controls which zero-config HTML fallback is used when no API provider succeeds (China → Bing; otherwise DuckDuckGo).",
    "sectionSearch": "Search providers",
    "sectionSearchHint": "Providers are tried in order. Keys are stored in the gateway config file. Leave the list empty to use only the HTML fallback.",
    "sectionBlocklist": "Domain blocklist",
    "sectionBlocklistHint": "When enabled, web_search and web_extract skip URLs whose host matches these domains (exact or suffix match).",
    "blocklistEnabled": "Enable domain blocklist",
    "blocklistEnabledDesc": "Blocks matching hosts before fetch; useful for privacy or compliance.",
    "blocklistDomains": "Blocked domains",
    "blocklistDomainsDesc": "One domain per line (e.g. example.com). Subdomains of listed domains are also blocked.",
    "blocklistDomainsPlaceholder": "example.com\nads.example.net",
    "regionLabel": "Fallback region",
    "regionDesc": "Auto uses your system timezone. Override if you are on a VPN or need a specific fallback.",
    "regionAuto": "Auto (timezone)",
    "regionCn": "China (Bing HTML fallback)",
    "regionGlobal": "Global (DuckDuckGo HTML fallback)",
    "maxResultsLabel": "Default max results",
    "maxResultsDesc": "Used when the model does not pass a count (1–50).",
    "providersTitle": "Providers (ordered)",
    "addProvider": "Add provider",
    "apiKeyLabel": "API key",
    "apiKeyDesc": "Optional for some setups. Leave masked to keep the saved value.",
    "urlLabel": "Instance URL",
    "urlDesc": "SearXNG base URL (e.g. http://localhost:8080). No trailing slash required.",
    "keyPlaceholder": "API key or env var name",
    "keyPlaceholderMasked": "•••••••• (unchanged)",
    "disabled": "Skip",
    "footerHint": "HTML fallbacks depend on third-party pages and may change. For production, use a supported search API (Brave, Tavily, Bing, or self-hosted SearXNG).",
    "providerTypes": {
      "brave": "Brave Search API",
      "tavily": "Tavily",
      "bing": "Bing Web Search API",
      "searxng": "SearXNG"
    }
  }
}
