Files
hermes-webui/static/i18n.js
T
Nathan Esquenazi 397d851bdb feat(kanban): multi-board management + SSE live event stream
Closes the remaining gaps to first-party Hermes Agent dashboard parity:
multi-board CRUD on /api/kanban/boards and a real-time event stream over
Server-Sent Events. Builds on top of #1660 (review-feedback hardening).

== Multi-board ==

Five new endpoints mirror the agent dashboard plugin contract verbatim
(plugins/kanban/dashboard/plugin_api.py) so a single CLI / gateway slash
command / dashboard / WebUI all share the same active-board pointer:

  GET    /api/kanban/boards
  POST   /api/kanban/boards
  PATCH  /api/kanban/boards/<slug>
  DELETE /api/kanban/boards/<slug>
  POST   /api/kanban/boards/<slug>/switch

All existing endpoints accept ?board=<slug> (and writes also accept
'board' in the JSON body) — query takes precedence over body. The slug
travels through the kanban_db library which already had multi-board
support; the bridge is mostly thin wrappers around create_board /
remove_board / list_boards / set_current_board / get_current_board.

The default board is protected from deletion. Slugs are normalised
through kb._normalize_board_slug() with path-traversal rejection.
Archive is the default for DELETE; ?delete=1 hard-deletes.

Frontend gets a 'Default ▾' switcher pill in the panel header. The menu
lists every board (current first), per-status total badges, plus three
actions (New / Rename / Archive). Create + rename use the same modal
with a slug auto-derived from the name. Archive routes through the
existing showConfirmDialog with a clear 'tasks remain on disk and the
board can be restored from kanban/boards/_archived/' message.

Active-board state is persisted to localStorage so a refresh stays put.
The on-disk pointer in kanban/current is the cross-process source of
truth, kept in sync via POST /boards/<slug>/switch.

== SSE event stream ==

GET /api/kanban/events/stream is a long-lived Server-Sent Events feed
that mirrors the agent dashboard's WebSocket /events contract. The
WebUI uses SSE rather than WebSocket because (1) the existing transport
is BaseHTTPServer, not async — WS would require a significant refactor
or a hijack-the-socket hack; (2) SSE is the right tool for unidirectional
server-pushed event streams; (3) browsers auto-reconnect on drop;
(4) the existing /api/approval/stream and /api/clarify/stream patterns
are proven and easy to copy.

The handler polls task_events at 300ms (matching the agent dashboard's
WebSocket poll cadence) so write-to-receive latency is identical.
Heartbeats every 15s prevent proxy/CDN reaping. Hard cap of 200 events
per batch.

Frontend uses EventSource by default and falls back to 30s HTTP polling
after 3 SSE failures. A 250ms debounce coalesces bursts of N events
into a single board re-fetch. Stream is torn down when the user leaves
the Kanban panel.

== Bugs fixed during build ==

(1) read_only=True legacy lie. _board_payload, _events_payload,
    _task_log_payload, and the no-change short-circuit all hardcoded
    read_only=True from the read-only-bridge era of #1645. Bridge has
    been writable since #1649 — flag now matches reality.

(2) Modal + dropdown menu transparent backgrounds. The PR stack used
    var(--panel) which is undefined in the WebUI design system (uses
    --surface, --bg, gradient panels). Replaced with the same gradient
    + accent border pattern used by the .app-dialog overlay.

(3) Archive race. kb.connect(board=<slug>) auto-materialises the
    directory + sqlite on first call, so any in-flight SSE poll on a
    board mid-archive would silently un-archive it by re-creating the
    directory. Two-layer fix: (a) frontend stops the SSE stream BEFORE
    the DELETE call, restarts on failure; (b) bridge's _kanban_sse_fetch_new
    checks kb.board_exists() before connect(), returning empty results
    when the board is gone.

(4) Save vs. Cancel button visual hierarchy. Both rendered as identical
    secondary buttons in the modal. Save now uses the .primary class
    with accent-tinted gold styling.

(5) Mobile viewport gaps. Added 9 rules under @media (max-width: 640px)
    covering the switcher button (smaller padding/font), name truncation
    (max-width:140px), menu sizing (min(280px, 100vw - 24px)), modal
    padding, and inline-row stacking.

== Tests ==

+45 new tests across two files. Bridge tests: 18 covering board CRUD
endpoints, slug validation, default-board protection, dispatcher routing,
board isolation (verified via connect() spy), and 3 SSE tests including
a worker-thread integration test with threading.Event watchdog. UI static
tests: 11 covering switcher markup, modal markup, JS handler presence,
REST verb usage, board-param plumbing, localStorage persistence,
showConfirmDialog usage, EventSource subscription, polling fallback,
panel-switch teardown, and 250ms debouncing.

Bridge tests: 18 → 36 (+18 multi-board, +3 SSE)
UI static tests: 15 → 26 (+11)
Total kanban: 33 → 63

Full repo test suite: 4351 passed, 0 regressions.

== Live verification ==

End-to-end browser walkthrough on port 8789:
- Create Sprint 12 + Backlog via modal: switcher updates ✓
- Switch between boards: count isolation correct ✓
- Add task on Sprint 12 via API: SSE delivers in 400ms ✓
- 5-task burst: 250ms debounce coalesces to single render ✓
- Rename board via modal: switcher label updates ✓
- Archive board: confirm dialog → board moved to _archived/, no zombie
  directory (race fix verified) ✓
- Zero JS errors throughout 11-step flow

Co-authored-by: ai-ag2026 <ai-ag2026@users.noreply.github.com>
2026-05-05 00:18:36 +00:00

8329 lines
482 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// ── i18n: locale bundles and t() helper ──────────────────────────────────────
// To add a new language: add an entry to LOCALES below with all keys translated.
// The language code must match a valid BCP 47 tag (used for speech recognition).
// Keys missing in a non-English locale fall back to English automatically.
const LOCALES = {
en: {
_lang: 'en',
_label: 'English',
_speech: 'en-US',
// boot.js
cancelling: 'Cancelling\u2026',
cancel_failed: 'Cancel failed: ',
mic_denied: 'Microphone access denied. Check browser permissions.',
mic_no_speech: 'No speech detected. Try again.',
mic_network: 'Speech recognition unavailable.',
mic_error: 'Voice input error: ',
// Composer voice buttons (#1488 — distinct labels for dictation vs voice mode)
voice_dictate: 'Dictate',
voice_dictate_active: 'Stop dictation',
voice_mode_toggle: 'Voice mode',
voice_mode_toggle_active: 'Exit voice mode',
// Turn-based voice mode (#1333)
voice_listening: 'Listening…',
voice_speaking: 'Speaking…',
voice_thinking: 'Thinking…',
voice_error: 'Voice not supported in this browser',
voice_mode_active: 'Voice mode on',
voice_mode_off: 'Voice mode off',
session_imported: 'Session imported',
import_failed: 'Import failed: ',
import_invalid_json: 'Invalid JSON',
image_pasted: 'Image pasted: ',
// messages.js
edit_message: 'Edit message',
regenerate: 'Regenerate response',
copy: 'Copy',
copied: 'Copied!',
copy_failed: 'Copy failed',
diff_loading: 'Loading diff',
diff_error: 'Could not load patch file',
diff_too_large: 'Patch file too large to display inline',
tree_view: 'Tree',
raw_view: 'Raw',
parse_failed_note: 'parse failed',
you: 'You',
mcp_servers_title: 'MCP Servers',
mcp_servers_desc: 'Manage MCP servers configured in config.yaml.',
mcp_no_servers: 'No MCP servers configured.',
mcp_add_server: '+ Add Server',
mcp_field_name: 'Server Name',
mcp_transport_label: 'Transport Type',
mcp_field_command: 'Command',
mcp_field_args: 'Arguments (comma-separated)',
mcp_field_url: 'URL',
mcp_field_timeout: 'Timeout (seconds)',
mcp_save: 'Save',
mcp_cancel: 'Cancel',
mcp_name_required: 'Server name is required.',
mcp_url_required: 'URL is required for HTTP transport.',
mcp_command_required: 'Command is required for stdio transport.',
mcp_saved: 'MCP server saved.',
mcp_save_failed: 'Failed to save MCP server.',
mcp_delete_confirm_title: 'Delete MCP Server',
mcp_delete_confirm_message: 'Delete MCP server "{0}"? This action cannot be undone.',
mcp_deleted: 'MCP server deleted.',
mcp_delete_failed: 'Failed to delete MCP server.',
mcp_load_failed: 'Failed to load MCP servers.',
// PDF preview (#480)
pdf_loading: 'Loading PDF {0}…',
pdf_too_large: 'PDF too large for inline preview',
pdf_no_pages: 'PDF has no pages',
pdf_error: 'Failed to render PDF preview',
pdf_download: 'Download PDF',
// HTML sandbox preview (#482)
html_loading: 'Loading HTML preview…',
html_too_large: 'HTML too large for inline preview',
html_error: 'Failed to render HTML preview',
html_open_full: 'Open full page',
html_sandbox_label: 'HTML Preview (sandboxed)',
thinking: 'Thinking',
expand_all: 'Expand all',
collapse_all: 'Collapse all',
edit_failed: 'Edit failed: ',
regen_failed: 'Regenerate failed: ',
reconnect_active: 'A response is still being generated. Reload when ready?',
reconnect_finished: 'A response was in progress when you last left. Messages may have updated.',
// approval card
approval_heading: 'Approval required',
approval_desc_prefix: 'Dangerous command detected',
approval_btn_once: 'Allow once',
approval_btn_once_title: 'Allow this one command (Enter)',
approval_btn_session: 'Allow session',
approval_btn_session_title: 'Allow for this conversation session',
approval_btn_always: 'Always allow',
approval_btn_always_title: 'Always allow this command pattern',
approval_btn_deny: 'Deny',
approval_btn_deny_title: 'Deny — do not run this command',
approval_responding: 'Responding\u2026',
clarify_heading: 'Clarification needed',
clarify_hint: 'Pick a choice, or type your own answer below.',
clarify_other: 'Other',
clarify_send: 'Send',
clarify_input_placeholder: 'Type your response…',
clarify_responding: 'Responding\u2026',
untitled: 'Untitled',
n_messages: (n) => `${n} messages`,
load_older_messages: '↑ Scroll up or click to load older messages',
queued_label: 'Sends after response',
queued_count: (n) => n === 1 ? '1 queued' : `${n} queued`,
queued_cancel: 'Cancel queued message',
model_unavailable: ' (unavailable)',
model_unavailable_title: 'This model is no longer in your current provider list',
provider_mismatch_warning: (m,p)=>`"${m}" may not work with your configured provider (${p}). Send anyway, or run \`hermes model\` in your terminal to switch.`,
provider_mismatch_label: 'Provider mismatch',
model_not_found_label: 'Model not found',
model_custom_label: 'Custom model ID',
model_custom_placeholder: 'e.g. openai/gpt-5.4',
model_search_placeholder: 'Search models…',
model_search_no_results: 'No models found',
model_group_configured: 'Configured',
ws_search_placeholder: 'Search workspaces…',
ws_no_results: 'No workspaces found',
model_scope_advisory: 'Applies to this conversation from your next message.',
model_scope_toast: 'Applies to this conversation from your next message.',
// commands.js
cmd_clear: 'Clear conversation messages',
cmd_compress: 'Manually compress conversation context (usage: /compress [focus topic])',
ctx_compress_hint: 'Compress context to free up space →',
ctx_compress_action: '⚠ Compress now to free context',
cmd_compact_alias: 'Legacy alias for /compress',
cmd_model: 'Switch model (e.g. /model gpt-4o)',
cmd_workspace: 'Switch workspace by name',
cmd_terminal: 'Open the workspace terminal',
cmd_new: 'Start a new chat session',
cmd_usage: 'Toggle token usage display on/off',
cmd_theme: 'Switch appearance (theme: system/dark/light, skin: default/ares/mono/slate/poseidon/sisyphus/charizard)',
cmd_personality: 'Switch agent personality',
cmd_skills: 'List available Hermes skills',
available_commands: 'Available commands:',
type_slash: 'Type / to see commands',
conversation_cleared: 'Conversation cleared',
command_label: 'Command',
context_compaction_label: 'Context compaction',
preserved_task_list_label: 'Preserved task list',
reference_only_label: 'Reference only',
model_usage: 'Usage: /model <name>',
no_model_match: 'No model matching "',
switched_to: 'Switched to ',
workspace_usage: 'Usage: /workspace <name>',
no_workspace_match: 'No workspace matching "',
switched_workspace: 'Switched to workspace: ',
workspace_switch_failed: 'Workspace switch failed: ',
new_session: 'New session created',
compressing: 'Requesting context compression...',
compress_running_label: 'Compressing',
compress_complete_label: 'Compression complete',
auto_compress_label: 'Automatic compression',
compress_failed_label: 'Compression failed',
focus_label: 'Focus',
token_usage_on: 'Token usage on',
token_usage_off: 'Token usage off',
theme_usage: 'Usage: /theme ',
theme_set: 'Theme: ',
no_active_session: 'No active session',
cmd_queue: 'Queue a message for the next turn',
cmd_interrupt: 'Cancel current turn and send a new message',
cmd_steer: 'Inject a mid-turn correction without interrupting the agent',
cmd_queue_no_msg: 'Usage: /queue <message>',
cmd_queue_not_busy: 'No active task — just send normally',
cmd_queue_confirm: 'Message queued',
cmd_interrupt_no_msg: 'Usage: /interrupt <message>',
cmd_interrupt_confirm: 'Interrupted — sending new message',
cmd_steer_no_msg: 'Usage: /steer <message>',
cmd_steer_fallback: 'Steer unavailable — queued for next turn instead',
cmd_steer_delivered: 'Steer delivered — agent will see it on its next tool result',
steer_leftover_queued: 'Steer queued for next turn',
busy_steer_fallback: 'Steer unavailable — queued for next turn',
busy_interrupt_confirm: 'Interrupted — sending new message',
settings_label_busy_input_mode: 'Busy input mode',
settings_desc_busy_input_mode: 'Controls what happens when you send a message while the agent is running. Queue waits; Interrupt cancels and starts fresh; Steer injects a correction mid-turn without interrupting (falls back to queue when agent or stream unavailable).',
settings_busy_input_mode_queue: 'Queue follow-up',
settings_busy_input_mode_interrupt: 'Interrupt current turn',
settings_busy_input_mode_steer: 'Steer (mid-turn correction)',
slash_skill_badge:'Skill',
slash_skill_desc:'Invoke this skill',
cmd_stop:'Stop the current response',
cmd_title:'Get or set the session title',
cmd_retry:'Resend the last message',
cmd_undo:'Remove the last exchange',
cmd_btw:'Ask a side question (ephemeral)',
cmd_btw_usage:'/btw <question> — ask a side question using session context',
cmd_background:'Run a prompt in background',
cmd_background_usage:'/background <prompt> — run in parallel without blocking',
cmd_branch:'Fork this conversation into a new session',
cmd_branch_usage:'/branch [name] — fork conversation (optionally with a name)',
branch_forked:'Forked into new session',
branch_failed:'Fork failed: ',
fork_from_here:'Fork from here',
forked_from:'Forked from',
subagent_children:'Subagent sessions',
btw_asking:'Asking side question...',
btw_label:'Side question — not in history',
btw_done:'Side question answered',
btw_no_answer:'No answer received.',
btw_failed:'Side question failed: ',
bg_running:'Running in background...',
bg_complete:'Background task complete',
bg_label:'Background result:',
bg_no_answer:'(no answer)',
bg_failed:'Background task failed: ',
undo_exchange:'Undo last exchange',
cmd_status:'Show session info',
cmd_voice:'Toggle microphone input',
stream_stopped:'Response stopped.',
no_active_task:'No active task to stop.',
cancel_unavailable:'Cancel not available.',
retry_failed:'Retry failed: ',
undo_failed:'Undo failed: ',
undid_n_messages:'Removed',
undid_messages_suffix:'message(s).',
status_heading:'Session Status',
status_session_id:'Session ID',
status_title:'Title',
status_model:'Model',
status_workspace:'Workspace',
status_personality:'Personality',
status_messages:'Messages',
status_agent_running:'Agent running',
status_profile: 'Profile',
status_hermes_home: 'Hermes home',
status_started: 'Started',
status_tokens: 'Tokens',
status_no_tokens: 'No tokens used',
status_unknown: 'Unknown',
status_yes:'Yes',
status_no:'No',
status_load_failed:'Failed to load status: ',
title_current:'Current title',
title_change_hint:'Use `/title <new name>` to rename.',
title_set:'Title set to',
cmd_webui_only_session:'This command is not available for CLI-imported sessions.',
cmd_voice_use_mic:'Click the mic button in the composer.',
usage_heading:'Token Usage',
usage_default_model:'default',
usage_unknown:'unknown',
usage_input_tokens:'Input tokens',
usage_output_tokens:'Output tokens',
usage_total:'Total tokens',
usage_estimated_cost:'Estimated cost',
usage_settings_tip:'Note: cost estimates are approximate.',
usage_load_failed:'Failed to load usage: ',
usage_personality_none:'none',
// Session toolsets (#493)
session_toolsets:'Session Toolsets',
session_toolsets_desc:'Restrict available tools for this session (blank = use global config)',
session_toolsets_global:'Global (default)',
session_toolsets_custom:'Custom',
session_toolsets_placeholder:'tool1, tool2, …',
session_toolsets_apply:'Apply',
session_toolsets_clear:'Clear (use global)',
session_toolsets_applied:'Toolsets updated',
session_toolsets_cleared:'Toolsets cleared — using global config',
session_toolsets_failed:'Failed to update toolsets: ',
untitled:'Untitled',
no_personalities: 'No personalities found (add them to ~/.hermes/personalities/)',
available_personalities: 'Available personalities:',
personality_switch_hint: '\n\nUse `/personality <name>` to switch, or `/personality none` to clear.',
personalities_load_failed: 'Failed to load personalities',
personality_cleared: 'Personality cleared',
personality_set: 'Personality: ',
failed_colon: 'Failed: ',
// ui.js
no_workspace: 'No workspace',
terminal_open_title: 'Open workspace terminal',
terminal_no_workspace_title: 'Select a workspace to open terminal',
terminal_title: 'Terminal',
terminal_clear: 'Clear',
terminal_copy_output: 'Copy output',
terminal_restart: 'Restart',
terminal_collapse: 'Collapse',
terminal_expand: 'Expand',
terminal_close: 'Close',
terminal_input_placeholder: 'Run a command...',
terminal_start_failed: 'Terminal start failed: ',
terminal_input_failed: 'Terminal input failed: ',
terminal_copy_failed: 'Copy failed: ',
terminal_error: 'Terminal error',
workspace_empty_no_path: 'No workspace selected. Set a workspace in Settings \u2192 Workspace to browse files.',
workspace_empty_dir: 'This workspace is empty.',
dialog_confirm_title: 'Confirm action',
dialog_prompt_title: 'Enter a value',
dialog_confirm_btn: 'Confirm',
// workspace.js
unsaved_confirm: 'You have unsaved changes in the preview. Discard and navigate?',
discard: 'Discard',
save: 'Save',
edit: 'Edit',
clear: 'Clear',
create: 'Create',
remove: 'Remove',
save_title: 'Save changes',
edit_title: 'Edit this file',
saved: 'Saved',
save_failed: 'Save failed: ',
image_load_failed: 'Could not load image',
file_open_failed: 'Could not open file',
downloading: (name) => `Downloading ${name}\u2026`,
double_click_rename: 'Double-click to rename',
renamed_to: 'Renamed to ',
rename_failed: 'Rename failed: ',
delete_title: 'Delete',
delete_confirm: (name) => `Delete ${name}?`,
delete_dir_confirm: (name) => `Delete folder "${name}" and all its contents?`,
rename_title: 'Rename',
rename_prompt: 'New name:',
deleted: 'Deleted ',
delete_failed: 'Delete failed: ',
reveal_in_finder: 'Reveal in File Manager',
reveal_failed: 'Failed to reveal: ',
new_file_prompt: 'New file name (e.g. notes.md):',
project_name_prompt: 'Project name:',
created: 'Created ',
create_failed: 'Create failed: ',
new_folder_prompt: 'New folder name:',
folder_created: 'Created folder ',
folder_create_failed: 'Create folder failed: ',
workspace_auto_create_folder: 'Create folder if it doesn\'t exist',
folder_add_as_space_btn: 'Add as Space',
folder_add_as_space_msg: 'Add this folder as a new space in your workspace list?',
folder_add_as_space_title: 'Add as Space?',
remove_title: 'Remove',
empty_dir: '(empty)',
upload_failed: 'Upload failed: ',
all_uploads_failed: (n) => `All ${n} upload(s) failed`,
archive_extracted: (n, c) => `Extracted ${n} file(s) from ${c} archive(s)`,
session_pin: 'Pin conversation',
session_unpin: 'Unpin conversation',
session_pin_desc: 'Keep this conversation at the top',
session_unpin_desc: 'Remove from pinned',
session_pin_failed: 'Pin failed: ',
session_move_project: 'Move to project',
session_move_project_desc_has: 'Change the project for this conversation',
session_move_project_desc_none: 'Assign a project to this conversation',
session_archive: 'Archive conversation',
session_restore: 'Restore conversation',
session_archive_desc: 'Hide this conversation until archived is shown',
session_restore_desc: 'Bring this conversation back into the main list',
session_archived: 'Session archived',
session_restored: 'Session restored',
session_archive_failed: 'Archive failed: ',
session_duplicate: 'Duplicate conversation',
session_duplicate_desc: 'Create a copy with the same workspace and model',
session_duplicated: 'Session duplicated',
session_duplicate_failed: 'Duplicate failed: ',
session_stop_response: 'Stop response',
session_stop_response_desc: 'Cancel the running response for this conversation',
session_delete: 'Delete conversation',
session_delete_desc: 'Permanently remove this conversation',
session_select_mode: 'Select',
session_select_mode_desc: 'Select conversations to batch manage',
session_select_all: 'Select all',
session_deselect_all: 'Deselect all',
session_selected_count: '{0} selected',
session_batch_archive: 'Archive',
session_batch_delete: 'Delete',
session_batch_move: 'Move to project',
session_batch_delete_confirm: 'Delete {0} conversations?',
session_batch_archive_confirm: 'Archive {0} conversations?',
session_no_selection: 'No conversations selected',
// settings panel
settings_heading_title: 'Control Center',
settings_heading_subtitle: 'Preferences, conversation tools, and system controls.',
settings_section_conversation_title: 'Conversation',
settings_section_appearance_title: 'Appearance',
settings_section_appearance_meta: 'Theme, accent colors, and visual style.',
settings_section_preferences_title: 'Preferences',
settings_section_preferences_meta: 'Defaults and UI behavior for Hermes Web UI.',
settings_section_system_title: 'System',
settings_section_system_meta: 'Instance version and access controls.',
settings_check_now: 'Check now',
settings_checking: 'Checking\u2026',
settings_up_to_date: 'Up to date \u2713',
settings_updates_available: '{count} update(s) available',
settings_updates_disabled: 'Update checks disabled',
settings_update_check_failed: 'Update check failed',
settings_label_workspace_panel_open: 'Keep workspace panel open by default',
settings_desc_workspace_panel_open: 'When enabled, the workspace / file browser panel opens automatically with each new session. You can still close it manually at any time.',
open_in_browser: 'Open in browser',
settings_dropdown_conversation: 'Conversation',
settings_dropdown_appearance: 'Appearance',
settings_dropdown_preferences: 'Preferences',
settings_dropdown_providers: 'Providers',
settings_dropdown_system: 'System',
settings_tab_conversation: 'Conversation',
settings_tab_appearance: 'Appearance',
settings_tab_preferences: 'Preferences',
settings_tab_system: 'System',
settings_title: 'Settings',
settings_save_btn: 'Save Settings',
settings_label_model: 'Default Model',
settings_desc_model: 'Used for new conversations. Existing conversations keep their selected model.',
settings_label_send_key: 'Send Key',
settings_label_theme: 'Theme',
settings_label_skin: 'Skin',
settings_label_font_size: 'Font size',
font_size_small: 'Small',
font_size_default: 'Default',
font_size_large: 'Large',
settings_autosave_saving: 'Saving…',
settings_autosave_saved: 'Saved',
settings_autosave_failed: 'Save failed',
settings_autosave_retry: 'Retry',
settings_label_language: 'Language',
settings_label_token_usage: 'Show token usage',
settings_label_sidebar_density: 'Sidebar density',
cmd_reasoning: 'Toggle thinking visibility (show/hide), set effort level, or check current status',
settings_label_external_sessions: 'Show non-WebUI sessions',
settings_label_sync_insights: 'Sync to insights',
settings_label_check_updates: 'Check for updates',
settings_label_bot_name: 'Assistant Name',
settings_label_password: 'Access Password',
settings_saved: 'Settings saved',
settings_save_failed: 'Save failed: ',
settings_load_failed: 'Failed to load settings: ',
settings_saved_pw: 'Settings saved — password protection enabled and this browser stays signed in',
settings_saved_pw_updated: 'Settings saved — password updated',
// login page (used server-side via /api/i18n/login endpoint)
login_title: 'Sign in',
login_subtitle: 'Enter your password to continue',
login_placeholder: 'Password',
login_btn: 'Sign in',
login_invalid_pw: 'Invalid password',
login_conn_failed: 'Connection failed',
dialog_confirm_title: 'Confirm action',
dialog_prompt_title: 'Enter a value',
dialog_confirm_btn: 'Confirm',
discard: 'Discard',
clear: 'Clear',
create: 'Create',
remove: 'Remove',
project_name_prompt: 'Project name:',
// Sidebar & Tabs
tab_chat: 'Chat',
tab_tasks: 'Tasks',
tab_skills: 'Skills',
tab_memory: 'Memory',
tab_workspaces: 'Spaces',
tab_profiles: 'Profiles',
tab_kanban: 'Kanban',
kanban_board: 'Board',
kanban_visible_tasks: '{0} visible tasks',
kanban_search_tasks: 'Search tasks',
kanban_all_assignees: 'All assignees',
kanban_all_tenants: 'All tenants',
kanban_include_archived: 'Include archived',
kanban_no_matching_tasks: 'No matching tasks',
kanban_no_data: 'No Kanban data',
kanban_unavailable: 'Kanban unavailable',
kanban_read_only: 'Read-only view',
kanban_empty: 'Empty',
kanban_task: 'Task',
kanban_no_description: 'No description',
kanban_refresh: 'Refresh',
kanban_status_triage: 'Triage',
kanban_status_todo: 'Todo',
kanban_status_ready: 'Ready',
kanban_status_running: 'Running',
kanban_status_blocked: 'Blocked',
kanban_status_done: 'Done',
kanban_comments_count: 'Comments ({0})',
kanban_events_count: 'Events ({0})',
kanban_links: 'Links',
kanban_parents: 'Parents',
kanban_children: 'Children',
kanban_runs_count: 'Runs ({0})',
kanban_no_comments: 'No comments',
kanban_no_events: 'No events',
kanban_no_runs: 'No runs',
kanban_new_task: 'New task',
kanban_add_comment: 'Add comment',
kanban_only_mine: 'Only mine',
kanban_bulk_action: 'Bulk action',
kanban_nudge_dispatcher: 'Nudge dispatcher',
kanban_stats: 'Stats',
kanban_worker_log: 'Worker log',
kanban_block: 'Block',
kanban_unblock: 'Unblock',
kanban_back_to_board: 'Back to board',
kanban_lanes_by_profile: 'Lanes by profile',
kanban_new_board: 'New board…',
kanban_rename_board: 'Rename current board…',
kanban_archive_board: 'Archive current board…',
kanban_archive_board_confirm: 'Archive board "{name}"? Tasks remain on disk and the board can be restored from kanban/boards/_archived/.',
kanban_board_archived: 'Board archived',
kanban_board_name: 'Name',
kanban_board_slug: 'Slug (lowercase, hyphens)',
kanban_board_description: 'Description (optional)',
kanban_board_icon: 'Icon (emoji, optional)',
kanban_board_color: 'Color (optional)',
kanban_board_name_required: 'Name is required',
kanban_board_slug_required: 'Slug is required',
kanban_card_start: 'start',
kanban_card_complete: 'complete',
kanban_card_archive: 'archive',
kanban_unassigned: 'unassigned',
kanban_status_archived: 'Archived',
tab_todos: 'Todos',
tab_insights: 'Insights',
tab_settings: 'Settings',
new_conversation: 'New conversation',
filter_conversations: 'Filter conversations...',
session_time_unknown: 'Unknown',
session_time_minutes_ago: (n) => `${n}m`,
session_time_hours_ago: (n) => `${n}h`,
session_time_days_ago: (n) => `${n}d`,
session_time_last_week: '1w',
session_time_bucket_today: 'Today',
session_time_bucket_yesterday: 'Yesterday',
session_time_bucket_this_week: 'This week',
session_time_bucket_last_week: 'Last week',
session_time_bucket_older: 'Older',
scheduled_jobs: 'Scheduled jobs',
new_job: 'New job',
loading: 'Loading...',
search_skills: 'Search skills...',
new_skill: 'New skill',
personal_memory: 'Personal memory',
current_task_list: 'Current task list',
// Insights
insights_title: 'Usage Analytics',
insights_sessions: 'Sessions',
insights_messages: 'Messages',
insights_tokens: 'Tokens',
insights_cost: 'Estimated Cost',
insights_no_cost: 'N/A',
insights_models: 'Models',
insights_activity_by_day: 'Activity by Day',
insights_activity_by_hour: 'Activity by Hour',
insights_peak_hour: 'Peak: {hour}',
insights_token_breakdown: 'Token Breakdown',
insights_input_tokens: 'Input',
insights_output_tokens: 'Output',
insights_total: 'Total',
insights_footer: 'Showing data from the last {days} days',
workspace_desc: 'Add and switch workspaces for your sessions.',
session_meta_messages: (n) => `${n} msg${n === 1 ? '' : 's'}`,
session_meta_children: (n) => `${n} child${n === 1 ? '' : 'ren'}`,
new_profile: 'New profile',
transcript: 'Transcript',
download_transcript: 'Download as Markdown',
import: 'Import',
// Settings detail
settings_label_sound: 'Notification sound',
settings_desc_sound: 'Play a sound when the assistant finishes a response.',
// TTS (#499)
tts_listen: 'Listen',
tts_not_supported: 'Speech synthesis not supported in this browser.',
settings_label_tts: 'Text-to-Speech for responses',
settings_desc_tts: "Show a speaker button on each assistant message to read it aloud using your browser's speech synthesis.",
settings_label_tts_auto_read: 'Auto-read responses aloud',
settings_desc_tts_auto_read: 'Automatically speak each new assistant response when it finishes. Pauses when you start typing.',
// Composer voice-mode pref (#1488)
settings_label_voice_mode: 'Hands-free voice mode button',
settings_desc_voice_mode: 'Show the voice-mode button (audio waveform) next to the dictation mic. Lets you speak naturally — Hermes auto-sends after a pause and reads replies aloud. Requires a browser that supports both speech recognition and TTS.',
settings_label_tts_voice: 'Voice',
settings_desc_tts_voice: "Preferred voice. Populated from your browser's available voices.",
settings_label_tts_rate: 'Speech rate',
settings_label_tts_pitch: 'Speech pitch',
settings_label_notifications: 'Browser notifications',
settings_desc_notifications: 'Show a system notification when a response completes while the app is in the background.',
settings_desc_token_usage: 'Displays input/output token count below each assistant reply. Also toggled with /usage.',
settings_label_api_redact: 'Redact sensitive data in API responses',
settings_desc_api_redact: 'Self-hosted users can disable for transparency (not recommended for shared instances).',
settings_sidebar_density_compact: 'Compact',
settings_sidebar_density_detailed: 'Detailed',
settings_desc_sidebar_density: 'Controls how much metadata the session list shows in the left sidebar.',
settings_label_auto_title_refresh: 'Adaptive title refresh',
settings_auto_title_refresh_off: 'Off',
settings_auto_title_refresh_5: 'Every 5 exchanges',
settings_auto_title_refresh_10: 'Every 10 exchanges',
settings_auto_title_refresh_20: 'Every 20 exchanges',
settings_desc_auto_title_refresh: 'Automatically re-generates the session title based on the latest exchange, keeping it relevant as the conversation evolves. Requires an LLM title generation model to be configured.',
settings_desc_external_sessions: 'Show conversations from CLI, Telegram, Discord, Slack, and other channels in the session list. Click to import and continue.',
settings_desc_sync_insights: 'Mirrors WebUI token usage to state.db so hermes /insights includes browser session data. Off by default.',
settings_desc_check_updates: 'Show a banner when newer versions of the WebUI or Agent are available. Runs a background git fetch periodically.',
settings_desc_bot_name: 'Display name for the assistant throughout the UI. Defaults to Hermes.',
settings_desc_password: 'Enter a new password to set or change it. Leave blank to keep current setting.',
password_placeholder: 'Enter new password…',
password_env_var_locked: 'The HERMES_WEBUI_PASSWORD environment variable is currently set and takes precedence. Unset it and restart the server to manage the password from here.',
password_env_var_locked_placeholder: 'Locked: HERMES_WEBUI_PASSWORD env var is set',
disable_auth: 'Disable Auth',
sign_out: 'Sign Out',
// Providers panel
providers_tab_title: 'Providers',
providers_section_title: 'Providers',
providers_section_meta: 'Manage API keys for AI providers. Changes take effect immediately.',
providers_status_configured: 'API key configured',
providers_status_not_configured: 'No API key',
providers_status_oauth: 'OAuth',
providers_status_api_key: 'API key',
providers_status_not_configured_label: 'Not configured',
providers_oauth_hint: 'Authenticated via OAuth. No API key needed.',
providers_oauth_config_yaml_hint: 'Token configured via config.yaml. To update, edit the providers section in your config.yaml or run hermes auth.',
providers_oauth_not_configured_hint: 'Not authenticated. Run hermes auth in the terminal to configure this provider.',
providers_save: 'Save',
providers_remove: 'Remove',
providers_saving: 'Saving…',
providers_removing: 'Removing…',
providers_enter_key: 'Please enter an API key',
providers_empty: 'No configurable providers found.',
providers_key_updated: 'API key saved',
providers_key_removed: 'API key removed',
providers_key_placeholder_new: 'sk-...',
providers_key_placeholder_replace: 'Enter new key to replace…',
cancel: 'Cancel',
create_job: 'Create job',
save_skill: 'Save skill',
editing: 'Editing',
// Empty state
empty_title: 'What can I help with?',
empty_subtitle: 'Ask anything, run commands, explore files, or manage your scheduled tasks.',
suggest_files: 'What files are in this workspace?',
suggest_schedule: "What's on my schedule today?",
suggest_plan: 'Help me plan a small project.',
// onboarding
onboarding_badge: 'FIRST RUN',
onboarding_title: 'Welcome to Hermes Web UI',
onboarding_lead: 'A quick guided setup will verify Hermes, save a real provider configuration, choose a workspace and model, and optionally protect the app with a password.',
onboarding_back: 'Back',
onboarding_continue: 'Continue',
onboarding_skip: 'Skip setup',
onboarding_skipped: 'Setup skipped — using existing config.',
onboarding_open: 'Open Hermes',
onboarding_step_system_title: 'System check',
onboarding_step_system_desc: 'Verify Hermes Agent and config visibility.',
onboarding_step_setup_title: 'Provider setup',
onboarding_step_setup_desc: 'Save the minimum Hermes provider config.',
onboarding_step_workspace_title: 'Workspace + model',
onboarding_step_workspace_desc: 'Pick defaults for new sessions and chat.',
onboarding_step_password_title: 'Optional password',
onboarding_step_password_desc: 'Protect the Web UI before sharing it.',
onboarding_step_finish_title: 'Finish',
onboarding_step_finish_desc: 'Review and enter the app.',
onboarding_notice_system_ready: 'Hermes Agent looks reachable from the Web UI.',
onboarding_notice_system_unavailable: 'Hermes Agent is not fully available yet. Bootstrap can install it, but provider setup may still require a terminal.',
onboarding_check_agent: 'Hermes Agent',
onboarding_check_agent_ready: 'Detected and importable',
onboarding_check_agent_missing: 'Missing or partially importable',
onboarding_check_password: 'Password',
onboarding_check_password_enabled: 'Already enabled',
onboarding_check_password_disabled: 'Not enabled yet',
onboarding_check_provider: 'Provider config',
onboarding_check_provider_ready: 'Ready to chat',
onboarding_check_provider_partial: 'Saved but incomplete',
onboarding_check_provider_pending: 'Needs verification',
onboarding_config_file: 'Config file:',
onboarding_env_file: '.env file:',
onboarding_unknown: 'Unknown',
onboarding_current_provider: 'Current setup:',
onboarding_missing_imports: 'Missing imports:',
onboarding_notice_setup_required: 'Choose a simple provider path here. Advanced OAuth flows still belong in the Hermes CLI for now.',
onboarding_notice_setup_already_ready: 'A working Hermes provider setup is already detected. You can keep it or replace it here.',
onboarding_oauth_provider_ready_title: 'Provider already authenticated',
onboarding_oauth_provider_ready_body: 'This instance is configured to use an OAuth provider (<strong>{provider}</strong>) that was set up via the Hermes CLI. No API key is needed here — click Continue to finish setup.',
onboarding_oauth_provider_not_ready_title: 'OAuth provider not yet authenticated',
onboarding_oauth_provider_not_ready_body: 'This instance is configured to use <strong>{provider}</strong>, which uses OAuth rather than an API key. Run <code>hermes auth</code> or <code>hermes model</code> in a terminal to authenticate, then reload the Web UI.',
onboarding_oauth_switch_hint: 'Or choose a different provider below to switch to an API-key setup:',
oauth_login_codex: 'Login with Codex (ChatGPT)',
oauth_codex_step1: 'Step 1: Visit this URL and enter the code',
oauth_codex_step2: 'Step 2: Enter this code on the page',
oauth_codex_polling: 'Waiting for authorization...',
oauth_codex_success: 'Codex OAuth login successful!',
oauth_codex_error: 'OAuth login failed',
oauth_codex_expired: 'Code expired, please try again',
onboarding_notice_workspace: 'These values reuse the same settings APIs as the normal app.',
onboarding_workspace_label: 'Workspace',
onboarding_workspace_or_path: 'Or enter a workspace path',
onboarding_workspace_placeholder: '/home/you/workspace',
onboarding_provider_label: 'Setup mode',
onboarding_quick_setup_badge: 'quick setup',
provider_category_easy_start: 'Easy start',
provider_category_self_hosted: 'Open / self-hosted',
provider_category_specialized: 'Specialized',
onboarding_api_key_label: 'API key',
onboarding_api_key_placeholder: 'Leave blank to keep an existing saved key',
onboarding_api_key_label_optional: 'API key (optional)',
onboarding_api_key_placeholder_optional: 'Leave blank for keyless servers',
onboarding_api_key_help_keyless: 'Most LM Studio / Ollama / vLLM installs run keyless — leave this blank if your server doesn\'t require authentication. Use the Test connection button to verify.',
onboarding_api_key_help_prefix: 'Saved as a secret in your Hermes .env file using',
onboarding_base_url_label: 'Base URL',
onboarding_base_url_placeholder: 'https://your-endpoint.example/v1',
onboarding_base_url_help: 'Use this for OpenAI-compatible routers, self-hosted servers, LiteLLM, Ollama, LM Studio, vLLM, or similar endpoints.',
onboarding_model_label: 'Default model',
onboarding_workspace_help: 'Pick the model Hermes should use for new chats after setup completes.',
onboarding_custom_model_placeholder: 'your-model-name',
onboarding_custom_model_help: 'For custom endpoints, enter the exact model ID your server expects.',
onboarding_notice_password_enabled: 'A password is already configured. Enter a new one only if you want to replace it.',
onboarding_notice_password_recommended: 'Optional but recommended if you will expose the UI beyond localhost.',
onboarding_password_label: 'Password (optional)',
onboarding_password_placeholder: 'Leave blank to skip',
onboarding_password_help: 'Passwords are stored through the existing settings API and hashed server-side.',
onboarding_notice_finish: 'You can reopen Settings later to change any of this.',
onboarding_not_set: 'Not set',
onboarding_password_will_enable: 'Will be enabled',
onboarding_password_will_replace: 'Will be replaced',
onboarding_password_keep_existing: 'Keep current password',
onboarding_password_remains_disabled: 'Will remain disabled',
onboarding_password_skipped: 'Skipped for now',
onboarding_finish_help: 'Finishing stores <code>onboarding_completed</code> in settings and drops you into the normal app.',
onboarding_error_choose_workspace: 'Choose a workspace before continuing.',
onboarding_error_choose_model: 'Choose a model before continuing.',
onboarding_error_provider_required: 'Choose a setup mode before continuing.',
onboarding_error_base_url_required: 'Base URL is required for custom endpoints.',
onboarding_probe_test_button: 'Test connection',
onboarding_probe_probing: 'Testing connection…',
onboarding_probe_ok: 'Connected. {n} model(s) available.',
onboarding_probe_error_generic: 'Could not reach the configured base URL.',
onboarding_probe_error_invalid_url: 'Base URL must start with http:// or https://.',
onboarding_probe_error_dns: 'Could not resolve the host. Check the URL or use the host\'s IP address.',
onboarding_probe_error_connect_refused: 'Connection refused — the server may not be running on that address. From inside Docker, try the host IP instead of localhost.',
onboarding_probe_error_timeout: 'The endpoint did not respond in time. Check that the server is running and the URL is correct.',
onboarding_probe_error_http_4xx: 'The endpoint returned a client error. Check authentication and the URL path (typically ends in /v1).',
onboarding_probe_error_http_5xx: 'The endpoint returned a server error. Check the LM Studio / Ollama server logs.',
onboarding_probe_error_parse: 'The endpoint did not return a model list in the expected shape. Verify the URL points to the OpenAI-compatible API root.',
onboarding_probe_error_unreachable: 'Could not reach the configured base URL.',
onboarding_error_probe_failed: 'Could not validate the configured base URL.',
onboarding_error_workspace_required: 'Workspace is required.',
onboarding_error_model_required: 'Model is required.',
onboarding_complete: 'Onboarding complete',
// panel/runtime i18n
error_prefix: 'Error: ',
not_available: 'N/A',
never: 'never',
add: 'Add',
add_failed: 'Add failed: ',
remove_failed: 'Remove failed: ',
switch_failed: 'Switch failed: ',
name_required: 'Name is required',
content_required: 'Content is required',
view: 'View',
dismiss: 'Dismiss',
disable: 'Disable',
cron_no_jobs: 'No scheduled jobs found.',
cron_status_off: 'off',
cron_status_paused: 'paused',
cron_status_error: 'error',
cron_status_active: 'active',
cron_status_running: 'running\u2026',
cron_status_needs_attention: 'needs attention',
cron_attention_desc: 'This recurring job has no next run time. The scheduler may have failed to compute its next run.',
cron_attention_croniter_hint: 'The Gateway runtime may be missing the croniter package. Restart the Gateway with cron support, then resume this job.',
cron_attention_resume: 'Resume and recalculate',
cron_jobs_project: 'Cron Jobs',
cron_attention_run_once: 'Run once now',
cron_attention_copy_diagnostics: 'Copy diagnostics',
cron_diagnostics_copied: 'Cron diagnostics copied',
cron_next: 'Next',
cron_last: 'Last',
cron_run_now: 'Run now',
cron_pause: 'Pause',
cron_resume: 'Resume',
cron_job_name_placeholder: 'Job name',
cron_schedule_placeholder: 'Schedule',
cron_prompt_placeholder: 'Prompt',
cron_last_output: 'Last output',
cron_all_runs: 'All runs',
cron_hide_runs: 'Hide runs',
cron_no_runs_yet: '(no runs yet)',
cron_schedule_required_example: 'Schedule is required (e.g. "0 9 * * *" or "every 1h")',
cron_schedule_required: 'Schedule is required',
cron_prompt_required: 'Prompt is required',
cron_job_created: 'Job created',
cron_duplicate: 'Duplicate',
cron_duplicated: 'Job duplicated (paused)',
cron_job_triggered: 'Job triggered',
cron_job_paused: 'Job paused',
cron_job_resumed: 'Job resumed',
cron_job_updated: 'Job updated',
cron_delete_confirm_title: 'Delete cron job',
cron_delete_confirm_message: 'This cannot be undone.',
cron_job_deleted: 'Job deleted',
cron_completion_status: (name, status) => `Cron "${name}" ${status}`,
status_failed: 'failed',
status_completed: 'completed',
todos_no_active: 'No active task list in this session.',
clear_conversation_title: 'Clear conversation',
clear_conversation_message: 'Clear all messages? This cannot be undone.',
clear_failed: 'Clear failed: ',
skills_no_match: 'No skills match.',
linked_files: 'Linked Files',
skill_load_failed: 'Could not load skill: ',
skill_file_load_failed: 'Could not load file: ',
skill_name_required: 'Skill name is required',
skill_updated: 'Skill updated',
skill_created: 'Skill created',
skill_deleted: 'Skill deleted',
skill_delete_confirm: 'Delete skill "{0}"?',
skills_empty_title: 'Select a skill',
skills_empty_sub: 'Pick a skill from the sidebar to view its contents, or create a new one.',
skills_edit: 'Edit',
skills_delete: 'Delete',
skills_back_to: 'Back to {0}',
tasks_empty_title: 'Select a scheduled job',
tasks_empty_sub: 'Pick a job from the sidebar to view its details and runs, or create a new one.',
workspaces_empty_title: 'Select a space',
workspaces_empty_sub: 'Pick a space from the sidebar to view its files and settings, or add a new one.',
profiles_empty_title: 'Select a profile',
profiles_empty_sub: 'Pick an agent profile from the sidebar to view and edit its settings, or create a new one.',
memory_notes_label: 'memory (notes)',
memory_saved: 'Memory saved',
my_notes: 'My Notes',
user_profile: 'User Profile',
no_notes_yet: 'No notes yet.',
no_profile_yet: 'No profile yet.',
workspace_choose_path: 'Choose workspace path',
workspace_choose_path_meta: 'Add a validated path and switch this conversation',
workspace_manage: 'Manage workspaces',
workspace_manage_meta: 'Open the Spaces panel',
workspace_use_title: 'Use in current session',
workspace_use: 'Use',
workspace_add_path_placeholder: 'Add workspace path (e.g. /home/user/my-project)',
workspace_paths_validated_hint: 'Paths are validated as existing directories before saving.',
workspace_drag_hint: 'Drag to reorder',
workspace_reorder_failed: 'Reorder failed',
workspace_added: 'Workspace added',
workspace_renamed: 'Workspace renamed',
workspace_remove_confirm_title: 'Remove workspace',
workspace_remove_confirm_message: (path) => `Remove "${path}"?`,
workspace_removed: 'Workspace removed',
workspace_switch_prompt_title: 'Switch workspace',
workspace_switch_prompt_message: 'Enter an absolute workspace path to add and switch this conversation to.',
workspace_switch_prompt_confirm: 'Switch',
workspace_switch_prompt_placeholder: '/Users/you/project',
workspace_not_added: 'Workspace was not added',
workspace_already_saved: 'Workspace already saved — choose it from the list',
workspace_busy_switch: 'Cannot switch workspace while agent is running',
discard_file_edits_title: 'Discard file edits?',
discard_file_edits_message: 'Switching workspaces will discard unsaved file edits in the preview.',
workspace_switched_to: (name) => `Switched to ${name}`,
profiles_no_profiles: 'No profiles found.',
profile_api_keys_configured: 'API keys configured',
profile_gateway_running: 'Gateway running',
profile_gateway_stopped: 'Gateway stopped',
profile_active: 'ACTIVE',
profile_no_configuration: 'No configuration',
profile_skill_count: (count) => `${count} skill${count === 1 ? '' : 's'}`,
profile_use: 'Use',
profile_switch_title: 'Switch to this profile',
profile_delete_title: 'Delete this profile',
profile_default_label: '(default)',
profile_name_placeholder: 'Profile name (lowercase, a-z 0-9 hyphens)',
profile_clone_label: 'Clone config from active profile',
profile_base_url_placeholder: 'Base URL (optional, e.g. http://localhost:11434)',
profile_api_key_placeholder: 'API key (optional)',
manage_profiles: 'Manage profiles',
profiles_load_failed: 'Failed to load profiles',
profiles_busy_switch: 'Cannot switch profiles while agent is running',
profile_switched_new_conversation: (name) => `Switched to profile: ${name} — new conversation started`,
profile_switched: (name) => `Switched to profile: ${name}`,
profile_name_rule: 'Lowercase letters, numbers, hyphens, underscores only',
profile_base_url_rule: 'Base URL must start with http:// or https://',
profile_created: (name) => `Profile created: ${name}`,
profile_delete_confirm_title: (name) => `Delete profile "${name}"?`,
profile_delete_confirm_message: 'All sessions, config, skills, and memory for this profile will be permanently deleted. This cannot be undone.',
profile_deleted: (name) => `Profile deleted: ${name}`,
active_conversation_none: 'No active conversation selected.',
active_conversation_meta: (title, count) => `${title} · ${count} message${count === 1 ? '' : 's'}`,
settings_unsaved_changes: 'You have unsaved changes.',
sign_out_failed: 'Sign out failed: ',
disable_auth_confirm_title: 'Disable password protection',
disable_auth_confirm_message: 'Anyone will be able to access this instance.',
auth_disabled: 'Auth disabled — password protection removed',
disable_auth_failed: 'Failed to disable auth: ',
bg_error_single: (title) => `"${title}" has encountered an error`,
bg_error_multi: (count) => `${count} sessions have encountered an error`,
// skill form
skill_name: 'Name',
skill_category: 'Category',
skill_category_placeholder: 'Optional, e.g. devops',
skill_content: 'SKILL.md content',
skill_content_placeholder: 'YAML frontmatter + markdown body',
skill_rename_not_supported: 'Renaming a skill is not supported. Create a new skill and delete the old one to rename.',
skill_metadata: 'Metadata',
// cron form
cron_name_label: 'Name',
cron_name_placeholder: 'Optional',
cron_schedule_label: 'Schedule',
cron_schedule_hint: "Cron expression or shorthand like 'every 1h'.",
cron_prompt_label: 'Prompt',
cron_deliver_label: 'Deliver output to',
cron_deliver_local: 'Local (save output only)',
cron_skills_label: 'Skills',
cron_skills_placeholder: 'Add skills (optional)…',
cron_skills_edit_hint: 'Skill list is not editable after creation.',
// workspace form
workspace_name_label: 'Name',
workspace_name_placeholder: 'Optional friendly name',
workspace_path_label: 'Path',
workspace_path_required: 'Path is required',
workspace_path_readonly: 'Path cannot be changed. Rename only.',
workspace_new_title: 'New space',
// profile form
profile_name_label: 'Name',
profile_base_url_label: 'Base URL',
profile_api_key_label: 'API key',
cmd_yolo: 'Toggle YOLO mode (skip approvals)',
yolo_no_session: 'No active session',
yolo_enabled: '⚡ YOLO mode ON — approvals skipped this session',
yolo_disabled: 'YOLO mode OFF',
yolo_pill_label: 'YOLO',
yolo_pill_title_active: 'YOLO mode active — click to disable',
approval_skip_all: '⚡ Skip all this session',
approval_skip_all_title: 'Skip all approval prompts for this session',
// composer action tooltips
composer_send: 'Send message',
composer_queue: 'Queue message',
composer_interrupt: 'Interrupt and send',
composer_steer: 'Steer current response',
composer_stop: 'Stop generation',
composer_disabled_clarify: 'Respond to the clarification request',
composer_disabled_compression: 'Waiting for compression to finish',
composer_disabled_empty: 'Type a message to send',
composer_mobile_workspace: 'Workspace',
composer_mobile_model: 'Model',
composer_mobile_reasoning: 'Reasoning',
composer_mobile_context: 'Context',
media_audio_label: 'Audio',
media_svg_label: 'Diagram',
media_video_label: 'Video',
csv_loading: 'Loading CSV',
csv_too_large: 'CSV file too large for inline rendering',
csv_no_data: 'CSV file has insufficient data to render as table',
csv_error: 'Failed to load CSV file',
csv_header_note: 'First row shown as table header',
excalidraw_loading: 'Loading diagram',
excalidraw_too_large: 'Excalidraw file too large for inline rendering',
excalidraw_invalid: 'Invalid Excalidraw file format',
excalidraw_error: 'Failed to load Excalidraw file',
excalidraw_label: 'Diagram',
excalidraw_download: 'Download',
excalidraw_empty: 'Empty diagram',
excalidraw_render_error: 'Failed to render diagram',
excalidraw_simplified: 'Simplified SVG preview — not pixel-identical to Excalidraw canvas',
// ── Checkpoints / Rollback ──
checkpoint_title: 'Checkpoints',
checkpoint_empty: 'No checkpoints found for this workspace.',
checkpoint_loading: 'Loading checkpoints…',
checkpoint_error: 'Failed to load checkpoints',
checkpoint_date: 'Date',
checkpoint_message: 'Message',
checkpoint_files: 'Files',
checkpoint_view_diff: 'View diff',
checkpoint_restore: 'Restore',
checkpoint_restore_confirm_title: 'Restore checkpoint?',
checkpoint_restore_confirm_message: (ckpt) => `Restore workspace to checkpoint "${ckpt}"? This will overwrite files with the saved versions. Files added after this checkpoint will not be deleted.`,
checkpoint_restored: 'Checkpoint restored',
checkpoint_diff_title: 'Changes in checkpoint',
checkpoint_diff_no_changes: 'No differences found between this checkpoint and the current workspace.',
checkpoint_diff_files_changed: (n) => `${n} file${n === 1 ? '' : 's'} changed`,
},
ja: {
_lang: 'ja',
_label: '日本語',
_speech: 'ja-JP',
// boot.js
cancelling: 'キャンセル中…',
cancel_failed: 'キャンセル失敗: ',
mic_denied: 'マイクへのアクセスが拒否されました。ブラウザの権限を確認してください。',
mic_no_speech: '音声が検出されませんでした。もう一度お試しください。',
mic_network: '音声認識を利用できません。',
mic_error: '音声入力エラー: ',
// Turn-based voice mode (#1333)
// Composer voice buttons (#1488)
voice_dictate: 'ディクテーション',
voice_dictate_active: 'ディクテーション停止',
voice_mode_toggle: '音声モード',
voice_mode_toggle_active: '音声モードを終了',
voice_listening: '聞き取り中…',
voice_speaking: '発話中…',
voice_thinking: '考え中…',
voice_error: 'このブラウザでは音声入力に対応していません',
voice_mode_active: '音声モード ON',
voice_mode_off: '音声モード OFF',
session_imported: 'セッションをインポートしました',
import_failed: 'インポート失敗: ',
import_invalid_json: '無効な JSON',
image_pasted: '画像を貼り付けました: ',
// messages.js
edit_message: 'メッセージを編集',
regenerate: '応答を再生成',
copy: 'コピー',
copied: 'コピーしました!',
copy_failed: 'コピー失敗',
diff_loading: '差分を読み込み中',
diff_error: 'パッチファイルを読み込めませんでした',
diff_too_large: 'パッチファイルが大きすぎてインライン表示できません',
tree_view: 'ツリー',
raw_view: '生データ',
parse_failed_note: '解析失敗',
you: 'あなた',
mcp_servers_title: 'MCPサーバー',
mcp_servers_desc: 'config.yaml で設定された MCP サーバーを管理します。',
mcp_no_servers: 'MCPサーバーは設定されていません。',
mcp_add_server: '+ サーバーを追加',
mcp_field_name: 'サーバー名',
mcp_transport_label: 'トランスポート種別',
mcp_field_command: 'コマンド',
mcp_field_args: '引数 (カンマ区切り)',
mcp_field_url: 'URL',
mcp_field_timeout: 'タイムアウト (秒)',
mcp_save: '保存',
mcp_cancel: 'キャンセル',
mcp_name_required: 'サーバー名は必須です。',
mcp_url_required: 'HTTP トランスポートには URL が必要です。',
mcp_command_required: 'stdio トランスポートにはコマンドが必要です。',
mcp_saved: 'MCPサーバーを保存しました。',
mcp_save_failed: 'MCPサーバーの保存に失敗しました。',
mcp_delete_confirm_title: 'MCPサーバーを削除',
mcp_delete_confirm_message: 'MCPサーバー "{0}" を削除しますか? この操作は取り消せません。',
mcp_deleted: 'MCPサーバーを削除しました。',
mcp_delete_failed: 'MCPサーバーの削除に失敗しました。',
mcp_load_failed: 'MCPサーバーの読み込みに失敗しました。',
// PDF preview (#480)
pdf_loading: 'PDF {0} を読み込み中…',
pdf_too_large: 'PDF が大きすぎてインラインプレビューできません',
pdf_no_pages: 'PDF にページがありません',
pdf_error: 'PDF プレビューの描画に失敗しました',
pdf_download: 'PDF をダウンロード',
// HTML sandbox preview (#482)
html_loading: 'HTML プレビューを読み込み中…',
html_too_large: 'HTML が大きすぎてインラインプレビューできません',
html_error: 'HTML プレビューの描画に失敗しました',
html_open_full: 'フルページを開く',
html_sandbox_label: 'HTML プレビュー (サンドボックス)',
thinking: '考え中',
expand_all: 'すべて展開',
collapse_all: 'すべて折りたたむ',
edit_failed: '編集失敗: ',
regen_failed: '再生成失敗: ',
reconnect_active: '応答を生成中です。準備ができたら再読み込みしますか?',
reconnect_finished: '前回離脱時に応答が進行中でした。メッセージが更新されている可能性があります。',
// approval card
approval_heading: '承認が必要',
approval_desc_prefix: '危険なコマンドを検出しました',
approval_btn_once: '今回だけ許可',
approval_btn_once_title: 'このコマンド1回だけ許可 (Enter)',
approval_btn_session: 'セッション中許可',
approval_btn_session_title: 'この会話セッション中は許可',
approval_btn_always: '常に許可',
approval_btn_always_title: 'このコマンドパターンを常に許可',
approval_btn_deny: '拒否',
approval_btn_deny_title: '拒否 — このコマンドを実行しない',
approval_responding: '応答中…',
clarify_heading: '確認が必要',
clarify_hint: '選択肢を選ぶか、下に独自の回答を入力してください。',
clarify_other: 'その他',
clarify_send: '送信',
clarify_input_placeholder: '回答を入力…',
clarify_responding: '応答中…',
untitled: '無題',
n_messages: (n) => `${n} 件のメッセージ`,
load_older_messages: '↑ 上にスクロール、またはクリックして過去のメッセージを読み込む',
queued_label: '応答後に送信',
queued_count: (n) => `${n} 件キュー中`,
queued_cancel: 'キューに入れたメッセージをキャンセル',
model_unavailable: ' (利用不可)',
model_unavailable_title: 'このモデルは現在のプロバイダ一覧に含まれていません',
provider_mismatch_warning: (m,p)=>`"${m}" は設定されたプロバイダ (${p}) で動作しない可能性があります。このまま送信するか、ターミナルで \`hermes model\` を実行して切り替えてください。`,
provider_mismatch_label: 'プロバイダ不一致',
model_not_found_label: 'モデルが見つかりません',
model_custom_label: 'カスタムモデルID',
model_custom_placeholder: '例: openai/gpt-5.4',
model_search_placeholder: 'モデルを検索…',
model_search_no_results: 'モデルが見つかりません',
model_group_configured: '設定済み',
ws_search_placeholder: 'ワークスペースを検索…',
ws_no_results: 'ワークスペースが見つかりません',
model_scope_advisory: '次回のメッセージからこの会話に適用されます。',
model_scope_toast: '次回のメッセージからこの会話に適用されます。',
// commands.js
cmd_clear: '会話メッセージをクリア',
cmd_compress: '会話コンテキストを手動で圧縮 (使い方: /compress [トピック])',
ctx_compress_hint: 'コンテキストを圧縮して空きを確保 →',
ctx_compress_action: '⚠ 今すぐ圧縮してコンテキストを確保',
cmd_compact_alias: '/compress の旧エイリアス',
cmd_model: 'モデルを切り替え (例: /model gpt-4o)',
cmd_workspace: '名前でワークスペースを切り替え',
cmd_terminal: 'ワークスペースのターミナルを開く',
cmd_new: '新しいチャットセッションを開始',
cmd_usage: 'トークン使用量表示の ON/OFF を切り替え',
cmd_theme: '外観を切り替え (theme: system/dark/light, skin: default/ares/mono/slate/poseidon/sisyphus/charizard)',
cmd_personality: 'エージェントのパーソナリティを切り替え',
cmd_skills: '利用可能な Hermes スキルを一覧表示',
available_commands: '利用可能なコマンド:',
type_slash: '/ を入力するとコマンド一覧',
conversation_cleared: '会話をクリアしました',
command_label: 'コマンド',
context_compaction_label: 'コンテキスト圧縮',
preserved_task_list_label: '保持されたタスクリスト',
reference_only_label: '参照専用',
model_usage: '使い方: /model <名前>',
no_model_match: '一致するモデルなし: "',
switched_to: '切り替えました: ',
workspace_usage: '使い方: /workspace <名前>',
no_workspace_match: '一致するワークスペースなし: "',
switched_workspace: 'ワークスペースを切り替えました: ',
workspace_switch_failed: 'ワークスペース切替失敗: ',
new_session: '新しいセッションを作成しました',
compressing: 'コンテキスト圧縮を要求中...',
compress_running_label: '圧縮中',
compress_complete_label: '圧縮完了',
auto_compress_label: '自動圧縮',
compress_failed_label: '圧縮失敗',
focus_label: 'フォーカス',
token_usage_on: 'トークン使用量: ON',
token_usage_off: 'トークン使用量: OFF',
theme_usage: '使い方: /theme ',
theme_set: 'テーマ: ',
no_active_session: 'アクティブなセッションがありません',
cmd_queue: '次のターン用にメッセージをキュー',
cmd_interrupt: '現在のターンをキャンセルして新規メッセージを送信',
cmd_steer: 'エージェントを中断せずにターン中に修正を注入',
cmd_queue_no_msg: '使い方: /queue <メッセージ>',
cmd_queue_not_busy: 'アクティブなタスクなし — 通常通り送信してください',
cmd_queue_confirm: 'メッセージをキューに入れました',
cmd_interrupt_no_msg: '使い方: /interrupt <メッセージ>',
cmd_interrupt_confirm: '中断 — 新しいメッセージを送信中',
cmd_steer_no_msg: '使い方: /steer <メッセージ>',
cmd_steer_fallback: 'ステア利用不可 — 代わりに次のターンへキュー',
cmd_steer_delivered: 'ステア送信完了 — 次のツール結果でエージェントが認識します',
steer_leftover_queued: 'ステアを次のターンへキュー',
busy_steer_fallback: 'ステア利用不可 — 次のターンへキュー',
busy_interrupt_confirm: '中断 — 新しいメッセージを送信中',
settings_label_busy_input_mode: 'ビジー時の入力モード',
settings_desc_busy_input_mode: 'エージェント実行中にメッセージを送信した時の動作を制御します。Queue は待機、Interrupt はキャンセルして再開、Steer は中断せずにターン中に修正を注入します (エージェントやストリームが利用不可ならキューにフォールバック)。',
settings_busy_input_mode_queue: 'フォローアップをキュー',
settings_busy_input_mode_interrupt: '現在のターンを中断',
settings_busy_input_mode_steer: 'ステア (ターン中の修正)',
slash_skill_badge:'スキル',
slash_skill_desc:'このスキルを呼び出す',
cmd_stop:'現在の応答を停止',
cmd_title:'セッションタイトルを取得・設定',
cmd_retry:'最後のメッセージを再送信',
cmd_undo:'最後のやり取りを削除',
cmd_btw:'サイド質問 (一時的)',
cmd_btw_usage:'/btw <質問> — セッション文脈でサイド質問',
cmd_background:'プロンプトをバックグラウンド実行',
cmd_background_usage:'/background <プロンプト> — ブロックせずに並列実行',
cmd_branch:'この会話を新しいセッションへ分岐',
cmd_branch_usage:'/branch [名前] — 会話を分岐 (任意で名前指定)',
branch_forked:'新しいセッションへ分岐しました',
branch_failed:'分岐失敗: ',
fork_from_here:'ここから分岐',
forked_from:'分岐元',
subagent_children:'サブエージェントセッション',
btw_asking:'サイド質問を問い合わせ中...',
btw_label:'サイド質問 — 履歴に残らない',
btw_done:'サイド質問に回答しました',
btw_no_answer:'回答が得られませんでした。',
btw_failed:'サイド質問失敗: ',
bg_running:'バックグラウンド実行中...',
bg_complete:'バックグラウンドタスク完了',
bg_label:'バックグラウンド結果:',
bg_no_answer:'(回答なし)',
bg_failed:'バックグラウンドタスク失敗: ',
undo_exchange:'最後のやり取りを取り消す',
cmd_status:'セッション情報を表示',
cmd_voice:'マイク入力を切り替え',
stream_stopped:'応答を停止しました。',
no_active_task:'停止できるアクティブタスクがありません。',
cancel_unavailable:'キャンセルできません。',
retry_failed:'再試行失敗: ',
undo_failed:'取り消し失敗: ',
undid_n_messages:'削除',
undid_messages_suffix:'件のメッセージ。',
status_heading:'セッションステータス',
status_session_id:'セッションID',
status_title:'タイトル',
status_model:'モデル',
status_workspace:'ワークスペース',
status_personality:'パーソナリティ',
status_messages:'メッセージ',
status_agent_running:'エージェント実行中',
status_profile: 'プロファイル',
status_hermes_home: 'Hermes ホーム',
status_started: '開始',
status_tokens: 'トークン',
status_no_tokens: 'トークン未使用',
status_unknown: '不明',
status_yes:'はい',
status_no:'いいえ',
status_load_failed:'ステータス読み込み失敗: ',
title_current:'現在のタイトル',
title_change_hint:'`/title <新しい名前>` で改名できます。',
title_set:'タイトルを設定: ',
cmd_webui_only_session:'CLI からインポートしたセッションでは使えません。',
cmd_voice_use_mic:'コンポーザーのマイクボタンをクリックしてください。',
usage_heading:'トークン使用量',
usage_default_model:'デフォルト',
usage_unknown:'不明',
usage_input_tokens:'入力トークン',
usage_output_tokens:'出力トークン',
usage_total:'合計トークン',
usage_estimated_cost:'推定コスト',
usage_settings_tip:'注: コスト推定はおおよその値です。',
usage_load_failed:'使用量読み込み失敗: ',
usage_personality_none:'なし',
// Session toolsets (#493)
session_toolsets:'セッションツールセット',
session_toolsets_desc:'このセッションで利用可能なツールを制限 (空欄=グローバル設定を使用)',
session_toolsets_global:'グローバル (デフォルト)',
session_toolsets_custom:'カスタム',
session_toolsets_placeholder:'tool1, tool2, …',
session_toolsets_apply:'適用',
session_toolsets_clear:'クリア (グローバルを使用)',
session_toolsets_applied:'ツールセットを更新しました',
session_toolsets_cleared:'ツールセットをクリアしました — グローバル設定を使用',
session_toolsets_failed:'ツールセット更新失敗: ',
untitled:'無題',
no_personalities: 'パーソナリティが見つかりません (~/.hermes/personalities/ に追加してください)',
available_personalities: '利用可能なパーソナリティ:',
personality_switch_hint: '\n\n`/personality <名前>` で切り替え、`/personality none` でクリアします。',
personalities_load_failed: 'パーソナリティの読み込みに失敗しました',
personality_cleared: 'パーソナリティをクリアしました',
personality_set: 'パーソナリティ: ',
failed_colon: '失敗: ',
// ui.js
no_workspace: 'ワークスペースなし',
terminal_open_title: 'ワークスペースのターミナルを開く',
terminal_no_workspace_title: 'ターミナルを開くにはワークスペースを選択してください',
terminal_title: 'ターミナル',
terminal_clear: 'クリア',
terminal_copy_output: '出力をコピー',
terminal_restart: '再起動',
terminal_collapse: '折りたたむ',
terminal_expand: '展開',
terminal_close: '閉じる',
terminal_input_placeholder: 'コマンドを実行...',
terminal_start_failed: 'ターミナル起動失敗: ',
terminal_input_failed: 'ターミナル入力失敗: ',
terminal_copy_failed: 'コピー失敗: ',
terminal_error: 'ターミナルエラー',
workspace_empty_no_path: 'ワークスペースが選択されていません。設定 → ワークスペースで選択してください。',
workspace_empty_dir: 'このワークスペースは空です。',
dialog_confirm_title: '操作の確認',
dialog_prompt_title: '値を入力',
dialog_confirm_btn: '確認',
// workspace.js
unsaved_confirm: 'プレビューに未保存の変更があります。破棄して移動しますか?',
discard: '破棄',
save: '保存',
edit: '編集',
clear: 'クリア',
create: '作成',
remove: '削除',
save_title: '変更を保存',
edit_title: 'このファイルを編集',
saved: '保存しました',
save_failed: '保存失敗: ',
image_load_failed: '画像を読み込めませんでした',
file_open_failed: 'ファイルを開けませんでした',
downloading: (name) => `${name} をダウンロード中…`,
double_click_rename: 'ダブルクリックで名前変更',
renamed_to: '名前を変更: ',
rename_failed: '名前変更失敗: ',
delete_title: '削除',
delete_confirm: (name) => `${name} を削除しますか?`,
delete_dir_confirm: (name) => `フォルダ "${name}" とその内容をすべて削除しますか?`,
rename_title: '名前変更',
rename_prompt: '新しい名前:',
deleted: '削除しました: ',
delete_failed: '削除失敗: ',
reveal_in_finder: 'ファイルマネージャーで表示',
reveal_failed: '表示に失敗しました: ',
new_file_prompt: '新しいファイル名 (例: notes.md):',
project_name_prompt: 'プロジェクト名:',
created: '作成しました: ',
create_failed: '作成失敗: ',
new_folder_prompt: '新しいフォルダ名:',
folder_created: 'フォルダを作成しました: ',
folder_create_failed: 'フォルダ作成失敗: ',
workspace_auto_create_folder: 'フォルダが存在しなければ作成',
folder_add_as_space_btn: 'スペースとして追加',
folder_add_as_space_msg: 'このフォルダをワークスペース一覧に新しいスペースとして追加しますか?',
folder_add_as_space_title: 'スペースとして追加?',
remove_title: '削除',
empty_dir: '(空)',
upload_failed: 'アップロード失敗: ',
all_uploads_failed: (n) => `${n} 件のアップロードがすべて失敗しました`,
archive_extracted: (n, c) => `${c} 個のアーカイブから ${n} 件のファイルを展開しました`,
session_pin: '会話をピン留め',
session_unpin: 'ピン留めを解除',
session_pin_desc: 'この会話を上部に固定',
session_unpin_desc: 'ピン留めから外す',
session_pin_failed: 'ピン留め失敗: ',
session_move_project: 'プロジェクトへ移動',
session_move_project_desc_has: 'この会話のプロジェクトを変更',
session_move_project_desc_none: 'この会話にプロジェクトを割り当て',
session_archive: '会話をアーカイブ',
session_restore: '会話を復元',
session_archive_desc: 'アーカイブを表示するまでこの会話を非表示にする',
session_restore_desc: 'この会話をメイン一覧に戻す',
session_archived: 'セッションをアーカイブしました',
session_restored: 'セッションを復元しました',
session_archive_failed: 'アーカイブ失敗: ',
session_duplicate: '会話を複製',
session_duplicate_desc: '同じワークスペースとモデルでコピーを作成',
session_duplicated: 'セッションを複製しました',
session_duplicate_failed: '複製失敗: ',
session_stop_response: 'Stop response',
session_stop_response_desc: 'Cancel the running response for this conversation',
session_delete: '会話を削除',
session_delete_desc: 'この会話を完全に削除',
session_select_mode: '選択',
session_select_mode_desc: '会話を選択して一括管理',
session_select_all: 'すべて選択',
session_deselect_all: '選択解除',
session_selected_count: '{0} 件選択',
session_batch_archive: 'アーカイブ',
session_batch_delete: '削除',
session_batch_move: 'プロジェクトへ移動',
session_batch_delete_confirm: '{0} 件の会話を削除しますか?',
session_batch_archive_confirm: '{0} 件の会話をアーカイブしますか?',
session_no_selection: '会話が選択されていません',
// settings panel
settings_heading_title: 'コントロールセンター',
settings_heading_subtitle: '環境設定、会話ツール、システム制御。',
settings_section_conversation_title: '会話',
settings_section_appearance_title: '外観',
settings_section_appearance_meta: 'テーマ、アクセントカラー、ビジュアルスタイル。',
settings_section_preferences_title: '環境設定',
settings_section_preferences_meta: 'Hermes Web UI のデフォルトと UI 動作。',
settings_section_system_title: 'システム',
settings_section_system_meta: 'インスタンスのバージョンとアクセス制御。',
settings_check_now: '今すぐ確認',
settings_checking: '確認中…',
settings_up_to_date: '最新です ✓',
settings_updates_available: '{count} 件のアップデートあり',
settings_update_check_failed: 'アップデート確認失敗',
settings_updates_disabled: 'アップデート確認は無効です',
settings_label_workspace_panel_open: 'ワークスペースパネルをデフォルトで開いておく',
settings_desc_workspace_panel_open: '有効にすると、新しいセッションごとにワークスペース/ファイルブラウザパネルが自動で開きます。手動でいつでも閉じられます。',
open_in_browser: 'ブラウザで開く',
settings_dropdown_conversation: '会話',
settings_dropdown_appearance: '外観',
settings_dropdown_preferences: '環境設定',
settings_dropdown_providers: 'プロバイダ',
settings_dropdown_system: 'システム',
settings_tab_conversation: '会話',
settings_tab_appearance: '外観',
settings_tab_preferences: '環境設定',
settings_tab_system: 'システム',
settings_title: '設定',
settings_save_btn: '設定を保存',
settings_label_model: 'デフォルトモデル',
settings_desc_model: '新しい会話で使用されます。既存の会話は選択済みモデルを保持します。',
settings_label_send_key: '送信キー',
settings_label_theme: 'テーマ',
settings_label_skin: 'スキン',
settings_label_font_size: 'フォントサイズ',
font_size_small: '小',
font_size_default: 'デフォルト',
font_size_large: '大',
settings_autosave_saving: '保存中…',
settings_autosave_saved: '保存しました',
settings_autosave_failed: '保存失敗',
settings_autosave_retry: '再試行',
settings_label_language: '言語',
settings_label_token_usage: 'トークン使用量を表示',
settings_label_sidebar_density: 'サイドバー密度',
cmd_reasoning: '思考表示の切り替え (表示/非表示)、努力レベル設定、現在状態の確認',
settings_label_external_sessions: '非WebUIセッションを表示',
settings_label_sync_insights: 'インサイトに同期',
settings_label_check_updates: 'アップデートを確認',
settings_label_bot_name: 'アシスタント名',
settings_label_password: 'アクセスパスワード',
settings_saved: '設定を保存しました',
settings_save_failed: '保存失敗: ',
settings_load_failed: '設定の読み込みに失敗: ',
settings_saved_pw: '設定を保存 — パスワード保護を有効化、このブラウザはサインイン状態を維持します',
settings_saved_pw_updated: '設定を保存 — パスワードを更新しました',
// login page (used server-side via /api/i18n/login endpoint)
login_title: 'サインイン',
login_subtitle: 'パスワードを入力して続行',
login_placeholder: 'パスワード',
login_btn: 'サインイン',
login_invalid_pw: 'パスワードが無効です',
login_conn_failed: '接続失敗',
dialog_confirm_title: '操作の確認',
dialog_prompt_title: '値を入力',
dialog_confirm_btn: '確認',
discard: '破棄',
clear: 'クリア',
create: '作成',
remove: '削除',
project_name_prompt: 'プロジェクト名:',
// Sidebar & Tabs
tab_chat: 'チャット',
tab_tasks: 'タスク',
tab_skills: 'スキル',
tab_memory: 'メモリ',
tab_workspaces: 'スペース',
tab_profiles: 'プロファイル',
tab_kanban: 'Kanban',
kanban_board: 'Board',
kanban_visible_tasks: '{0} visible tasks',
kanban_search_tasks: 'Search tasks',
kanban_all_assignees: 'All assignees',
kanban_all_tenants: 'All tenants',
kanban_include_archived: 'Include archived',
kanban_no_matching_tasks: 'No matching tasks',
kanban_no_data: 'No Kanban data',
kanban_unavailable: 'Kanban unavailable',
kanban_read_only: 'Read-only view',
kanban_empty: 'Empty',
kanban_task: 'Task',
kanban_no_description: 'No description',
kanban_refresh: 'Refresh',
kanban_status_triage: 'Triage',
kanban_status_todo: 'Todo',
kanban_status_ready: 'Ready',
kanban_status_running: 'Running',
kanban_status_blocked: 'Blocked',
kanban_status_done: 'Done',
kanban_comments_count: 'Comments ({0})',
kanban_events_count: 'Events ({0})',
kanban_links: 'Links',
kanban_parents: 'Parents',
kanban_children: 'Children',
kanban_runs_count: 'Runs ({0})',
kanban_no_comments: 'No comments',
kanban_no_events: 'No events',
kanban_no_runs: 'No runs',
kanban_new_task: 'New task',
kanban_add_comment: 'Add comment',
kanban_only_mine: 'Only mine',
kanban_bulk_action: 'Bulk action',
kanban_nudge_dispatcher: 'Nudge dispatcher',
kanban_stats: 'Stats',
kanban_worker_log: 'Worker log',
kanban_block: 'Block',
kanban_unblock: 'Unblock',
kanban_back_to_board: 'Back to board',
kanban_lanes_by_profile: 'Lanes by profile',
kanban_new_board: 'New board…',
kanban_rename_board: 'Rename current board…',
kanban_archive_board: 'Archive current board…',
kanban_archive_board_confirm: 'Archive board "{name}"? Tasks remain on disk and the board can be restored from kanban/boards/_archived/.',
kanban_board_archived: 'Board archived',
kanban_board_name: 'Name',
kanban_board_slug: 'Slug (lowercase, hyphens)',
kanban_board_description: 'Description (optional)',
kanban_board_icon: 'Icon (emoji, optional)',
kanban_board_color: 'Color (optional)',
kanban_board_name_required: 'Name is required',
kanban_board_slug_required: 'Slug is required',
kanban_card_start: 'start',
kanban_card_complete: 'complete',
kanban_card_archive: 'archive',
kanban_unassigned: 'unassigned',
kanban_status_archived: 'Archived',
tab_todos: 'ToDo',
tab_insights: 'インサイト',
tab_settings: '設定',
new_conversation: '新しい会話',
filter_conversations: '会話を絞り込み...',
session_time_unknown: '不明',
session_time_minutes_ago: (n) => `${n}分前`,
session_time_hours_ago: (n) => `${n}時間前`,
session_time_days_ago: (n) => `${n}日前`,
session_time_last_week: '1週間前',
session_time_bucket_today: '今日',
session_time_bucket_yesterday: '昨日',
session_time_bucket_this_week: '今週',
session_time_bucket_last_week: '先週',
session_time_bucket_older: 'それ以前',
scheduled_jobs: 'スケジュールジョブ',
new_job: '新規ジョブ',
loading: '読み込み中...',
search_skills: 'スキルを検索...',
new_skill: '新規スキル',
personal_memory: '個人メモリ',
current_task_list: '現在のタスクリスト',
// Insights
insights_title: '使用状況分析',
insights_sessions: 'セッション',
insights_messages: 'メッセージ',
insights_tokens: 'トークン',
insights_cost: '推定コスト',
insights_no_cost: 'N/A',
insights_models: 'モデル',
insights_activity_by_day: '日別アクティビティ',
insights_activity_by_hour: '時間別アクティビティ',
insights_peak_hour: 'ピーク: {hour}',
insights_token_breakdown: 'トークン内訳',
insights_input_tokens: '入力',
insights_output_tokens: '出力',
insights_total: '合計',
insights_footer: '直近 {days} 日間のデータを表示',
workspace_desc: 'セッション用のワークスペースを追加・切り替えします。',
session_meta_messages: (n) => `${n}`,
session_meta_children: (n) => `${n}`,
new_profile: '新規プロファイル',
transcript: 'トランスクリプト',
download_transcript: 'Markdown としてダウンロード',
import: 'インポート',
// Settings detail
settings_label_sound: '通知音',
settings_desc_sound: 'アシスタントが応答を完了したときに音を鳴らします。',
// TTS (#499)
tts_listen: '読み上げ',
tts_not_supported: 'このブラウザは音声合成に対応していません。',
settings_label_tts: '応答の読み上げ (TTS)',
settings_desc_tts: 'アシスタントの各メッセージにスピーカーボタンを表示し、ブラウザの音声合成で読み上げます。',
settings_label_tts_auto_read: '応答を自動で読み上げ',
settings_desc_tts_auto_read: '新しいアシスタント応答が完了するたびに自動で読み上げます。入力中は一時停止します。',
// Composer voice-mode pref (#1488)
settings_label_voice_mode: 'ハンズフリー音声モードのボタン',
settings_desc_voice_mode: '音声波形ボタンをディクテーションマイクの隣に表示します。発話の合間に自動送信し、返答を読み上げます。音声認識と TTS の両方をサポートするブラウザが必要です。',
settings_label_tts_voice: '声',
settings_desc_tts_voice: '優先する声。ブラウザで利用可能な声から選択されます。',
settings_label_tts_rate: '読み上げ速度',
settings_label_tts_pitch: '読み上げピッチ',
settings_label_notifications: 'ブラウザ通知',
settings_desc_notifications: 'アプリがバックグラウンドの間に応答が完了したらシステム通知を表示します。',
settings_desc_token_usage: 'アシスタント応答の下に入力/出力トークン数を表示します。/usage でも切替可能。',
settings_label_api_redact: 'API 応答内の機密データをマスク',
settings_desc_api_redact: 'セルフホスト利用者は透明性のため無効化できます (共有インスタンスでは非推奨)。',
settings_sidebar_density_compact: 'コンパクト',
settings_sidebar_density_detailed: '詳細',
settings_desc_sidebar_density: '左サイドバーのセッション一覧に表示するメタデータ量を制御します。',
settings_label_auto_title_refresh: 'タイトル自動更新',
settings_auto_title_refresh_off: 'オフ',
settings_auto_title_refresh_5: '5 回ごと',
settings_auto_title_refresh_10: '10 回ごと',
settings_auto_title_refresh_20: '20 回ごと',
settings_desc_auto_title_refresh: '最新のやり取りに基づいてセッションタイトルを自動再生成し、会話の進行に合わせて適切に保ちます。LLM タイトル生成モデルの設定が必要です。',
settings_desc_external_sessions: 'CLI、Telegram、Discord、Slack その他のチャネルからの会話をセッション一覧に表示します。クリックでインポートして続行できます。',
settings_desc_sync_insights: 'WebUI のトークン使用量を state.db にミラーし、hermes /insights にブラウザセッションのデータを含めます。デフォルトはオフ。',
settings_desc_check_updates: 'WebUI または Agent の新しいバージョンが利用可能な時にバナーを表示します。バックグラウンドで定期的に git fetch を実行します。',
settings_desc_bot_name: 'UI 全体で表示されるアシスタントの名前。デフォルトは Hermes。',
settings_desc_password: '新しいパスワードを入力すると設定または変更します。空欄なら現在の設定を維持。',
password_placeholder: '新しいパスワードを入力…',
password_env_var_locked: '現在 HERMES_WEBUI_PASSWORD 環境変数が設定されており優先されます。ここで管理するには変数を解除してサーバーを再起動してください。',
password_env_var_locked_placeholder: 'ロック中: HERMES_WEBUI_PASSWORD 環境変数が設定されています',
disable_auth: '認証を無効化',
sign_out: 'サインアウト',
// Providers panel
providers_tab_title: 'プロバイダ',
providers_section_title: 'プロバイダ',
providers_section_meta: 'AI プロバイダの APIキー を管理します。変更は即時反映されます。',
providers_status_configured: 'APIキー設定済み',
providers_status_not_configured: 'APIキーなし',
providers_status_oauth: 'OAuth',
providers_status_api_key: 'APIキー',
providers_status_not_configured_label: '未設定',
providers_oauth_hint: 'OAuth 認証済み。APIキーは不要です。',
providers_oauth_config_yaml_hint: 'config.yaml でトークンが設定されています。更新するには config.yaml の providers セクションを編集するか hermes auth を実行してください。',
providers_oauth_not_configured_hint: '未認証です。ターミナルで hermes auth を実行してこのプロバイダを設定してください。',
providers_save: '保存',
providers_remove: '削除',
providers_saving: '保存中…',
providers_removing: '削除中…',
providers_enter_key: 'APIキーを入力してください',
providers_empty: '設定可能なプロバイダが見つかりません。',
providers_key_updated: 'APIキーを保存しました',
providers_key_removed: 'APIキーを削除しました',
providers_key_placeholder_new: 'sk-...',
providers_key_placeholder_replace: '置き換える新しいキーを入力…',
cancel: 'キャンセル',
create_job: 'ジョブを作成',
save_skill: 'スキルを保存',
editing: '編集中',
// Empty state
empty_title: '何をお手伝いしましょう?',
empty_subtitle: '何でも質問する、コマンド実行、ファイル探索、スケジュールタスク管理ができます。',
suggest_files: 'このワークスペースにあるファイルは?',
suggest_schedule: '今日のスケジュールは?',
suggest_plan: '小さなプロジェクトの計画を手伝って。',
// onboarding
onboarding_badge: '初回起動',
onboarding_title: 'Hermes Web UI へようこそ',
onboarding_lead: 'クイックガイドで Hermes を確認し、プロバイダ設定を保存し、ワークスペースとモデルを選択し、必要ならパスワードでアプリを保護します。',
onboarding_back: '戻る',
onboarding_continue: '続ける',
onboarding_skip: 'セットアップをスキップ',
onboarding_skipped: 'セットアップをスキップ — 既存設定を使用します。',
onboarding_open: 'Hermes を開く',
onboarding_step_system_title: 'システム確認',
onboarding_step_system_desc: 'Hermes Agent と設定の可視性を確認します。',
onboarding_step_setup_title: 'プロバイダ設定',
onboarding_step_setup_desc: '最低限の Hermes プロバイダ設定を保存します。',
onboarding_step_workspace_title: 'ワークスペース + モデル',
onboarding_step_workspace_desc: '新規セッションとチャットのデフォルトを選択します。',
onboarding_step_password_title: 'パスワード (任意)',
onboarding_step_password_desc: '共有前に Web UI を保護します。',
onboarding_step_finish_title: '完了',
onboarding_step_finish_desc: '確認してアプリに入ります。',
onboarding_notice_system_ready: 'Web UI から Hermes Agent へ到達できそうです。',
onboarding_notice_system_unavailable: 'Hermes Agent はまだ完全には利用できません。Bootstrap でインストールできますが、プロバイダ設定にはターミナルが必要な場合があります。',
onboarding_check_agent: 'Hermes Agent',
onboarding_check_agent_ready: '検出済み・インポート可能',
onboarding_check_agent_missing: '不在または部分的にしかインポートできません',
onboarding_check_password: 'パスワード',
onboarding_check_password_enabled: '既に有効',
onboarding_check_password_disabled: '未有効',
onboarding_check_provider: 'プロバイダ設定',
onboarding_check_provider_ready: 'チャット可能',
onboarding_check_provider_partial: '保存済みだが不完全',
onboarding_check_provider_pending: '検証が必要',
onboarding_config_file: '設定ファイル:',
onboarding_env_file: '.env ファイル:',
onboarding_unknown: '不明',
onboarding_current_provider: '現在の設定:',
onboarding_missing_imports: '不足しているインポート:',
onboarding_notice_setup_required: 'シンプルなプロバイダ経路をここで選んでください。高度な OAuth フローは現状 Hermes CLI 側で扱います。',
onboarding_notice_setup_already_ready: '動作する Hermes プロバイダ設定が既に検出されています。維持するか、ここで置き換えできます。',
onboarding_oauth_provider_ready_title: 'プロバイダは認証済み',
onboarding_oauth_provider_ready_body: 'このインスタンスは Hermes CLI で設定された OAuth プロバイダ (<strong>{provider}</strong>) を使用します。APIキーは不要 — 続けるをクリックしてセットアップを完了してください。',
onboarding_oauth_provider_not_ready_title: 'OAuth プロバイダは未認証',
onboarding_oauth_provider_not_ready_body: 'このインスタンスは <strong>{provider}</strong> を使用しますが、これは APIキー ではなく OAuth を使用します。ターミナルで <code>hermes auth</code> または <code>hermes model</code> を実行して認証し、Web UI を再読み込みしてください。',
onboarding_oauth_switch_hint: 'または下から別のプロバイダを選び、APIキー設定に切り替え:',
oauth_login_codex: 'Codex (ChatGPT) でログイン',
oauth_codex_step1: 'ステップ 1: この URL にアクセスしてコードを入力',
oauth_codex_step2: 'ステップ 2: ページにこのコードを入力',
oauth_codex_polling: '認可待ち...',
oauth_codex_success: 'Codex OAuth ログインに成功しました!',
oauth_codex_error: 'OAuth ログインに失敗しました',
oauth_codex_expired: 'コードの有効期限が切れました。もう一度お試しください',
onboarding_notice_workspace: 'これらの値は通常アプリと同じ設定 API を使用します。',
onboarding_workspace_label: 'ワークスペース',
onboarding_workspace_or_path: 'またはワークスペースのパスを入力',
onboarding_workspace_placeholder: '/home/you/workspace',
onboarding_provider_label: 'セットアップモード',
onboarding_quick_setup_badge: 'クイックセットアップ',
provider_category_easy_start: '簡単スタート',
provider_category_self_hosted: 'オープン / セルフホスト',
provider_category_specialized: '専門用途',
onboarding_api_key_label: 'APIキー',
onboarding_api_key_placeholder: '空欄で既存の保存済みキーを維持',
onboarding_api_key_label_optional: 'API key (optional)', // TODO: translate
onboarding_api_key_placeholder_optional: 'Leave blank for keyless servers', // TODO: translate
onboarding_api_key_help_keyless: 'Most LM Studio / Ollama / vLLM installs run keyless — leave this blank if your server doesn\'t require authentication. Use the Test connection button to verify.', // TODO: translate
onboarding_api_key_help_prefix: 'Hermes の .env ファイルにシークレットとして保存されます — 使用変数:',
onboarding_base_url_label: 'ベース URL',
onboarding_base_url_placeholder: 'https://your-endpoint.example/v1',
onboarding_base_url_help: 'OpenAI 互換ルーター、セルフホストサーバー、LiteLLM、Ollama、LM Studio、vLLM、または同様のエンドポイントで使用してください。',
onboarding_model_label: 'デフォルトモデル',
onboarding_workspace_help: 'セットアップ完了後の新規チャットで Hermes が使用するモデルを選択してください。',
onboarding_custom_model_placeholder: 'your-model-name',
onboarding_custom_model_help: 'カスタムエンドポイントの場合、サーバーが期待する正確なモデル ID を入力してください。',
onboarding_notice_password_enabled: 'パスワードは既に設定済みです。置き換える場合のみ新しいものを入力してください。',
onboarding_notice_password_recommended: '任意ですが、localhost 以外で UI を公開する場合は推奨します。',
onboarding_password_label: 'パスワード (任意)',
onboarding_password_placeholder: '空欄でスキップ',
onboarding_password_help: 'パスワードは既存の設定 API 経由で保存され、サーバー側でハッシュ化されます。',
onboarding_notice_finish: '後で設定からいつでも変更できます。',
onboarding_not_set: '未設定',
onboarding_password_will_enable: '有効化されます',
onboarding_password_will_replace: '置き換えられます',
onboarding_password_keep_existing: '現在のパスワードを維持',
onboarding_password_remains_disabled: '無効のまま',
onboarding_password_skipped: '今回はスキップ',
onboarding_finish_help: '完了すると <code>onboarding_completed</code> が設定に保存され、通常アプリへ入ります。',
onboarding_error_choose_workspace: '続行する前にワークスペースを選択してください。',
onboarding_error_choose_model: '続行する前にモデルを選択してください。',
onboarding_error_provider_required: '続行する前にセットアップモードを選択してください。',
onboarding_error_base_url_required: 'カスタムエンドポイントにはベース URL が必要です。',
onboarding_probe_test_button: 'Test connection', // TODO: translate
onboarding_probe_probing: 'Testing connection…', // TODO: translate
onboarding_probe_ok: 'Connected. {n} model(s) available.', // TODO: translate
onboarding_probe_error_generic: 'Could not reach the configured base URL.', // TODO: translate
onboarding_probe_error_invalid_url: 'Base URL must start with http:// or https://.', // TODO: translate
onboarding_probe_error_dns: 'Could not resolve the host. Check the URL or use the host\'s IP address.', // TODO: translate
onboarding_probe_error_connect_refused: 'Connection refused — the server may not be running on that address. From inside Docker, try the host IP instead of localhost.', // TODO: translate
onboarding_probe_error_timeout: 'The endpoint did not respond in time. Check that the server is running and the URL is correct.', // TODO: translate
onboarding_probe_error_http_4xx: 'The endpoint returned a client error. Check authentication and the URL path (typically ends in /v1).', // TODO: translate
onboarding_probe_error_http_5xx: 'The endpoint returned a server error. Check the LM Studio / Ollama server logs.', // TODO: translate
onboarding_probe_error_parse: 'The endpoint did not return a model list in the expected shape. Verify the URL points to the OpenAI-compatible API root.', // TODO: translate
onboarding_probe_error_unreachable: 'Could not reach the configured base URL.', // TODO: translate
onboarding_error_probe_failed: 'Could not validate the configured base URL.', // TODO: translate
onboarding_error_workspace_required: 'ワークスペースは必須です。',
onboarding_error_model_required: 'モデルは必須です。',
onboarding_complete: 'オンボーディング完了',
// panel/runtime i18n
error_prefix: 'エラー: ',
not_available: 'N/A',
never: 'なし',
add: '追加',
add_failed: '追加失敗: ',
remove_failed: '削除失敗: ',
switch_failed: '切替失敗: ',
name_required: '名前は必須です',
content_required: '内容は必須です',
view: '表示',
dismiss: '閉じる',
disable: '無効化',
cron_no_jobs: 'スケジュールジョブが見つかりません。',
cron_status_off: 'オフ',
cron_status_paused: '一時停止',
cron_status_error: 'エラー',
cron_status_active: '有効',
cron_status_running: '実行中…',
cron_status_needs_attention: '要対応',
cron_attention_desc: 'この繰り返しジョブには次回実行時刻がありません。スケジューラが次回実行時刻を計算できなかった可能性があります。',
cron_attention_croniter_hint: 'Gateway ランタイムに croniter パッケージが不足している可能性があります。cron サポート付きで Gateway を再起動し、ジョブを再開してください。',
cron_attention_resume: '再開して再計算',
cron_jobs_project: 'Cronジョブ',
cron_attention_run_once: '今すぐ1回実行',
cron_attention_copy_diagnostics: '診断情報をコピー',
cron_diagnostics_copied: 'Cron 診断情報をコピーしました',
cron_next: '次回',
cron_last: '前回',
cron_run_now: '今すぐ実行',
cron_pause: '一時停止',
cron_resume: '再開',
cron_job_name_placeholder: 'ジョブ名',
cron_schedule_placeholder: 'スケジュール',
cron_prompt_placeholder: 'プロンプト',
cron_last_output: '前回の出力',
cron_all_runs: 'すべての実行',
cron_hide_runs: '実行履歴を隠す',
cron_no_runs_yet: '(まだ実行されていません)',
cron_schedule_required_example: 'スケジュールは必須です (例: "0 9 * * *" または "every 1h")',
cron_schedule_required: 'スケジュールは必須です',
cron_prompt_required: 'プロンプトは必須です',
cron_job_created: 'ジョブを作成しました',
cron_duplicate: '複製',
cron_duplicated: 'ジョブを複製しました (一時停止)',
cron_job_triggered: 'ジョブを起動しました',
cron_job_paused: 'ジョブを一時停止しました',
cron_job_resumed: 'ジョブを再開しました',
cron_job_updated: 'ジョブを更新しました',
cron_delete_confirm_title: 'Cronジョブを削除',
cron_delete_confirm_message: 'この操作は取り消せません。',
cron_job_deleted: 'ジョブを削除しました',
cron_completion_status: (name, status) => `Cron "${name}" ${status}`,
status_failed: '失敗',
status_completed: '完了',
todos_no_active: 'このセッションにアクティブなタスクリストがありません。',
clear_conversation_title: '会話をクリア',
clear_conversation_message: 'すべてのメッセージをクリアしますか? この操作は取り消せません。',
clear_failed: 'クリア失敗: ',
skills_no_match: '一致するスキルがありません。',
linked_files: 'リンクされたファイル',
skill_load_failed: 'スキルを読み込めませんでした: ',
skill_file_load_failed: 'ファイルを読み込めませんでした: ',
skill_name_required: 'スキル名は必須です',
skill_updated: 'スキルを更新しました',
skill_created: 'スキルを作成しました',
skill_deleted: 'スキルを削除しました',
skill_delete_confirm: 'スキル "{0}" を削除しますか?',
skills_empty_title: 'スキルを選択',
skills_empty_sub: 'サイドバーからスキルを選んで内容を表示するか、新しいスキルを作成してください。',
skills_edit: '編集',
skills_delete: '削除',
skills_back_to: '{0} に戻る',
tasks_empty_title: 'スケジュールジョブを選択',
tasks_empty_sub: 'サイドバーからジョブを選んで詳細と実行履歴を表示するか、新規作成してください。',
workspaces_empty_title: 'スペースを選択',
workspaces_empty_sub: 'サイドバーからスペースを選んでファイルと設定を表示するか、新しく追加してください。',
profiles_empty_title: 'プロファイルを選択',
profiles_empty_sub: 'サイドバーからエージェントプロファイルを選んで設定を表示・編集するか、新規作成してください。',
memory_notes_label: 'メモリ (ノート)',
memory_saved: 'メモリを保存しました',
my_notes: 'マイノート',
user_profile: 'ユーザープロファイル',
no_notes_yet: 'まだノートはありません。',
no_profile_yet: 'まだプロファイルはありません。',
workspace_choose_path: 'ワークスペースのパスを選択',
workspace_choose_path_meta: '検証済みパスを追加してこの会話を切り替え',
workspace_manage: 'ワークスペースを管理',
workspace_manage_meta: 'スペースパネルを開く',
workspace_use_title: '現在のセッションで使用',
workspace_use: '使用',
workspace_add_path_placeholder: 'ワークスペースパスを追加 (例: /home/user/my-project)',
workspace_paths_validated_hint: '保存前に既存ディレクトリとして検証されます。',
workspace_drag_hint: 'ドラッグして並び替え',
workspace_reorder_failed: '並び替え失敗',
workspace_added: 'ワークスペースを追加しました',
workspace_renamed: 'ワークスペース名を変更しました',
workspace_remove_confirm_title: 'ワークスペースを削除',
workspace_remove_confirm_message: (path) => `"${path}" を削除しますか?`,
workspace_removed: 'ワークスペースを削除しました',
workspace_switch_prompt_title: 'ワークスペースを切り替え',
workspace_switch_prompt_message: '追加してこの会話を切り替える絶対パスを入力してください。',
workspace_switch_prompt_confirm: '切り替え',
workspace_switch_prompt_placeholder: '/Users/you/project',
workspace_not_added: 'ワークスペースは追加されませんでした',
workspace_already_saved: 'ワークスペースは既に保存済み — 一覧から選択してください',
workspace_busy_switch: 'エージェント実行中はワークスペースを切り替えできません',
discard_file_edits_title: 'ファイル編集を破棄しますか?',
discard_file_edits_message: 'ワークスペース切替でプレビュー内の未保存編集が破棄されます。',
workspace_switched_to: (name) => `${name} に切り替えました`,
profiles_no_profiles: 'プロファイルが見つかりません。',
profile_api_keys_configured: 'APIキー設定済み',
profile_gateway_running: 'Gateway 実行中',
profile_gateway_stopped: 'Gateway 停止中',
profile_active: 'アクティブ',
profile_no_configuration: '設定なし',
profile_skill_count: (count) => `${count} 件のスキル`,
profile_use: '使用',
profile_switch_title: 'このプロファイルに切り替え',
profile_delete_title: 'このプロファイルを削除',
profile_default_label: '(デフォルト)',
profile_name_placeholder: 'プロファイル名 (小文字 a-z 0-9 ハイフン)',
profile_clone_label: 'アクティブプロファイルから設定をコピー',
profile_base_url_placeholder: 'ベース URL (任意、例: http://localhost:11434)',
profile_api_key_placeholder: 'APIキー (任意)',
manage_profiles: 'プロファイルを管理',
profiles_load_failed: 'プロファイルの読み込みに失敗しました',
profiles_busy_switch: 'エージェント実行中はプロファイルを切り替えできません',
profile_switched_new_conversation: (name) => `プロファイルを切替: ${name} — 新しい会話を開始しました`,
profile_switched: (name) => `プロファイルを切替: ${name}`,
profile_name_rule: '小文字、数字、ハイフン、アンダースコアのみ',
profile_base_url_rule: 'ベース URL は http:// または https:// で始める必要があります',
profile_created: (name) => `プロファイルを作成: ${name}`,
profile_delete_confirm_title: (name) => `プロファイル "${name}" を削除しますか?`,
profile_delete_confirm_message: 'このプロファイルのすべてのセッション、設定、スキル、メモリが完全に削除されます。この操作は取り消せません。',
profile_deleted: (name) => `プロファイルを削除: ${name}`,
active_conversation_none: 'アクティブな会話が選択されていません。',
active_conversation_meta: (title, count) => `${title} · ${count} 件のメッセージ`,
settings_unsaved_changes: '未保存の変更があります。',
sign_out_failed: 'サインアウト失敗: ',
disable_auth_confirm_title: 'パスワード保護を無効化',
disable_auth_confirm_message: '誰でもこのインスタンスにアクセスできるようになります。',
auth_disabled: '認証無効化 — パスワード保護を解除しました',
disable_auth_failed: '認証の無効化に失敗: ',
bg_error_single: (title) => `"${title}" でエラーが発生しました`,
bg_error_multi: (count) => `${count} 件のセッションでエラーが発生しました`,
// skill form
skill_name: '名前',
skill_category: 'カテゴリ',
skill_category_placeholder: '任意、例: devops',
skill_content: 'SKILL.md の内容',
skill_content_placeholder: 'YAML フロントマター + Markdown 本文',
skill_rename_not_supported: 'スキルの名前変更には対応していません。新しいスキルを作成し、古いものを削除してください。',
skill_metadata: 'メタデータ',
// cron form
cron_name_label: '名前',
cron_name_placeholder: '任意',
cron_schedule_label: 'スケジュール',
cron_schedule_hint: "Cron 式または 'every 1h' のような短縮形。",
cron_prompt_label: 'プロンプト',
cron_deliver_label: '出力先',
cron_deliver_local: 'ローカル (出力を保存のみ)',
cron_skills_label: 'スキル',
cron_skills_placeholder: 'スキルを追加 (任意)…',
cron_skills_edit_hint: 'スキル一覧は作成後に編集できません。',
// workspace form
workspace_name_label: '名前',
workspace_name_placeholder: '任意の表示名',
workspace_path_label: 'パス',
workspace_path_required: 'パスは必須です',
workspace_path_readonly: 'パスは変更できません。名前変更のみ可能です。',
workspace_new_title: '新規スペース',
// profile form
profile_name_label: '名前',
profile_base_url_label: 'ベース URL',
profile_api_key_label: 'APIキー',
cmd_yolo: 'YOLO モード切替 (承認スキップ)',
yolo_no_session: 'アクティブなセッションがありません',
yolo_enabled: '⚡ YOLO モード ON — このセッションは承認をスキップ',
yolo_disabled: 'YOLO モード OFF',
yolo_pill_label: 'YOLO',
yolo_pill_title_active: 'YOLO モード有効 — クリックで無効化',
approval_skip_all: '⚡ このセッションはすべてスキップ',
approval_skip_all_title: 'このセッションのすべての承認プロンプトをスキップ',
// composer action tooltips
composer_send: 'メッセージを送信',
composer_queue: 'メッセージをキュー',
composer_interrupt: '中断して送信',
composer_steer: '現在の応答をステア',
composer_stop: '生成を停止',
composer_disabled_clarify: '確認要求に応答してください',
composer_disabled_compression: '圧縮の完了待ち',
composer_disabled_empty: '送信するメッセージを入力してください',
composer_mobile_workspace: 'ワークスペース',
composer_mobile_model: 'モデル',
composer_mobile_reasoning: '思考',
composer_mobile_context: 'コンテキスト',
media_audio_label: '音声',
media_svg_label: '図',
media_video_label: '動画',
csv_loading: 'CSV を読み込み中',
csv_too_large: 'CSV ファイルが大きすぎてインライン表示できません',
csv_no_data: 'CSV ファイルのデータが不足しているためテーブル表示できません',
csv_error: 'CSV ファイルの読み込みに失敗しました',
csv_header_note: '先頭行をテーブルヘッダーとして表示',
excalidraw_loading: '図を読み込み中',
excalidraw_too_large: 'Excalidraw ファイルが大きすぎてインライン表示できません',
excalidraw_invalid: '無効な Excalidraw ファイル形式',
excalidraw_error: 'Excalidraw ファイルの読み込みに失敗しました',
excalidraw_label: '図',
excalidraw_download: 'ダウンロード',
excalidraw_empty: '空の図',
excalidraw_render_error: '図の描画に失敗しました',
excalidraw_simplified: '簡略化された SVG プレビュー — Excalidraw キャンバスとピクセル単位では一致しません',
// ── Checkpoints / Rollback ──
checkpoint_title: 'チェックポイント',
checkpoint_empty: 'このワークスペースのチェックポイントが見つかりません。',
checkpoint_loading: 'チェックポイントを読み込み中…',
checkpoint_error: 'チェックポイントの読み込みに失敗しました',
checkpoint_date: '日時',
checkpoint_message: 'メッセージ',
checkpoint_files: 'ファイル',
checkpoint_view_diff: '差分を表示',
checkpoint_restore: '復元',
checkpoint_restore_confirm_title: 'チェックポイントを復元しますか?',
checkpoint_restore_confirm_message: (ckpt) => `ワークスペースをチェックポイント "${ckpt}" に復元しますか? ファイルが保存版で上書きされます。このチェックポイント後に追加されたファイルは削除されません。`,
checkpoint_restored: 'チェックポイントを復元しました',
checkpoint_diff_title: 'チェックポイントの変更内容',
checkpoint_diff_no_changes: 'このチェックポイントと現在のワークスペースの間に差分はありません。',
checkpoint_diff_files_changed: (n) => `${n} 件のファイルが変更されました`,
},
ru: {
_lang: 'ru',
_label: 'Русский',
_speech: 'ru-RU',
cancelling: 'Отменяю…',
cancel_failed: 'Не удалось отменить: ',
mic_denied: 'Доступ к микрофону запрещён. Проверьте разрешения браузера.',
mic_no_speech: 'Речь не распознана. Попробуйте ещё раз.',
mic_network: 'Распознавание речи недоступно.',
mic_error: 'Ошибка ввода речи: ',
// Composer voice buttons (#1488)
voice_dictate: 'Диктовка',
voice_dictate_active: 'Остановить диктовку',
voice_mode_toggle: 'Голосовой режим',
voice_mode_toggle_active: 'Выйти из голосового режима',
voice_listening: 'Слушаю…',
voice_speaking: 'Говорю…',
voice_thinking: 'Думаю…',
voice_error: 'Голосовой ввод не поддерживается в этом браузере',
voice_mode_active: 'Голосовой режим включён',
voice_mode_off: 'Голосовой режим выключен',
session_imported: 'Сеанс импортирован',
import_failed: 'Не удалось импортировать: ',
import_invalid_json: 'Неверный JSON',
image_pasted: 'Изображение вставлено: ',
edit_message: 'Редактировать сообщение',
regenerate: 'Сгенерировать ответ заново',
copy: 'Копировать',
copied: 'Скопировано!',
copy_failed: '\u041e\u0448\u0438\u0431\u043a\u0430 \u043a\u043e\u043f\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f',
diff_loading: 'Загрузка diff',
diff_error: 'Не удалось загрузить файл патча',
diff_too_large: 'Файл патча слишком большой для отображения',
tree_view: '樹狀',
raw_view: '原始',
parse_failed_note: 'parse failed',
you: 'Вы',
mcp_servers_title: 'MCP 伺服器',
mcp_servers_desc: '管理 config.yaml 中設定的 MCP 伺服器。',
mcp_no_servers: '未設定 MCP 伺服器。',
mcp_add_server: '+ 新增伺服器',
mcp_field_name: '伺服器名稱',
mcp_transport_label: '傳輸類型',
mcp_field_command: '命令',
mcp_field_args: '參數(逗號分隔)',
mcp_field_url: 'URL',
mcp_field_timeout: '逾時(秒)',
mcp_save: '儲存',
mcp_cancel: '取消',
mcp_name_required: '需要伺服器名稱。',
mcp_url_required: 'HTTP 傳輸需要 URL。',
mcp_command_required: 'stdio 傳輸需要命令。',
mcp_saved: 'MCP 伺服器已儲存。',
mcp_save_failed: '儲存 MCP 伺服器失敗。',
mcp_delete_confirm_title: '刪除 MCP 伺服器',
mcp_delete_confirm_message: '刪除 MCP 伺服器「{0}」?此操作無法撤銷。',
mcp_deleted: 'MCP 伺服器已刪除。',
mcp_delete_failed: '刪除 MCP 伺服器失敗。',
mcp_load_failed: '載入 MCP 伺服器失敗。',
thinking: 'Думаю',
expand_all: 'Развернуть всё',
collapse_all: 'Свернуть всё',
edit_failed: 'Не удалось отредактировать: ',
regen_failed: 'Не удалось сгенерировать заново: ',
reconnect_active: 'Ответ всё ещё генерируется. Обновить, когда будет готово?',
reconnect_finished: 'Когда вы уходили, ответ ещё генерировался. Сообщения могли обновиться.',
approval_heading: 'Требуется подтверждение',
approval_desc_prefix: 'Обнаружена опасная команда',
approval_btn_once: 'Разрешить один раз',
approval_btn_once_title: 'Разрешить только эту команду (Enter)',
approval_btn_session: 'Разрешить на этот сеанс',
approval_btn_session_title: 'Разрешить для этого сеанса разговора',
approval_btn_always: 'Всегда разрешать',
approval_btn_always_title: 'Всегда разрешать команды по этому шаблону',
approval_btn_deny: 'Запретить',
approval_btn_deny_title: 'Запретить — не выполнять эту команду',
approval_responding: 'Отвечаю…',
untitled: 'Без названия',
n_messages: (n) => `${n} сообщений`,
load_older_messages: '↑ Прокрутите вверх или нажмите, чтобы загрузить ранние сообщения',
queued_label: 'Отправить после ответа',
queued_count: (n) => n === 1 ? '1 в очереди' : `${n} в очереди`,
queued_cancel: 'Отменить сообщение',
model_unavailable: ' (недоступна)',
model_unavailable_title: 'Эта модель больше не входит в ваш текущий список провайдеров',
provider_mismatch_warning: (m, p) =>
`"${m}" может не работать с вашим настроенным провайдером (${p}). Всё равно отправить или запустите \`hermes model\` в терминале, чтобы переключиться.`,
provider_mismatch_label: 'Несовпадение провайдера',
model_not_found_label: 'Модель не найдена',
model_custom_label: 'Пользовательский ID модели',
model_custom_placeholder: 'например, openai/gpt-5.4',
cmd_help: 'Показать доступные команды',
cmd_clear: 'Очистить сообщения беседы',
cmd_compact: 'Сжать контекст беседы',
cmd_model: 'Переключить модель (например, /model gpt-4o)',
cmd_workspace: 'Переключить рабочее пространство по названию',
cmd_terminal: 'Открыть терминал рабочей области',
cmd_new: 'Начать новую сессию чата',
cmd_usage: 'Показать или скрыть использование токенов',
cmd_theme: 'Переключить тему (dark/light/slate/solarized/monokai/nord/oled)',
cmd_personality: 'Переключить личность агента',
cmd_skills: 'Показать доступные навыки Hermes',
available_commands: 'Доступные команды:',
type_slash: 'Введите /, чтобы увидеть команды',
conversation_cleared: 'Беседа очищена',
model_usage: 'Использование: /model <name>',
no_model_match: 'Нет модели, соответствующей "',
switched_to: 'Переключено на ',
workspace_usage: 'Использование: /workspace <name>',
no_workspace_match: 'Нет рабочего пространства, соответствующего "',
switched_workspace: 'Переключено на рабочее пространство: ',
workspace_switch_failed: 'Не удалось переключить рабочее пространство: ',
new_session: 'Новая сессия создана',
compressing: 'Запрашиваю сжатие контекста...',
token_usage_on: 'Отображение токенов включено',
usage_personality_none: 'none', // TODO: translate
token_usage_off: 'Отображение токенов выключено',
theme_usage: 'Использование: /theme ',
theme_set: 'Тема: ',
no_active_session: 'Нет активной сессии',
cmd_queue: 'Поставить сообщение в очередь на следующий оборот',
cmd_interrupt: 'Прервать текущий оборот и отправить новое сообщение',
cmd_steer: 'Направить агента исправлением (переходит к прерыванию)',
cmd_queue_no_msg: 'Использование: /queue <сообщение>',
cmd_queue_not_busy: 'Нет активной задачи — просто отправьте',
cmd_queue_confirm: 'Сообщение в очереди',
cmd_interrupt_no_msg: 'Использование: /interrupt <сообщение>',
cmd_interrupt_confirm: 'Прервано — отправка нового сообщения',
cmd_steer_no_msg: 'Использование: /steer <сообщение>',
cmd_steer_fallback: 'Steer недоступен — прервано и поставлено в очередь',
cmd_steer_delivered: 'Steer доставлен — агент увидит его в следующем ответе инструмента',
steer_leftover_queued: 'Steer поставлен в очередь на следующий ход',
busy_steer_fallback: 'Steer недоступен — прервано',
busy_interrupt_confirm: 'Прервано — отправка нового сообщения',
settings_label_busy_input_mode: 'Режим ввода при занятости',
settings_desc_busy_input_mode: 'Определяет поведение при отправке сообщения во время работы агента. Очередь ждёт; Прерывание отменяет и начинает заново; Steer внедряет коррекцию без прерывания.',
settings_busy_input_mode_queue: 'Поставить в очередь',
settings_busy_input_mode_interrupt: 'Прервать текущий оборот',
settings_busy_input_mode_steer: 'Steer (прерывание + отправка)',
no_personalities: 'Личности не найдены (добавьте их в ~/.hermes/personalities/)',
clarify_heading: 'Требуется уточнение',
clarify_hint: 'Выберите вариант или введите свой ответ ниже.',
clarify_input_placeholder: 'Введите ответ…',
clarify_other: 'Другое',
clarify_responding: 'Отвечаю…',
clarify_send: 'Отправить',
cmd_compact_alias: 'Устаревший псевдоним для /compress',
cmd_compress: 'Сжать контекст беседы (использование: /compress [тема])',
ctx_compress_hint: 'Сжать контекст для освобождения места →',
ctx_compress_action: '⚠ Сжать сейчас для освобождения контекста',
command_label: 'Команда',
compress_complete_label: 'Сжатие завершено',
auto_compress_label: 'Автосжатие',
compress_failed_label: 'Ошибка сжатия',
compress_running_label: 'Сжатие…',
context_compaction_label: 'Сжатие контекста',
preserved_task_list_label: 'Сохранённый список задач',
focus_label: 'Фокус',
model_search_no_results: 'Модели не найдены',
model_group_configured: 'Настроенные',
ws_search_placeholder: 'Поиск рабочих пространств…',
ws_no_results: 'Рабочие пространства не найдены',
model_search_placeholder: 'Поиск моделей…',
model_scope_advisory: 'Применяется к этой беседе со следующего сообщения.',
session_toolsets: 'Session Toolsets', // TODO: translate
session_toolsets_desc: 'Restrict available tools for this session (blank = use global config)', // TODO: translate
session_toolsets_global: 'Global (default)', // TODO: translate
session_toolsets_custom: 'Custom', // TODO: translate
session_toolsets_placeholder: 'tool1, tool2, \u2026', // TODO: translate
session_toolsets_apply: 'Apply', // TODO: translate
session_toolsets_clear: 'Clear (use global)', // TODO: translate
session_toolsets_applied: 'Toolsets updated', // TODO: translate
session_toolsets_cleared: 'Toolsets cleared — using global config', // TODO: translate
session_toolsets_failed: 'Failed to update toolsets: ', // TODO: translate
model_scope_toast: 'Применяется к этой беседе со следующего сообщения.',
reference_only_label: 'Только справка',
settings_label_skin: 'Скин',
settings_label_font_size: 'Размер шрифта',
font_size_small: 'Маленький',
font_size_default: 'Стандарт',
font_size_large: 'Большой',
settings_autosave_saving: 'Сохранение…',
settings_autosave_saved: 'Сохранено',
settings_autosave_failed: 'Не удалось сохранить',
settings_autosave_retry: 'Повторить',
workspace_empty_dir: 'Это рабочее пространство пусто.',
workspace_empty_no_path: 'Рабочее пространство не выбрано. Настройте его в Настройки → Рабочее пространство.',
available_personalities: 'Доступные личности:',
personality_switch_hint: '\n\nИспользуйте `/personality <name>` для переключения или `/personality none` для сброса.',
personalities_load_failed: 'Не удалось загрузить личности',
personality_cleared: 'Личность очищена',
personality_set: 'Личность: ',
failed_colon: 'Не удалось: ',
no_workspace: 'Нет рабочего пространства',
terminal_open_title: 'Открыть терминал рабочей области',
terminal_no_workspace_title: 'Выберите рабочую область, чтобы открыть терминал',
terminal_title: 'Терминал',
terminal_clear: 'Очистить',
terminal_copy_output: 'Копировать вывод',
terminal_restart: 'Перезапустить',
terminal_collapse: 'Свернуть',
terminal_expand: 'Развернуть',
terminal_close: 'Закрыть',
terminal_input_placeholder: 'Введите команду...',
terminal_start_failed: 'Не удалось запустить терминал: ',
terminal_input_failed: 'Ошибка ввода терминала: ',
terminal_copy_failed: 'Не удалось скопировать: ',
terminal_error: 'Ошибка терминала',
dialog_confirm_title: 'Подтвердить действие',
dialog_prompt_title: 'Введите значение',
dialog_confirm_btn: 'Подтвердить',
unsaved_confirm: 'У вас есть несохранённые изменения в предпросмотре. Отменить и перейти дальше?',
discard: 'Отменить',
save: 'Сохранить',
edit: 'Редактировать',
clear: 'Очистить',
create: 'Создать',
remove: 'Удалить',
save_title: 'Сохранить изменения',
edit_title: 'Редактировать этот файл',
saved: 'Сохранено',
save_failed: 'Не удалось сохранить: ',
image_load_failed: 'Не удалось загрузить изображение',
file_open_failed: 'Не удалось открыть файл',
downloading: (name) => `Скачиваю ${name}`,
double_click_rename: 'Дважды щёлкните, чтобы переименовать',
renamed_to: 'Переименовано в ',
rename_failed: 'Не удалось переименовать: ',
delete_title: 'Удалить',
delete_confirm: (name) => `Удалить ${name}?`,
delete_dir_confirm: (name) => `Удалить папку "${name}" и всё её содержимое?`,
rename_title: 'Переименовать',
rename_prompt: 'Новое имя:',
deleted: 'Удалено ',
delete_failed: 'Не удалось удалить: ',
reveal_in_finder: 'Показать в файловом менеджере',
reveal_failed: 'Не удалось открыть: ',
new_file_prompt: 'Имя нового файла (например, notes.md):',
project_name_prompt: 'Имя проекта:',
created: 'Создано ',
create_failed: 'Не удалось создать: ',
new_folder_prompt: 'Имя новой папки:',
folder_created: 'Папка создана ',
folder_create_failed: 'Не удалось создать папку: ',
workspace_auto_create_folder: 'Создать папку, если она не существует',
folder_add_as_space_btn: 'Добавить',
folder_add_as_space_msg: 'Добавить эту папку как новое пространство?',
folder_add_as_space_title: 'Добавить как пространство?',
remove_title: 'Удаление',
empty_dir: '(пусто)',
upload_failed: 'Не удалось загрузить: ',
all_uploads_failed: (n) => `Не удалось загрузить все ${n} файлов`,
archive_extracted: (n, c) => `Извлечено ${n} файл(ов) из ${c} архив(ов)`,
settings_title: 'Настройки',
settings_save_btn: 'Сохранить настройки',
settings_label_model: 'Модель по умолчанию',
settings_desc_model: 'Используется для новых бесед. Существующие беседы сохраняют выбранную модель.',
settings_label_send_key: 'Клавиша отправки',
settings_label_theme: 'Тема',
settings_label_language: 'Язык',
settings_label_token_usage: 'Показывать использование токенов',
settings_label_sidebar_density: 'Плотность боковой панели',
cmd_reasoning: 'Toggle thinking visibility (show/hide), set effort level, or check current status',
settings_label_external_sessions: 'Показывать внешние сеансы',
settings_label_sync_insights: 'Синхронизировать с Insights',
settings_label_check_updates: 'Проверять обновления',
settings_label_bot_name: 'Имя помощника',
settings_label_password: 'Пароль доступа',
settings_saved: 'Настройки сохранены',
settings_save_failed: 'Не удалось сохранить: ',
settings_load_failed: 'Не удалось загрузить настройки: ',
settings_saved_pw: 'Настройки сохранены (пароль задан — теперь требуется вход)',
settings_saved_pw_updated: 'Настройки сохранены (пароль обновлён)',
login_title: 'Вход',
login_subtitle: 'Введите пароль, чтобы продолжить',
login_placeholder: 'Пароль',
login_btn: 'Войти',
login_invalid_pw: 'Неверный пароль',
login_conn_failed: 'Не удалось подключиться',
tab_chat: 'Чат',
tab_tasks: 'Задачи',
tab_skills: 'Навыки',
tab_memory: 'Память',
tab_workspaces: 'Рабочие пространства',
tab_profiles: 'Профили',
tab_kanban: 'Kanban',
kanban_board: 'Board',
kanban_visible_tasks: '{0} visible tasks',
kanban_search_tasks: 'Search tasks',
kanban_all_assignees: 'All assignees',
kanban_all_tenants: 'All tenants',
kanban_include_archived: 'Include archived',
kanban_no_matching_tasks: 'No matching tasks',
kanban_no_data: 'No Kanban data',
kanban_unavailable: 'Kanban unavailable',
kanban_read_only: 'Read-only view',
kanban_empty: 'Empty',
kanban_task: 'Task',
kanban_no_description: 'No description',
kanban_refresh: 'Refresh',
kanban_status_triage: 'Triage',
kanban_status_todo: 'Todo',
kanban_status_ready: 'Ready',
kanban_status_running: 'Running',
kanban_status_blocked: 'Blocked',
kanban_status_done: 'Done',
kanban_comments_count: 'Comments ({0})',
kanban_events_count: 'Events ({0})',
kanban_links: 'Links',
kanban_parents: 'Parents',
kanban_children: 'Children',
kanban_runs_count: 'Runs ({0})',
kanban_no_comments: 'No comments',
kanban_no_events: 'No events',
kanban_no_runs: 'No runs',
kanban_new_task: 'New task',
kanban_add_comment: 'Add comment',
kanban_only_mine: 'Only mine',
kanban_bulk_action: 'Bulk action',
kanban_nudge_dispatcher: 'Nudge dispatcher',
kanban_stats: 'Stats',
kanban_worker_log: 'Worker log',
kanban_block: 'Block',
kanban_unblock: 'Unblock',
kanban_back_to_board: 'Back to board',
kanban_lanes_by_profile: 'Lanes by profile',
kanban_new_board: 'New board…',
kanban_rename_board: 'Rename current board…',
kanban_archive_board: 'Archive current board…',
kanban_archive_board_confirm: 'Archive board "{name}"? Tasks remain on disk and the board can be restored from kanban/boards/_archived/.',
kanban_board_archived: 'Board archived',
kanban_board_name: 'Name',
kanban_board_slug: 'Slug (lowercase, hyphens)',
kanban_board_description: 'Description (optional)',
kanban_board_icon: 'Icon (emoji, optional)',
kanban_board_color: 'Color (optional)',
kanban_board_name_required: 'Name is required',
kanban_board_slug_required: 'Slug is required',
kanban_card_start: 'start',
kanban_card_complete: 'complete',
kanban_card_archive: 'archive',
kanban_unassigned: 'unassigned',
kanban_status_archived: 'Archived',
tab_todos: 'Список дел',
tab_insights: 'Аналитика',
tab_settings: 'Настройки',
new_conversation: 'Новая беседа',
filter_conversations: 'Фильтр бесед...',
session_time_unknown: 'Неизвестно',
session_time_minutes_ago: (n) => `${n}м`,
session_time_hours_ago: (n) => `${n}ч`,
session_time_days_ago: (n) => `${n}д`,
session_time_last_week: '1н',
session_time_bucket_today: 'Сегодня',
session_time_bucket_yesterday: 'Вчера',
session_time_bucket_this_week: 'На этой неделе',
session_time_bucket_last_week: 'На прошлой неделе',
session_time_bucket_older: 'Ранее',
scheduled_jobs: 'Запланированные задания',
new_job: 'Новое задание',
loading: 'Загрузка...',
search_skills: 'Поиск навыков...',
new_skill: 'Новый навык',
personal_memory: 'Личная память',
current_task_list: 'Текущий список задач',
workspace_desc: 'Добавляйте рабочие пространства и переключайтесь между ними в своих сеансах.',
session_meta_messages: (n) => `${n} сообщ.`,
session_meta_children: (n) => `${n} ${n === 1 ? 'дочерн.' : 'дочерн.'}`,
new_profile: 'Новый профиль',
transcript: 'Транскрипт',
download_transcript: 'Скачать как Markdown',
import: 'Импорт',
settings_label_sound: 'Звук уведомления',
settings_desc_sound: 'Проигрывать звук, когда помощник завершает ответ.',
settings_label_notifications: 'Уведомления браузера',
settings_desc_notifications: 'Показывать системное уведомление, когда ответ готов, а вкладка находится в фоне.',
settings_desc_token_usage: 'Показывает количество входных и выходных токенов под каждым ответом помощника. Также переключается через /usage.',
settings_sidebar_density_compact: 'Компактно',
settings_sidebar_density_detailed: 'Подробно',
settings_desc_sidebar_density: 'Управляет тем, сколько метаданных показывается в списке сеансов на левой панели.',
settings_label_auto_title_refresh: 'Адаптивное обновление заголовка',
settings_auto_title_refresh_off: 'Выкл',
settings_auto_title_refresh_5: 'Каждые 5 обменов',
settings_auto_title_refresh_10: 'Каждые 10 обменов',
settings_auto_title_refresh_20: 'Каждые 20 обменов',
settings_desc_auto_title_refresh: 'Автоматически переформулирует заголовок сессии на основе последнего обмена, чтобы он оставался актуальным по мере развития беседы. Требует настроенную модель генерации заголовков.',
settings_desc_external_sessions: 'Показать беседы из CLI, Telegram, Discord, Slack и других каналов в списке сеансов. Нажмите для импорта и продолжения.',
settings_desc_sync_insights: 'Синхронизирует использование токенов WebUI в state.db, чтобы Hermes /insights включал данные браузерных сеансов. Выключено по умолчанию.',
settings_desc_check_updates: 'Показывает баннер, когда доступны более новые версии WebUI или Agent. Периодически выполняет git fetch в фоне.',
settings_desc_bot_name: 'Отображаемое имя помощника во всём интерфейсе. По умолчанию Hermes.',
settings_desc_password: 'Введите новый пароль, чтобы задать или изменить его. Оставьте пустым, чтобы сохранить текущую настройку.',
password_placeholder: 'Введите новый пароль…',
password_env_var_locked: 'Переменная окружения HERMES_WEBUI_PASSWORD сейчас задана и имеет приоритет. Сбросьте её и перезапустите сервер, чтобы управлять паролем отсюда.',
password_env_var_locked_placeholder: 'Заблокировано: задана переменная HERMES_WEBUI_PASSWORD',
disable_auth: 'Отключить авторизацию',
sign_out: 'Выйти',
// Providers panel (English fallback — native translations welcome in follow-up PRs)
providers_tab_title: 'Providers',
providers_section_title: 'Providers',
providers_section_meta: 'Manage API keys for AI providers. Changes take effect immediately.',
providers_status_configured: 'API key configured',
providers_status_not_configured: 'No API key',
providers_status_oauth: 'OAuth',
providers_status_api_key: 'API key',
providers_status_not_configured_label: 'Not configured',
providers_oauth_hint: 'Authenticated via OAuth. No API key needed.',
providers_oauth_config_yaml_hint: 'Token configured via config.yaml. To update, edit the providers section in your config.yaml or run hermes auth.',
providers_oauth_not_configured_hint: 'Not authenticated. Run hermes auth in the terminal to configure this provider.',
providers_save: 'Save',
providers_remove: 'Remove',
providers_saving: 'Saving…',
providers_removing: 'Removing…',
providers_enter_key: 'Please enter an API key',
providers_empty: 'No configurable providers found.',
providers_key_updated: 'API key saved',
providers_key_removed: 'API key removed',
providers_key_placeholder_new: 'sk-...',
providers_key_placeholder_replace: 'Enter new key to replace…',
cancel: 'Отмена',
create_job: 'Создать задание',
save_skill: 'Сохранить навык',
editing: 'Редактирование',
empty_title: 'Чем я могу помочь?',
empty_subtitle: 'Спрашивайте что угодно, запускайте команды, изучайте файлы или управляйте запланированными задачами.',
suggest_files: 'Какие файлы есть в этом рабочем пространстве?',
suggest_schedule: 'Что у меня сегодня в расписании?',
suggest_plan: 'Помоги спланировать небольшой проект.',
onboarding_badge: 'ПЕРВЫЙ ЗАПУСК',
onboarding_title: 'Добро пожаловать в Hermes Web UI',
onboarding_lead: 'Краткая пошаговая настройка проверит Hermes, сохранит рабочую конфигурацию провайдера, выберет рабочее пространство и модель и при желании защитит приложение паролем.',
onboarding_back: 'Назад',
onboarding_continue: 'Продолжить',
onboarding_skip: 'Пропустить настройку',
onboarding_skipped: 'Настройка пропущена — используется существующая конфигурация.',
onboarding_open: 'Открыть Hermes',
onboarding_step_system_title: 'Проверка системы',
onboarding_step_system_desc: 'Проверить Hermes Agent и видимость конфигурации.',
onboarding_step_setup_title: 'Настройка провайдера',
onboarding_step_setup_desc: 'Сохранить минимальную рабочую конфигурацию провайдера Hermes.',
onboarding_step_workspace_title: 'Рабочее пространство и модель',
onboarding_step_workspace_desc: 'Выбрать значения по умолчанию для новых сеансов и чатов.',
onboarding_step_password_title: 'Необязательный пароль',
onboarding_step_password_desc: 'Защитить Web UI перед тем, как делиться им.',
onboarding_step_finish_title: 'Готово',
onboarding_step_finish_desc: 'Проверьте настройки и войдите в приложение.',
onboarding_notice_system_ready: 'Hermes Agent, похоже, доступен из Web UI.',
onboarding_notice_system_unavailable: 'Hermes Agent ещё не полностью доступен. Bootstrap может установить его, но для настройки провайдера всё ещё может понадобиться терминал.',
onboarding_check_agent: 'Hermes Agent',
onboarding_check_agent_ready: 'Обнаружен и доступен для импорта',
onboarding_check_agent_missing: 'Отсутствует или доступен только частично',
onboarding_check_password: 'Пароль',
onboarding_check_password_enabled: 'Уже включён',
onboarding_check_password_disabled: 'Пока не включён',
onboarding_check_provider: 'Конфигурация провайдера',
onboarding_check_provider_ready: 'Готова к чату',
onboarding_check_provider_partial: 'Сохранена, но не завершена',
onboarding_check_provider_pending: 'Требует проверки',
onboarding_config_file: 'Файл конфигурации:',
onboarding_env_file: 'Файл .env:',
onboarding_unknown: 'Неизвестно',
onboarding_current_provider: 'Текущая конфигурация:',
onboarding_missing_imports: 'Отсутствующие импорты:',
onboarding_notice_setup_required: 'Выберите здесь простой путь настройки провайдера. Продвинутые OAuth-сценарии пока остаются в Hermes CLI.',
onboarding_notice_setup_already_ready: 'Уже обнаружена рабочая конфигурация провайдера Hermes. Вы можете оставить её или заменить здесь.',
onboarding_oauth_provider_ready_title: 'Провайдер уже авторизован',
onboarding_oauth_provider_ready_body: 'Этот экземпляр настроен на использование OAuth-провайдера (<strong>{provider}</strong>), настроенного через Hermes CLI. API-ключ здесь не нужен — нажмите «Продолжить», чтобы завершить настройку.',
onboarding_oauth_provider_not_ready_title: 'OAuth-провайдер ещё не авторизован',
onboarding_oauth_provider_not_ready_body: 'Этот экземпляр настроен на использование <strong>{provider}</strong>, который работает через OAuth, а не через API-ключ. Запустите <code>hermes auth</code> или <code>hermes model</code> в терминале, чтобы пройти авторизацию, затем обновите Web UI.',
onboarding_oauth_switch_hint: 'Или выберите ниже другой провайдер, чтобы перейти на настройку с ключом API:',
onboarding_notice_workspace: 'Эти значения используют те же API настроек, что и обычное приложение.',
onboarding_workspace_label: 'Рабочее пространство',
onboarding_workspace_or_path: 'Или укажите путь к рабочему пространству',
onboarding_workspace_placeholder: '/home/you/workspace',
onboarding_provider_label: 'Режим настройки',
onboarding_quick_setup_badge: 'Быстрая настройка',
provider_category_easy_start: 'Быстрый старт',
provider_category_self_hosted: 'Локальные / Open source',
provider_category_specialized: 'Специализированные',
onboarding_api_key_label: 'Ключ API',
onboarding_api_key_placeholder: 'Оставьте пустым, чтобы сохранить уже сохранённый ключ',
onboarding_api_key_label_optional: 'API key (optional)', // TODO: translate
onboarding_api_key_placeholder_optional: 'Leave blank for keyless servers', // TODO: translate
onboarding_api_key_help_keyless: 'Most LM Studio / Ollama / vLLM installs run keyless — leave this blank if your server doesn\'t require authentication. Use the Test connection button to verify.', // TODO: translate
oauth_login_codex: 'Login with Codex (ChatGPT)', // TODO: translate
oauth_codex_step1: 'Step 1: Visit this URL and enter the code', // TODO: translate
oauth_codex_step2: 'Step 2: Enter this code on the page', // TODO: translate
oauth_codex_polling: 'Waiting for authorization...', // TODO: translate
oauth_codex_success: 'Codex OAuth login successful!', // TODO: translate
oauth_codex_error: 'OAuth login failed', // TODO: translate
oauth_codex_expired: 'Code expired, please try again', // TODO: translate
onboarding_api_key_help_prefix: 'Сохраняется как секрет в вашем файле `.env` Hermes с помощью',
onboarding_base_url_label: 'Базовый URL',
onboarding_base_url_placeholder: 'https://your-endpoint.example/v1',
onboarding_base_url_help: 'Используйте это для OpenAI-compatible маршрутизаторов, self-hosted серверов, LiteLLM, Ollama, LM Studio, vLLM и похожих endpoint-ов.',
onboarding_model_label: 'Модель по умолчанию',
onboarding_workspace_help: 'Выберите модель, которую Hermes должен использовать для новых чатов после завершения настройки.',
onboarding_custom_model_placeholder: 'имя_вашей_модели',
onboarding_custom_model_help: 'Для собственных endpoint-ов укажите точный ID модели, который ожидает ваш сервер.',
onboarding_notice_password_enabled: 'Пароль уже настроен. Вводите новый только если хотите заменить текущий.',
onboarding_notice_password_recommended: 'Необязательно, но рекомендуется, если вы собираетесь открывать UI не только на localhost.',
onboarding_password_label: 'Пароль (необязательно)',
onboarding_password_placeholder: 'Оставьте пустым, чтобы пропустить',
onboarding_password_help: 'Пароли сохраняются через существующий API настроек и хэшируются на сервере.',
onboarding_notice_finish: 'Позже вы сможете снова открыть настройки и изменить любое из этих значений.',
onboarding_not_set: 'Не задано',
onboarding_password_will_enable: 'Будет включён',
onboarding_password_will_replace: 'Будет заменён текущий пароль',
onboarding_password_keep_existing: 'Оставить текущий пароль',
onboarding_password_remains_disabled: 'Останется отключённым',
onboarding_password_skipped: 'Пропустить пока',
onboarding_finish_help: 'После завершения в настройках сохранится <code>onboarding_completed</code>, и вы попадёте в обычное приложение.',
onboarding_error_choose_workspace: 'Выберите рабочее пространство перед продолжением.',
onboarding_error_choose_model: 'Выберите модель перед продолжением.',
onboarding_error_provider_required: 'Выберите режим настройки перед продолжением.',
onboarding_error_base_url_required: 'Для собственных endpoint-ов требуется базовый URL.',
onboarding_probe_test_button: 'Test connection', // TODO: translate
onboarding_probe_probing: 'Testing connection…', // TODO: translate
onboarding_probe_ok: 'Connected. {n} model(s) available.', // TODO: translate
onboarding_probe_error_generic: 'Could not reach the configured base URL.', // TODO: translate
onboarding_probe_error_invalid_url: 'Base URL must start with http:// or https://.', // TODO: translate
onboarding_probe_error_dns: 'Could not resolve the host. Check the URL or use the host\'s IP address.', // TODO: translate
onboarding_probe_error_connect_refused: 'Connection refused — the server may not be running on that address. From inside Docker, try the host IP instead of localhost.', // TODO: translate
onboarding_probe_error_timeout: 'The endpoint did not respond in time. Check that the server is running and the URL is correct.', // TODO: translate
onboarding_probe_error_http_4xx: 'The endpoint returned a client error. Check authentication and the URL path (typically ends in /v1).', // TODO: translate
onboarding_probe_error_http_5xx: 'The endpoint returned a server error. Check the LM Studio / Ollama server logs.', // TODO: translate
onboarding_probe_error_parse: 'The endpoint did not return a model list in the expected shape. Verify the URL points to the OpenAI-compatible API root.', // TODO: translate
onboarding_probe_error_unreachable: 'Could not reach the configured base URL.', // TODO: translate
onboarding_error_probe_failed: 'Could not validate the configured base URL.', // TODO: translate
onboarding_error_workspace_required: 'Рабочее пространство обязательно.',
onboarding_error_model_required: 'Модель обязательна.',
onboarding_complete: 'Первичная настройка завершена',
error_prefix: 'Ошибка: ',
not_available: 'н/д',
never: 'никогда',
add: 'Добавить',
add_failed: 'Не удалось добавить: ',
remove_failed: 'Не удалось удалить: ',
switch_failed: 'Не удалось переключить: ',
name_required: 'Требуется имя',
content_required: 'Требуется содержимое',
view: 'Просмотр',
dismiss: 'Скрыть',
disable: 'Отключить',
cron_no_jobs: 'Запланированные задания не найдены.',
cron_status_off: 'неактивно',
cron_status_paused: 'на паузе',
cron_status_error: 'ошибка',
cron_status_active: 'активно',
cron_status_running: 'выполняется\u2026',
cron_status_needs_attention: 'требует внимания',
cron_attention_desc: 'У этого повторяющегося задания нет времени следующего запуска. Планировщик мог не суметь вычислить следующий запуск.',
cron_attention_croniter_hint: 'В окружении Gateway может отсутствовать пакет croniter. Перезапустите Gateway с поддержкой cron, затем возобновите это задание.',
cron_attention_resume: 'Возобновить и пересчитать',
cron_jobs_project: 'Задания Cron',
cron_attention_run_once: 'Запустить один раз сейчас',
cron_attention_copy_diagnostics: 'Скопировать диагностику',
cron_diagnostics_copied: 'Диагностика cron скопирована',
cron_next: 'Следующий',
cron_last: 'Последний',
cron_run_now: 'Запустить сейчас',
cron_pause: 'Пауза',
cron_resume: 'Возобновить',
cron_job_name_placeholder: 'Имя задания',
cron_schedule_placeholder: 'Расписание',
cron_prompt_placeholder: 'Промпт',
cron_last_output: 'Последний вывод',
cron_all_runs: 'Все запуски',
cron_hide_runs: 'Скрыть запуски',
cron_no_runs_yet: '(пока запусков нет)',
cron_schedule_required_example: 'Требуется расписание (например, "0 9 * * *" или "every 1h")',
cron_schedule_required: 'Требуется расписание',
cron_prompt_required: 'Требуется промпт',
cron_job_created: 'Задание создано',
cron_duplicate: 'Дублировать',
cron_duplicated: 'Задание дублировано (приостановлено)',
cron_job_triggered: 'Задание запущено',
cron_job_paused: 'Задание поставлено на паузу',
cron_job_resumed: 'Задание возобновлено',
cron_job_updated: 'Задание обновлено',
cron_delete_confirm_title: 'Удалить cron-задание',
cron_delete_confirm_message: 'Это действие нельзя отменить.',
cron_job_deleted: 'Задание удалено',
cron_completion_status: (name, status) => `Cron-задание «${name}» — ${status}`,
status_failed: 'неудачно',
status_completed: 'завершено',
todos_no_active: 'В этой сессии нет активного списка задач.',
clear_conversation_title: 'Очистить беседу',
clear_conversation_message: 'Очистить все сообщения? Это действие нельзя отменить.',
clear_failed: 'Не удалось очистить: ',
skills_no_match: 'Подходящих навыков не найдено.',
linked_files: 'Связанные файлы',
skill_load_failed: 'Не удалось загрузить навык: ',
skill_file_load_failed: 'Не удалось загрузить файл: ',
skill_name_required: 'Требуется имя навыка',
skill_updated: 'Навык обновлён',
skill_created: 'Навык создан',
memory_notes_label: 'память (заметки)',
memory_saved: 'Память сохранена',
my_notes: 'Мои заметки',
user_profile: 'Пользовательский профиль',
no_notes_yet: 'Пока нет заметок.',
no_profile_yet: 'Пока нет профиля.',
workspace_choose_path: 'Выберите путь к рабочему пространству',
workspace_choose_path_meta: 'Добавьте проверенный путь и переключите эту беседу',
workspace_manage: 'Управление рабочими пространствами',
workspace_manage_meta: 'Открыть панель Spaces',
workspace_use_title: 'Использовать в текущем сеансе',
workspace_use: 'Использовать',
workspace_add_path_placeholder: 'Добавьте путь к рабочему пространству (например, /Users/you/project)',
workspace_paths_validated_hint: 'Перед сохранением пути проверяются на существование.',
workspace_drag_hint: 'Перетащите для изменения порядка',
workspace_reorder_failed: 'Не удалось изменить порядок',
workspace_added: 'Рабочее пространство добавлено',
workspace_renamed: 'Рабочее пространство переименовано',
workspace_remove_confirm_title: 'Удалить рабочее пространство',
workspace_remove_confirm_message: (path) => `Удалить «${path}»?`,
workspace_removed: 'Рабочее пространство удалено',
workspace_switch_prompt_title: 'Переключить рабочее пространство',
workspace_switch_prompt_message: 'Введите абсолютный путь к рабочему пространству, чтобы добавить его и переключить эту беседу.',
workspace_switch_prompt_confirm: 'Переключить',
workspace_switch_prompt_placeholder: '/Users/you/project',
workspace_not_added: 'Рабочее пространство не добавлено',
workspace_already_saved: 'Рабочее пространство уже сохранено — выберите его из списка',
workspace_busy_switch: 'Нельзя переключать рабочее пространство, пока агент работает',
discard_file_edits_title: 'Отменить изменения файлов?',
discard_file_edits_message: 'При переключении рабочих пространств несохранённые изменения в предпросмотре будут потеряны.',
workspace_switched_to: (name) => `Переключено на ${name}`,
profiles_no_profiles: 'Профили не найдены.',
profile_api_keys_configured: 'API-ключи настроены',
profile_gateway_running: 'Gateway запущен',
profile_gateway_stopped: 'Gateway остановлен',
profile_active: 'АКТИВЕН',
profile_no_configuration: 'Нет конфигурации',
profile_skill_count: (count) => {
const mod10 = count % 10;
const mod100 = count % 100;
const word = mod10 === 1 && mod100 !== 11
? 'навык'
: (mod10 >= 2 && mod10 <= 4 && (mod100 < 10 || mod100 >= 20)
? 'навыка'
: 'навыков');
return `${count} ${word}`;
},
profile_use: 'Использовать',
profile_switch_title: 'Переключиться на этот профиль',
profile_delete_title: 'Удалить этот профиль',
profile_default_label: '(по умолчанию)',
profile_name_placeholder: 'Название профиля (строчные буквы, a-z, 0-9, дефисы)',
profile_clone_label: 'Скопировать конфигурацию из активного профиля',
profile_base_url_placeholder: 'Базовый URL (необязательно, например http://localhost:11434)',
profile_api_key_placeholder: 'API-ключ (необязательно)',
manage_profiles: 'Управление профилями',
profiles_load_failed: 'Не удалось загрузить профили',
profiles_busy_switch: 'Нельзя переключать профили, пока агент работает',
profile_switched_new_conversation: (name) => `Переключено на профиль: ${name} — начата новая беседа`,
profile_switched: (name) => `Переключено на профиль: ${name}`,
profile_name_rule: 'Только строчные буквы, цифры, дефисы и подчёркивания',
profile_base_url_rule: 'Базовый URL должен начинаться с http:// или https://',
profile_created: (name) => `Профиль создан: ${name}`,
profile_delete_confirm_title: (name) => `Удалить профиль «${name}»?`,
profile_delete_confirm_message: 'Все сеансы, конфигурация, навыки и память этого профиля будут удалены безвозвратно. Это действие невозможно отменить.',
profile_deleted: (name) => `Профиль удалён: ${name}`,
active_conversation_none: 'Активная беседа не выбрана.',
active_conversation_meta: (title, count) => {
const mod10 = count % 10;
const mod100 = count % 100;
const word = mod10 === 1 && mod100 !== 11
? 'сообщение'
: (mod10 >= 2 && mod10 <= 4 && (mod100 < 10 || mod100 >= 20)
? 'сообщения'
: 'сообщений');
return `${title} · ${count} ${word}`;
},
settings_unsaved_changes: 'У вас есть несохранённые изменения.',
sign_out_failed: 'Не удалось выйти: ',
disable_auth_confirm_title: 'Отключить защиту паролем',
disable_auth_confirm_message: 'Любой сможет получить доступ к этому экземпляру.',
auth_disabled: 'Авторизация отключена — защита паролем снята',
disable_auth_failed: 'Не удалось отключить авторизацию: ',
bg_error_single: (title) => `В "${title}" возникла ошибка`,
bg_error_multi: (count) => `${count} сеансов столкнулись с ошибкой`,
skill_deleted: 'Навык удалён',
skill_delete_confirm: 'Удалить навык "{0}"?',
skills_empty_title: 'Выберите навык',
skills_empty_sub: 'Выберите навык на боковой панели, чтобы просмотреть его содержимое, или создайте новый.',
skills_edit: 'Редактировать',
skills_delete: 'Удалить',
skills_back_to: 'Назад к {0}',
tasks_empty_title: 'Выберите запланированное задание',
tasks_empty_sub: 'Выберите задание на боковой панели, чтобы просмотреть его детали и запуски, или создайте новое.',
workspaces_empty_title: 'Выберите пространство',
workspaces_empty_sub: 'Выберите пространство на боковой панели, чтобы просмотреть его файлы и настройки, или добавьте новое.',
profiles_empty_title: 'Выберите профиль',
profiles_empty_sub: 'Выберите профиль агента на боковой панели, чтобы просмотреть и изменить его настройки, или создайте новый.',
// skill form
skill_name: 'Имя',
skill_category: 'Категория',
skill_category_placeholder: 'Необязательно, например devops',
skill_content: 'Содержимое SKILL.md',
skill_content_placeholder: 'YAML-заголовок + тело markdown',
skill_rename_not_supported: 'Переименование навыка не поддерживается. Создайте новый навык и удалите старый.',
skill_metadata: 'Метаданные',
// cron form
cron_name_label: 'Имя',
cron_name_placeholder: 'Необязательно',
cron_schedule_label: 'Расписание',
cron_schedule_hint: "Cron-выражение или сокращение, например 'every 1h'.",
cron_prompt_label: 'Запрос',
cron_deliver_label: 'Доставлять вывод',
cron_deliver_local: 'Локально (только сохранение)',
cron_skills_label: 'Навыки',
cron_skills_placeholder: 'Добавить навыки (необязательно)…',
cron_skills_edit_hint: 'Список навыков нельзя изменить после создания.',
// workspace form
workspace_name_label: 'Имя',
workspace_name_placeholder: 'Необязательное понятное имя',
workspace_path_label: 'Путь',
workspace_path_required: 'Путь обязателен',
workspace_path_readonly: 'Путь нельзя изменить. Только переименование.',
workspace_new_title: 'Новое пространство',
// profile form
profile_name_label: 'Имя',
profile_base_url_label: 'Базовый URL',
profile_api_key_label: 'API-ключ',
// Session management and settings keys (en fallback — pending translation)
session_archive: 'Archive conversation',
session_archive_desc: 'Hide this conversation until archived is shown',
session_archive_failed: 'Archive failed: ',
session_archived: 'Session archived',
session_delete: 'Delete conversation',
session_delete_desc: 'Permanently remove this conversation',
session_duplicate: 'Duplicate conversation',
session_duplicate_desc: 'Create a copy with the same workspace and model',
session_duplicate_failed: 'Duplicate failed: ',
session_stop_response: 'Stop response',
session_stop_response_desc: 'Cancel the running response for this conversation',
session_duplicated: 'Session duplicated',
session_move_project: 'Move to project',
session_move_project_desc_has: 'Change the project for this conversation',
session_move_project_desc_none: 'Assign a project to this conversation',
session_pin: 'Pin conversation',
session_pin_desc: 'Keep this conversation at the top',
session_pin_failed: 'Pin failed: ',
session_restore: 'Restore conversation',
session_restore_desc: 'Bring this conversation back into the main list',
session_restored: 'Session restored',
session_unpin: 'Unpin conversation',
session_unpin_desc: 'Remove from pinned',
session_select_mode: 'Выбрать',
session_select_mode_desc: 'Выберите беседы для массового управления',
session_select_all: 'Выбрать все',
session_deselect_all: 'Снять выделение',
session_selected_count: '{0} выбрано',
session_batch_archive: 'В архив',
session_batch_delete: 'Удалить',
session_batch_move: 'Переместить в проект',
session_batch_delete_confirm: 'Удалить {0} бесед(ы)?',
session_batch_archive_confirm: 'Архивировать {0} бесед(ы)?',
session_no_selection: 'Ничего не выбрано',
settings_dropdown_appearance: 'Appearance',
settings_dropdown_conversation: 'Conversation',
settings_dropdown_preferences: 'Preferences',
settings_dropdown_providers: 'Providers',
settings_dropdown_system: 'System',
settings_heading_subtitle: 'Preferences, conversation tools, and system controls.',
settings_heading_title: 'Control Center',
settings_section_appearance_meta: 'Theme, accent colors, and visual style.',
settings_section_appearance_title: 'Appearance',
settings_section_conversation_title: 'Conversation',
settings_section_preferences_meta: 'Defaults and UI behavior for Hermes Web UI.',
settings_section_preferences_title: 'Preferences',
settings_section_system_meta: 'Instance version and access controls.',
settings_check_now: 'Проверить',
settings_checking: 'Проверка\u2026',
settings_up_to_date: 'Актуально \u2713',
settings_updates_available: 'Доступно обновлений: {count}',
settings_updates_disabled: 'Проверка обновлений отключена',
settings_update_check_failed: 'Ошибка проверки обновлений',
settings_label_workspace_panel_open: 'Открывать панель рабочей области по умолчанию',
settings_desc_workspace_panel_open: 'При включении панель файлов будет открываться автоматически в каждой новой сессии.',
open_in_browser: 'Открыть в браузере',
settings_section_system_title: 'System',
settings_tab_appearance: 'Appearance',
settings_tab_conversation: 'Conversation',
settings_tab_preferences: 'Preferences',
settings_tab_system: 'System',
status_no_tokens: 'No token data',
status_profile: 'Profile',
status_hermes_home: 'Hermes home',
status_started: 'Started',
status_tokens: 'Tokens',
status_unknown: 'Unknown',
cmd_branch:'Fork this conversation into a new session',
cmd_branch_usage:'/branch [name] — fork conversation (optionally with a name)',
branch_forked:'Forked into new session',
branch_failed:'Fork failed: ',
fork_from_here:'Fork from here',
forked_from:'Forked from',
cmd_yolo: 'Переключить YOLO режим (без подтверждений)',
yolo_no_session: 'Нет активного сеанса',
yolo_enabled: '⚡ YOLO режим ВКЛ — подтверждения пропущены',
yolo_disabled: 'YOLO режим ВЫКЛ',
yolo_pill_label: 'YOLO',
yolo_pill_title_active: 'YOLO режим активен — нажмите для отключения',
approval_skip_all: '⚡ Пропустить все в этом сеансе',
approval_skip_all_title: 'Пропустить все запросы подтверждения в этом сеансе',
// composer action tooltips
composer_send: 'Отправить сообщение',
composer_queue: 'Поставить в очередь',
composer_interrupt: 'Прервать и отправить',
composer_steer: 'Направить ответ',
composer_stop: 'Остановить генерацию',
composer_disabled_clarify: 'Ответьте на запрос о разъяснении',
composer_disabled_compression: 'Ожидание завершения сжатия',
composer_disabled_empty: 'Введите сообщение для отправки',
composer_mobile_workspace: 'Рабочее пространство',
composer_mobile_model: 'Модель',
composer_mobile_reasoning: 'Рассуждение',
composer_mobile_context: 'Контекст',
media_audio_label: 'Аудио',
media_svg_label: 'Диаграмма',
media_video_label: 'Видео',
csv_loading: 'Загрузка CSV',
csv_too_large: 'CSV-файл слишком большой для встроенного отображения',
csv_no_data: 'Недостаточно данных в CSV-файле',
csv_error: 'Не удалось загрузить CSV-файл',
csv_header_note: 'Первая строка отображается как заголовок таблицы',
excalidraw_loading: 'Загрузка диаграммы',
excalidraw_too_large: 'Файл Excalidraw слишком большой для отображения',
excalidraw_invalid: 'Неверный формат файла Excalidraw',
excalidraw_error: 'Не удалось загрузить файл Excalidraw',
excalidraw_label: 'Диаграмма',
excalidraw_download: 'Скачать',
excalidraw_empty: 'Пустая диаграмма',
excalidraw_render_error: 'Не удалось отобразить диаграмму',
excalidraw_simplified: 'Упрощённый предпросмотр SVG — не полностью идентичен оригиналу Excalidraw',
pdf_loading: 'Загрузка PDF {0}…',
pdf_too_large: 'PDF слишком большой для встроенного просмотра',
pdf_no_pages: 'Не удалось отобразить предварительный просмотр PDF',
pdf_error: 'Не удалось загрузить PDF',
pdf_download: 'Скачать PDF',
html_loading: 'Загрузка предпросмотра HTML…',
html_too_large: 'HTML слишком большой для встроенного просмотра',
html_error: 'Не удалось загрузить предпросмотр HTML',
html_open_full: 'Открыть на всю страницу',
html_sandbox_label: 'Предпросмотр HTML',
// TTS (#499)
tts_listen: 'Прослушать',
tts_not_supported: 'Синтез речи не поддерживается',
settings_label_tts: 'Синтез речи для ответов',
settings_desc_tts: 'Показать кнопку динамика на сообщениях ассистента',
settings_label_tts_auto_read: 'Авто-чтение ответов',
settings_desc_tts_auto_read: 'Автоматически озвучивать ответы ассистента',
// Composer voice-mode pref (#1488)
settings_label_voice_mode: 'Кнопка режима свободных рук',
settings_desc_voice_mode: 'Показывать кнопку голосового режима (аудиоволны) рядом с микрофоном диктовки. Hermes автоматически отправляет реплики после паузы и зачитывает ответы вслух. Требуется браузер с поддержкой распознавания речи и TTS.',
settings_label_tts_voice: 'Голос',
settings_desc_tts_voice: 'Выберите голос для синтеза речи',
settings_label_tts_rate: 'Скорость речи',
settings_label_tts_pitch: 'Тон речи',
checkpoint_date: 'Date', // TODO: translate
checkpoint_diff_files_changed: (n) => `${n} file${n === 1 ? '' : 's'} changed`, // TODO: translate
checkpoint_diff_no_changes: 'No differences found between this checkpoint and the current workspace.', // TODO: translate
checkpoint_diff_title: 'Changes in checkpoint', // TODO: translate
checkpoint_empty: 'No checkpoints found for this workspace.', // TODO: translate
checkpoint_error: 'Failed to load checkpoints', // TODO: translate
checkpoint_files: 'Files', // TODO: translate
checkpoint_loading: 'Loading checkpoints…', // TODO: translate
checkpoint_message: 'Message', // TODO: translate
checkpoint_restore: 'Restore', // TODO: translate
checkpoint_restore_confirm_message: (ckpt) => `Restore workspace to checkpoint "${ckpt}"? This will overwrite files with the saved versions. Files added after this checkpoint will not be deleted.`, // TODO: translate
checkpoint_restore_confirm_title: 'Restore checkpoint?', // TODO: translate
checkpoint_restored: 'Checkpoint restored', // TODO: translate
checkpoint_title: 'Checkpoints', // TODO: translate
checkpoint_view_diff: 'View diff', // TODO: translate
insights_activity_by_day: 'Activity by Day', // TODO: translate
insights_activity_by_hour: 'Activity by Hour', // TODO: translate
insights_cost: 'Estimated Cost', // TODO: translate
insights_footer: 'Showing data from the last {days} days', // TODO: translate
insights_input_tokens: 'Input', // TODO: translate
insights_messages: 'Messages', // TODO: translate
insights_models: 'Models', // TODO: translate
insights_no_cost: 'N/A', // TODO: translate
insights_output_tokens: 'Output', // TODO: translate
insights_peak_hour: 'Peak: {hour}', // TODO: translate
insights_sessions: 'Sessions', // TODO: translate
insights_title: 'Usage Analytics', // TODO: translate
insights_token_breakdown: 'Token Breakdown', // TODO: translate
insights_tokens: 'Tokens', // TODO: translate
insights_total: 'Total', // TODO: translate
settings_desc_api_redact: 'Self-hosted users can disable for transparency (not recommended for shared instances).', // TODO: translate
settings_label_api_redact: 'Redact sensitive data in API responses', // TODO: translate
subagent_children: 'Subagent sessions', // TODO: translate
},
es: {
_lang: 'es',
_label: 'Español',
_speech: 'es-ES',
// boot.js
cancelling: 'Cancelando…',
cancel_failed: 'Error al cancelar: ',
mic_denied: 'Acceso al micrófono denegado. Revisa los permisos del navegador.',
mic_no_speech: 'No se detectó voz. Inténtalo de nuevo.',
mic_network: 'El reconocimiento de voz no está disponible.',
mic_error: 'Error de entrada por voz: ',
session_imported: 'Sesión importada',
import_failed: 'Error al importar: ',
import_invalid_json: 'JSON inválido',
image_pasted: 'Imagen pegada: ',
// messages.js
edit_message: 'Editar mensaje',
regenerate: 'Regenerar respuesta',
copy: 'Copiar',
copied: '¡Copiado!',
copy_failed: 'Error al copiar',
diff_loading: 'Cargando diff',
diff_error: 'No se pudo cargar el archivo de parche',
diff_too_large: 'Archivo de parche demasiado grande para mostrar',
tree_view: '树形',
raw_view: '原始',
parse_failed_note: 'parse failed',
you: 'Tú',
mcp_servers_title: 'MCP 服务器',
mcp_servers_desc: '管理 config.yaml 中配置的 MCP 服务器。',
mcp_no_servers: '未配置 MCP 服务器。',
mcp_add_server: '+ 添加服务器',
mcp_field_name: '服务器名称',
mcp_transport_label: '传输类型',
mcp_field_command: '命令',
mcp_field_args: '参数(逗号分隔)',
mcp_field_url: 'URL',
mcp_field_timeout: '超时(秒)',
mcp_save: '保存',
mcp_cancel: '取消',
mcp_name_required: '需要服务器名称。',
mcp_url_required: 'HTTP 传输需要 URL。',
mcp_command_required: 'stdio 传输需要命令。',
mcp_saved: 'MCP 服务器已保存。',
mcp_save_failed: '保存 MCP 服务器失败。',
mcp_delete_confirm_title: '删除 MCP 服务器',
mcp_delete_confirm_message: '删除 MCP 服务器「{0}」?此操作无法撤销。',
mcp_deleted: 'MCP 服务器已删除。',
mcp_delete_failed: '删除 MCP 服务器失败。',
mcp_load_failed: '加载 MCP 服务器失败。',
thinking: 'Pensando',
expand_all: 'Expandir todo',
collapse_all: 'Contraer todo',
edit_failed: 'Error al editar: ',
regen_failed: 'Error al regenerar: ',
reconnect_active: 'Todavía se está generando una respuesta. ¿Recargar cuando termine?',
reconnect_finished: 'Había una respuesta en curso cuando te fuiste. Puede que los mensajes se hayan actualizado.',
// approval card
approval_heading: 'Se requiere aprobación',
approval_desc_prefix: 'Se detectó un comando peligroso',
approval_btn_once: 'Permitir una vez',
approval_btn_once_title: 'Permitir solo este comando (Enter)',
approval_btn_session: 'Permitir en la sesión',
approval_btn_session_title: 'Permitir durante esta sesión de conversación',
approval_btn_always: 'Permitir siempre',
approval_btn_always_title: 'Permitir siempre este patrón de comando',
approval_btn_deny: 'Denegar',
approval_btn_deny_title: 'Denegar — no ejecutar este comando',
approval_responding: 'Respondiendo…',
clarify_heading: 'Se necesita aclaración',
clarify_hint: 'Elige una opción o escribe tu propia respuesta abajo.',
clarify_other: 'Otra',
clarify_send: 'Enviar',
clarify_input_placeholder: 'Escribe tu respuesta…',
clarify_responding: 'Respondiendo…',
untitled: 'Sin título',
n_messages: (n) => `${n} mensajes`,
load_older_messages: '↑ Desplázate hacia arriba o haz clic para cargar mensajes anteriores',
queued_label: 'Enviar después de la respuesta',
queued_count: (n) => n === 1 ? '1 en cola' : `${n} en cola`,
queued_cancel: 'Cancelar mensaje en cola',
model_unavailable: ' (no disponible)',
model_unavailable_title: 'Este modelo ya no está en tu lista actual de proveedores',
provider_mismatch_warning: (m,p)=>`"${m}" puede no funcionar con tu proveedor configurado (${p}). Envía de todas formas, o ejecuta \`hermes model\` en la terminal para cambiar.`,
provider_mismatch_label: 'Proveedor incompatible',
model_not_found_label: 'Modelo no encontrado',
model_custom_label: 'ID de modelo personalizado',
model_custom_placeholder: 'p. ej. openai/gpt-5.4',
model_search_placeholder: 'Buscar modelos…',
model_search_no_results: 'No se encontraron modelos',
model_group_configured: 'Configurados',
ws_search_placeholder: 'Buscar espacios de trabajo…',
ws_no_results: 'No se encontraron espacios de trabajo',
session_toolsets: 'Session Toolsets', // TODO: translate
session_toolsets_desc: 'Restrict available tools for this session (blank = use global config)', // TODO: translate
session_toolsets_global: 'Global (default)', // TODO: translate
session_toolsets_custom: 'Custom', // TODO: translate
session_toolsets_placeholder: 'tool1, tool2, \u2026', // TODO: translate
session_toolsets_apply: 'Apply', // TODO: translate
session_toolsets_clear: 'Clear (use global)', // TODO: translate
session_toolsets_applied: 'Toolsets updated', // TODO: translate
session_toolsets_cleared: 'Toolsets cleared — using global config', // TODO: translate
session_toolsets_failed: 'Failed to update toolsets: ', // TODO: translate
model_scope_advisory: 'Se aplica a esta conversación desde tu próximo mensaje.',
model_scope_toast: 'Se aplica a esta conversación desde tu próximo mensaje.',
// commands.js
cmd_help: 'Listar los comandos disponibles',
cmd_clear: 'Borrar los mensajes de la conversación',
cmd_compress: 'Comprimir manualmente el contexto de la conversación (uso: /compress [tema])',
ctx_compress_hint: 'Comprimir contexto para liberar espacio →',
ctx_compress_action: '⚠ Comprimir ahora para liberar contexto',
cmd_compact_alias: 'Alias antiguo de /compress',
cmd_compact: 'Comprimir contexto de la conversación',
cmd_model: 'Cambiar de modelo (p. ej. /model gpt-4o)',
cmd_workspace: 'Cambiar de espacio de trabajo por nombre',
cmd_terminal: 'Abrir terminal del espacio de trabajo',
cmd_new: 'Iniciar una nueva sesión de chat',
cmd_usage: 'Activar o desactivar el uso de tokens',
cmd_theme: 'Cambiar apariencia (tema: system/dark/light, skin: default/ares/mono/slate/poseidon/sisyphus/charizard)',
cmd_personality: 'Cambiar la personalidad del agente',
cmd_skills: 'Listar las skills de Hermes disponibles',
available_commands: 'Comandos disponibles:',
type_slash: 'Escribe / para ver los comandos',
conversation_cleared: 'Conversación borrada',
command_label: 'Comando',
context_compaction_label: 'Compacción de contexto',
preserved_task_list_label: 'Lista de tareas conservada',
reference_only_label: 'Solo referencia',
model_usage: 'Uso: /model <name>',
no_model_match: 'No hay ningún modelo que coincida con "',
switched_to: 'Se cambió a ',
workspace_usage: 'Uso: /workspace <name>',
no_workspace_match: 'No hay ningún espacio de trabajo que coincida con "',
switched_workspace: 'Se cambió al espacio de trabajo: ',
workspace_switch_failed: 'Error al cambiar de espacio de trabajo: ',
new_session: 'Nueva sesión creada',
compressing: 'Solicitando compresión del contexto...',
compress_running_label: 'Comprimiendo',
compress_complete_label: 'Compresión completa',
auto_compress_label: 'Compresión automática',
compress_failed_label: 'La compresión falló',
focus_label: 'Tema',
token_usage_on: 'Uso de tokens activado',
usage_personality_none: 'none', // TODO: translate
token_usage_off: 'Uso de tokens desactivado',
theme_usage: 'Uso: /theme ',
theme_set: 'Tema: ',
no_active_session: 'No hay ninguna sesión activa',
cmd_queue: 'Poner mensaje en cola para el siguiente turno',
cmd_interrupt: 'Cancelar turno actual y enviar nuevo mensaje',
cmd_steer: 'Inyectar una corrección a mitad del turno sin interrumpir al agente',
cmd_queue_no_msg: 'Uso: /queue <mensaje>',
cmd_queue_not_busy: 'Sin tarea activa \u2014 env\u00eda normalmente',
cmd_queue_confirm: 'Mensaje en cola',
cmd_interrupt_no_msg: 'Uso: /interrupt <mensaje>',
cmd_interrupt_confirm: 'Interrumpido \u2014 enviando nuevo mensaje',
cmd_steer_no_msg: 'Uso: /steer <mensaje>',
cmd_steer_fallback: 'Steer no disponible — en cola para el siguiente turno',
cmd_steer_delivered: 'Steer entregado \u2014 el agente lo ver\u00e1 en su pr\u00f3ximo resultado de herramienta',
steer_leftover_queued: 'Steer en cola para el pr\u00f3ximo turno',
busy_steer_fallback: 'Steer no disponible — en cola para el siguiente turno',
busy_interrupt_confirm: 'Interrumpido \u2014 enviando nuevo mensaje',
settings_label_busy_input_mode: 'Modo de entrada ocupada',
settings_desc_busy_input_mode: 'Controla qué sucede al enviar mensajes mientras el agente está activo. Cola espera; Interrumpir cancela y empieza de nuevo; Steer inyecta una corrección sin interrumpir (usa cola si el agente no está disponible).',
settings_busy_input_mode_queue: 'Poner en cola',
settings_busy_input_mode_interrupt: 'Interrumpir turno actual',
settings_busy_input_mode_steer: 'Steer (corrección a mitad de turno)',
no_personalities: 'No se encontraron personalidades (añádelas a ~/.hermes/personalities/)',
available_personalities: 'Personalidades disponibles:',
personality_switch_hint: '\n\nUsa `/personality <name>` para cambiar, o `/personality none` para limpiar.',
personalities_load_failed: 'No se pudieron cargar las personalidades',
personality_cleared: 'Personalidad borrada',
personality_set: 'Personalidad: ',
failed_colon: 'Error: ',
// ui.js
no_workspace: 'Sin espacio de trabajo',
terminal_open_title: 'Abrir terminal del espacio de trabajo',
terminal_no_workspace_title: 'Selecciona un espacio de trabajo para abrir el terminal',
terminal_title: 'Terminal',
terminal_clear: 'Limpiar',
terminal_copy_output: 'Copiar salida',
terminal_restart: 'Reiniciar',
terminal_collapse: 'Contraer',
terminal_expand: 'Expandir',
terminal_close: 'Cerrar',
terminal_input_placeholder: 'Ejecuta un comando...',
terminal_start_failed: 'Error al iniciar el terminal: ',
terminal_input_failed: 'Error de entrada del terminal: ',
terminal_copy_failed: 'Error al copiar: ',
terminal_error: 'Error del terminal',
workspace_empty_no_path: 'No hay espacio de trabajo seleccionado. Configure un espacio de trabajo en Ajustes \u2192 Workspace para explorar archivos.',
workspace_empty_dir: 'Este espacio de trabajo está vacío.',
// workspace.js
unsaved_confirm: 'Tienes cambios sin guardar en la vista previa. ¿Descartar y navegar?',
save: 'Guardar',
edit: 'Editar',
save_title: 'Guardar cambios',
edit_title: 'Editar este archivo',
saved: 'Guardado',
save_failed: 'Error al guardar: ',
image_load_failed: 'No se pudo cargar la imagen',
file_open_failed: 'No se pudo abrir el archivo',
downloading: (name) => `Descargando ${name}`,
double_click_rename: 'Haz doble clic para renombrar',
renamed_to: 'Renombrado a ',
rename_failed: 'Error al renombrar: ',
delete_title: 'Eliminar',
delete_confirm: (name) => `¿Eliminar ${name}?`,
delete_dir_confirm: (name) => `¿Eliminar carpeta "${name}" y todo su contenido?`,
rename_title: 'Renombrar',
rename_prompt: 'Nuevo nombre:',
deleted: 'Eliminado ',
delete_failed: 'Error al eliminar: ',
reveal_in_finder: 'Mostrar en el gestor de archivos',
reveal_failed: 'Error al mostrar: ',
new_file_prompt: 'Nombre del archivo nuevo (p. ej. notes.md):',
created: 'Creado ',
create_failed: 'Error al crear: ',
new_folder_prompt: 'Nombre de la carpeta nueva:',
folder_created: 'Carpeta creada ',
folder_create_failed: 'Error al crear la carpeta: ',
workspace_auto_create_folder: 'Crear carpeta si no existe',
folder_add_as_space_btn: 'Añadir como espacio',
folder_add_as_space_msg: '¿Añadir esta carpeta como un nuevo espacio?',
folder_add_as_space_title: '¿Añadir como espacio?',
remove_title: 'Quitar',
empty_dir: '(vacío)',
upload_failed: 'Error al subir: ',
all_uploads_failed: (n) => `Fallaron las ${n} subida(s)`,
archive_extracted: (n, c) => `${n} archivo(s) extraído(s) de ${c} archivo(s) comprimido(s)`,
// settings panel
settings_title: 'Configuración',
settings_save_btn: 'Guardar configuración',
settings_label_model: 'Modelo predeterminado',
settings_desc_model: 'Se usa para conversaciones nuevas. Las conversaciones existentes conservan su modelo seleccionado.',
settings_label_send_key: 'Tecla de envío',
settings_label_theme: 'Tema',
settings_label_skin: 'Piel',
settings_label_font_size: 'Tamaño de fuente',
font_size_small: 'Pequeño',
font_size_default: 'Por defecto',
font_size_large: 'Grande',
settings_autosave_saving: 'Guardando…',
settings_autosave_saved: 'Guardado',
settings_autosave_failed: 'Error al guardar',
settings_autosave_retry: 'Reintentar',
settings_label_language: 'Idioma',
settings_label_token_usage: 'Mostrar uso de tokens',
settings_label_sidebar_density: 'Densidad de la barra lateral',
cmd_reasoning: 'Toggle thinking visibility (show/hide), set effort level, or check current status',
settings_label_external_sessions: 'Mostrar sesiones externas',
settings_label_sync_insights: 'Sincronizar con insights',
settings_label_check_updates: 'Buscar actualizaciones',
settings_label_bot_name: 'Nombre del asistente',
settings_label_password: 'Contraseña de acceso',
settings_saved: 'Configuración guardada',
settings_save_failed: 'Error al guardar: ',
settings_load_failed: 'Error al cargar la configuración: ',
settings_saved_pw: 'Configuración guardada — la contraseña queda activada y este navegador sigue autenticado',
settings_saved_pw_updated: 'Configuración guardada — contraseña actualizada',
// login page (used server-side via /api/i18n/login endpoint)
login_title: 'Iniciar sesión',
login_subtitle: 'Introduce tu contraseña para continuar',
login_placeholder: 'Contraseña',
login_btn: 'Entrar',
login_invalid_pw: 'Contraseña inválida',
login_conn_failed: 'Error de conexión',
dialog_confirm_title: 'Confirmar acción',
dialog_prompt_title: 'Introduce un valor',
dialog_confirm_btn: 'Confirmar',
discard: 'Descartar',
clear: 'Borrar',
create: 'Crear',
remove: 'Quitar',
project_name_prompt: 'Nombre del proyecto:',
// Sidebar & Tabs
tab_chat: 'Chat',
tab_tasks: 'Tareas',
tab_skills: 'Habilidades',
tab_memory: 'Memoria',
tab_workspaces: 'Espacios',
tab_profiles: 'Perfiles',
tab_kanban: 'Kanban',
kanban_board: 'Board',
kanban_visible_tasks: '{0} visible tasks',
kanban_search_tasks: 'Search tasks',
kanban_all_assignees: 'All assignees',
kanban_all_tenants: 'All tenants',
kanban_include_archived: 'Include archived',
kanban_no_matching_tasks: 'No matching tasks',
kanban_no_data: 'No Kanban data',
kanban_unavailable: 'Kanban unavailable',
kanban_read_only: 'Read-only view',
kanban_empty: 'Empty',
kanban_task: 'Task',
kanban_no_description: 'No description',
kanban_refresh: 'Refresh',
kanban_status_triage: 'Triage',
kanban_status_todo: 'Todo',
kanban_status_ready: 'Ready',
kanban_status_running: 'Running',
kanban_status_blocked: 'Blocked',
kanban_status_done: 'Done',
kanban_comments_count: 'Comments ({0})',
kanban_events_count: 'Events ({0})',
kanban_links: 'Links',
kanban_parents: 'Parents',
kanban_children: 'Children',
kanban_runs_count: 'Runs ({0})',
kanban_no_comments: 'No comments',
kanban_no_events: 'No events',
kanban_no_runs: 'No runs',
kanban_new_task: 'New task',
kanban_add_comment: 'Add comment',
kanban_only_mine: 'Only mine',
kanban_bulk_action: 'Bulk action',
kanban_nudge_dispatcher: 'Nudge dispatcher',
kanban_stats: 'Stats',
kanban_worker_log: 'Worker log',
kanban_block: 'Block',
kanban_unblock: 'Unblock',
kanban_back_to_board: 'Back to board',
kanban_lanes_by_profile: 'Lanes by profile',
kanban_new_board: 'New board…',
kanban_rename_board: 'Rename current board…',
kanban_archive_board: 'Archive current board…',
kanban_archive_board_confirm: 'Archive board "{name}"? Tasks remain on disk and the board can be restored from kanban/boards/_archived/.',
kanban_board_archived: 'Board archived',
kanban_board_name: 'Name',
kanban_board_slug: 'Slug (lowercase, hyphens)',
kanban_board_description: 'Description (optional)',
kanban_board_icon: 'Icon (emoji, optional)',
kanban_board_color: 'Color (optional)',
kanban_board_name_required: 'Name is required',
kanban_board_slug_required: 'Slug is required',
kanban_card_start: 'start',
kanban_card_complete: 'complete',
kanban_card_archive: 'archive',
kanban_unassigned: 'unassigned',
kanban_status_archived: 'Archived',
tab_todos: 'Todos',
tab_insights: 'Analíticas',
tab_settings: 'Ajustes',
new_conversation: 'Nueva conversación',
filter_conversations: 'Filtrar conversaciones...',
session_time_unknown: 'Desconocido',
session_time_minutes_ago: (n) => `${n}m`,
session_time_hours_ago: (n) => `${n}h`,
session_time_days_ago: (n) => `${n}d`,
session_time_last_week: '1sem',
session_time_bucket_today: 'Hoy',
session_time_bucket_yesterday: 'Ayer',
session_time_bucket_this_week: 'Esta semana',
session_time_bucket_last_week: 'La semana pasada',
session_time_bucket_older: 'Más antiguo',
scheduled_jobs: 'Tareas programadas',
new_job: 'Nueva tarea',
loading: 'Cargando...',
search_skills: 'Buscar skills...',
new_skill: 'Nueva skill',
personal_memory: 'Memoria personal',
current_task_list: 'Lista de tareas actual',
workspace_desc: 'Añade y cambia espacios de trabajo para tus sesiones.',
session_meta_messages: (n) => `${n} mens.`,
session_meta_children: (n) => `${n} ${n === 1 ? 'hijo' : 'hijos'}`,
new_profile: 'Nuevo perfil',
transcript: 'Transcripción',
download_transcript: 'Descargar como Markdown',
import: 'Importar',
// Settings detail
settings_label_sound: 'Sonido de notificación',
settings_desc_sound: 'Reproduce un sonido cuando el asistente termina una respuesta.',
settings_label_notifications: 'Notificaciones del navegador',
settings_desc_notifications: 'Muestra una notificación del sistema cuando una respuesta termina mientras la pestaña está en segundo plano.',
settings_desc_token_usage: 'Muestra el conteo de tokens de entrada/salida debajo de cada respuesta del asistente. También se puede alternar con /usage.',
settings_sidebar_density_compact: 'Compacta',
settings_sidebar_density_detailed: 'Detallada',
settings_desc_sidebar_density: 'Controla cuántos metadatos muestra la lista de sesiones en la barra lateral izquierda.',
settings_label_auto_title_refresh: 'Actualización adaptativa del título',
settings_auto_title_refresh_off: 'Desactivado',
settings_auto_title_refresh_5: 'Cada 5 intercambios',
settings_auto_title_refresh_10: 'Cada 10 intercambios',
settings_auto_title_refresh_20: 'Cada 20 intercambios',
settings_desc_auto_title_refresh: 'Regenera automáticamente el título de la sesión basándose en el último intercambio, manteniéndolo relevante a medida que evoluciona la conversación. Requiere un modelo LLM de generación de títulos configurado.',
settings_desc_external_sessions: 'Mostrar conversaciones de CLI, Telegram, Discord, Slack y otros canales en la lista de sesiones. Haz clic para importar y continuar.',
settings_desc_sync_insights: 'Refleja el uso de tokens de la WebUI en state.db para que hermes /insights incluya datos de sesiones del navegador. Desactivado por defecto.',
settings_desc_check_updates: 'Muestra un banner cuando haya versiones más nuevas de la WebUI o del Agent. Ejecuta periódicamente un git fetch en segundo plano.',
settings_desc_bot_name: 'Nombre visible del asistente en toda la UI. Por defecto es Hermes.',
settings_desc_password: 'Introduce una nueva contraseña para establecerla o cambiarla. Déjalo en blanco para mantener la configuración actual.',
password_placeholder: 'Introduce una contraseña nueva…',
password_env_var_locked: 'La variable de entorno HERMES_WEBUI_PASSWORD está definida y tiene prioridad. Quítala y reinicia el servidor para gestionar la contraseña desde aquí.',
password_env_var_locked_placeholder: 'Bloqueado: la variable HERMES_WEBUI_PASSWORD está definida',
disable_auth: 'Desactivar autenticación',
sign_out: 'Cerrar sesión',
// Providers panel (English fallback — native translations welcome in follow-up PRs)
providers_tab_title: 'Providers',
providers_section_title: 'Providers',
providers_section_meta: 'Manage API keys for AI providers. Changes take effect immediately.',
providers_status_configured: 'API key configured',
providers_status_not_configured: 'No API key',
providers_status_oauth: 'OAuth',
providers_status_api_key: 'API key',
providers_status_not_configured_label: 'Not configured',
providers_oauth_hint: 'Authenticated via OAuth. No API key needed.',
providers_oauth_config_yaml_hint: 'Token configured via config.yaml. To update, edit the providers section in your config.yaml or run hermes auth.',
providers_oauth_not_configured_hint: 'Not authenticated. Run hermes auth in the terminal to configure this provider.',
providers_save: 'Save',
providers_remove: 'Remove',
providers_saving: 'Saving…',
providers_removing: 'Removing…',
providers_enter_key: 'Please enter an API key',
providers_empty: 'No configurable providers found.',
providers_key_updated: 'API key saved',
providers_key_removed: 'API key removed',
providers_key_placeholder_new: 'sk-...',
providers_key_placeholder_replace: 'Enter new key to replace…',
cancel: 'Cancelar',
create_job: 'Crear tarea',
save_skill: 'Guardar skill',
editing: 'Editando',
// Empty state
empty_title: '¿En qué puedo ayudarte?',
empty_subtitle: 'Pregunta lo que quieras, ejecuta comandos, explora archivos o gestiona tus tareas programadas.',
suggest_files: '¿Qué archivos hay en este espacio de trabajo?',
suggest_schedule: '¿Qué tengo hoy en mi agenda?',
suggest_plan: 'Ayúdame a planificar un proyecto pequeño.',
// onboarding
onboarding_badge: 'PRIMER USO',
onboarding_title: 'Bienvenido a Hermes Web UI',
onboarding_lead: 'Una guía rápida verificará Hermes, guardará una configuración real del proveedor, elegirá un espacio de trabajo y un modelo, y opcionalmente protegerá la app con una contraseña.',
onboarding_back: 'Atrás',
onboarding_continue: 'Continuar',
onboarding_skip: 'Omitir configuración',
onboarding_skipped: 'Configuración omitida — se usa la configuración existente.',
onboarding_open: 'Abrir Hermes',
onboarding_step_system_title: 'Comprobación del sistema',
onboarding_step_system_desc: 'Verifica Hermes Agent y la visibilidad de la configuración.',
onboarding_step_setup_title: 'Configuración del proveedor',
onboarding_step_setup_desc: 'Guarda la configuración mínima real de Hermes.',
onboarding_step_workspace_title: 'Espacio de trabajo + modelo',
onboarding_step_workspace_desc: 'Elige los valores predeterminados para nuevas sesiones y chats.',
onboarding_step_password_title: 'Contraseña opcional',
onboarding_step_password_desc: 'Protege la Web UI antes de compartirla.',
onboarding_step_finish_title: 'Finalizar',
onboarding_step_finish_desc: 'Revisa todo y entra en la app.',
onboarding_notice_system_ready: 'Parece que Hermes Agent está accesible desde la Web UI.',
onboarding_notice_system_unavailable: 'Hermes Agent todavía no está totalmente disponible. Bootstrap puede instalarlo, pero la configuración del proveedor quizá aún requiera una terminal.',
onboarding_check_agent: 'Hermes Agent',
onboarding_check_agent_ready: 'Detectado e importable',
onboarding_check_agent_missing: 'Falta o solo es parcialmente importable',
onboarding_check_password: 'Contraseña',
onboarding_check_password_enabled: 'Ya está activada',
onboarding_check_password_disabled: 'Todavía no está activada',
onboarding_check_provider: 'Configuración del proveedor',
onboarding_check_provider_ready: 'Listo para chatear',
onboarding_check_provider_partial: 'Guardado pero incompleto',
onboarding_check_provider_pending: 'Necesita verificación',
onboarding_config_file: 'Archivo de configuración:',
onboarding_env_file: 'Archivo .env:',
onboarding_unknown: 'Desconocido',
onboarding_current_provider: 'Configuración actual:',
onboarding_missing_imports: 'Importaciones faltantes:',
onboarding_notice_setup_required: 'Elige aquí una ruta simple de proveedor. Los flujos OAuth avanzados siguen siendo del CLI de Hermes por ahora.',
onboarding_notice_setup_already_ready: 'Ya se detectó una configuración funcional del proveedor de Hermes. Puedes conservarla o reemplazarla aquí.',
onboarding_oauth_provider_ready_title: 'Proveedor ya autenticado',
onboarding_oauth_provider_ready_body: 'Esta instancia está configurada para usar un proveedor OAuth (<strong>{provider}</strong>) configurado mediante la CLI de Hermes. No se necesita clave API aquí — haz clic en Continuar para finalizar la configuración.',
onboarding_oauth_provider_not_ready_title: 'Proveedor OAuth no autenticado aún',
onboarding_oauth_provider_not_ready_body: 'Esta instancia está configurada para usar <strong>{provider}</strong>, que utiliza OAuth en lugar de una clave API. Ejecuta <code>hermes auth</code> o <code>hermes model</code> en una terminal para autenticarte y recarga la interfaz web.',
onboarding_oauth_switch_hint: 'O elige un proveedor diferente a continuación para cambiar a la configuración con clave API:',
onboarding_notice_workspace: 'Estos valores reutilizan las mismas APIs de configuración que la app normal.',
onboarding_workspace_label: 'Espacio de trabajo',
onboarding_workspace_or_path: 'O introduce la ruta de un espacio de trabajo',
onboarding_workspace_placeholder: '/home/you/workspace',
onboarding_provider_label: 'Modo de configuración',
onboarding_quick_setup_badge: 'configuración rápida',
provider_category_easy_start: 'Inicio rápido',
provider_category_self_hosted: 'Local / Open source',
provider_category_specialized: 'Especializados',
onboarding_api_key_label: 'API key',
onboarding_api_key_placeholder: 'Déjala en blanco para conservar una key ya guardada',
onboarding_api_key_label_optional: 'API key (optional)', // TODO: translate
onboarding_api_key_placeholder_optional: 'Leave blank for keyless servers', // TODO: translate
onboarding_api_key_help_keyless: 'Most LM Studio / Ollama / vLLM installs run keyless — leave this blank if your server doesn\'t require authentication. Use the Test connection button to verify.', // TODO: translate
oauth_login_codex: 'Login with Codex (ChatGPT)', // TODO: translate
oauth_codex_step1: 'Step 1: Visit this URL and enter the code', // TODO: translate
oauth_codex_step2: 'Step 2: Enter this code on the page', // TODO: translate
oauth_codex_polling: 'Waiting for authorization...', // TODO: translate
oauth_codex_success: 'Codex OAuth login successful!', // TODO: translate
oauth_codex_error: 'OAuth login failed', // TODO: translate
oauth_codex_expired: 'Code expired, please try again', // TODO: translate
onboarding_api_key_help_prefix: 'Se guarda como secreto en tu archivo .env de Hermes usando',
onboarding_base_url_label: 'Base URL',
onboarding_base_url_placeholder: 'https://tu-endpoint.example/v1',
onboarding_base_url_help: 'Úsalo para routers OpenAI-compatible, servidores autoalojados, LiteLLM, Ollama, LM Studio, vLLM o endpoints parecidos.',
onboarding_model_label: 'Modelo predeterminado',
onboarding_workspace_help: 'Elige el modelo que Hermes debe usar para nuevos chats cuando termine la configuración.',
onboarding_custom_model_placeholder: 'tu-modelo',
onboarding_custom_model_help: 'Para endpoints personalizados, introduce el identificador exacto del modelo que espera tu servidor.',
onboarding_notice_password_enabled: 'Ya hay una contraseña configurada. Introduce una nueva solo si quieres reemplazarla.',
onboarding_notice_password_recommended: 'Es opcional, pero recomendable si vas a exponer la UI más allá de localhost.',
onboarding_password_label: 'Contraseña (opcional)',
onboarding_password_placeholder: 'Déjala en blanco para omitirla',
onboarding_password_help: 'Las contraseñas se guardan mediante la API de configuración existente y se hashean en el servidor.',
onboarding_notice_finish: 'Puedes volver a abrir Configuración más tarde para cambiar cualquiera de estos valores.',
onboarding_not_set: 'Sin definir',
onboarding_password_will_enable: 'Se activará',
onboarding_password_will_replace: 'Se reemplazará',
onboarding_password_keep_existing: 'Mantener la contraseña actual',
onboarding_password_remains_disabled: 'Seguirá desactivada',
onboarding_password_skipped: 'Se omitirá por ahora',
onboarding_finish_help: 'Al finalizar se guarda <code>onboarding_completed</code> en la configuración y entras en la app normal.',
onboarding_error_choose_workspace: 'Elige un espacio de trabajo antes de continuar.',
onboarding_error_choose_model: 'Elige un modelo antes de continuar.',
onboarding_error_provider_required: 'Elige un modo de configuración antes de continuar.',
onboarding_error_base_url_required: 'La base URL es obligatoria para endpoints personalizados.',
onboarding_probe_test_button: 'Test connection', // TODO: translate
onboarding_probe_probing: 'Testing connection…', // TODO: translate
onboarding_probe_ok: 'Connected. {n} model(s) available.', // TODO: translate
onboarding_probe_error_generic: 'Could not reach the configured base URL.', // TODO: translate
onboarding_probe_error_invalid_url: 'Base URL must start with http:// or https://.', // TODO: translate
onboarding_probe_error_dns: 'Could not resolve the host. Check the URL or use the host\'s IP address.', // TODO: translate
onboarding_probe_error_connect_refused: 'Connection refused — the server may not be running on that address. From inside Docker, try the host IP instead of localhost.', // TODO: translate
onboarding_probe_error_timeout: 'The endpoint did not respond in time. Check that the server is running and the URL is correct.', // TODO: translate
onboarding_probe_error_http_4xx: 'The endpoint returned a client error. Check authentication and the URL path (typically ends in /v1).', // TODO: translate
onboarding_probe_error_http_5xx: 'The endpoint returned a server error. Check the LM Studio / Ollama server logs.', // TODO: translate
onboarding_probe_error_parse: 'The endpoint did not return a model list in the expected shape. Verify the URL points to the OpenAI-compatible API root.', // TODO: translate
onboarding_probe_error_unreachable: 'Could not reach the configured base URL.', // TODO: translate
onboarding_error_probe_failed: 'Could not validate the configured base URL.', // TODO: translate
onboarding_error_workspace_required: 'El espacio de trabajo es obligatorio.',
onboarding_error_model_required: 'El modelo es obligatorio.',
onboarding_complete: 'Onboarding completado',
// panel/runtime i18n
error_prefix: 'Error: ',
not_available: 'N/A',
never: 'never',
add: 'Add',
add_failed: 'Add failed: ',
remove_failed: 'Remove failed: ',
switch_failed: 'Switch failed: ',
name_required: 'Name is required',
content_required: 'Content is required',
view: 'View',
dismiss: 'Dismiss',
disable: 'Disable',
cron_no_jobs: 'No scheduled jobs found.',
cron_status_off: 'off',
cron_status_paused: 'paused',
cron_status_error: 'error',
cron_status_active: 'active',
cron_status_running: 'ejecutándose\u2026',
cron_status_needs_attention: 'needs attention',
cron_attention_desc: 'This recurring job has no next run time. The scheduler may have failed to compute its next run.',
cron_attention_croniter_hint: 'The Gateway runtime may be missing the croniter package. Restart the Gateway with cron support, then resume this job.',
cron_attention_resume: 'Resume and recalculate',
cron_jobs_project: 'Tareas Programadas',
cron_attention_run_once: 'Run once now',
cron_attention_copy_diagnostics: 'Copy diagnostics',
cron_diagnostics_copied: 'Cron diagnostics copied',
cron_next: 'Next',
cron_last: 'Last',
cron_run_now: 'Run now',
cron_pause: 'Pause',
cron_resume: 'Resume',
cron_job_name_placeholder: 'Job name',
cron_schedule_placeholder: 'Schedule',
cron_prompt_placeholder: 'Prompt',
cron_last_output: 'Last output',
cron_all_runs: 'All runs',
cron_hide_runs: 'Hide runs',
cron_no_runs_yet: '(no runs yet)',
cron_schedule_required_example: 'Schedule is required (e.g. "0 9 * * *" or "every 1h")',
cron_schedule_required: 'Schedule is required',
cron_prompt_required: 'Prompt is required',
cron_job_created: 'Job created',
cron_duplicate: 'Duplicar',
cron_duplicated: 'Trabajo duplicado (en pausa)',
cron_job_triggered: 'Job triggered',
cron_job_paused: 'Job paused',
cron_job_resumed: 'Job resumed',
cron_job_updated: 'Job updated',
cron_delete_confirm_title: 'Delete cron job',
cron_delete_confirm_message: 'This cannot be undone.',
cron_job_deleted: 'Job deleted',
cron_completion_status: (name, status) => `Cron "${name}" ${status}`,
status_failed: 'failed',
status_completed: 'completed',
todos_no_active: 'No active task list in this session.',
clear_conversation_title: 'Clear conversation',
clear_conversation_message: 'Clear all messages? This cannot be undone.',
clear_failed: 'Clear failed: ',
skills_no_match: 'No skills match.',
linked_files: 'Linked Files',
skill_load_failed: 'Could not load skill: ',
skill_file_load_failed: 'Could not load file: ',
skill_name_required: 'Skill name is required',
skill_updated: 'Skill updated',
skill_created: 'Skill created',
skill_deleted: 'Skill deleted',
skill_delete_confirm: 'Delete skill "{0}"?',
skills_empty_title: 'Select a skill',
skills_empty_sub: 'Pick a skill from the sidebar to view its contents, or create a new one.',
skills_edit: 'Edit',
skills_delete: 'Delete',
skills_back_to: 'Back to {0}',
tasks_empty_title: 'Select a scheduled job',
tasks_empty_sub: 'Pick a job from the sidebar to view its details and runs, or create a new one.',
workspaces_empty_title: 'Select a space',
workspaces_empty_sub: 'Pick a space from the sidebar to view its files and settings, or add a new one.',
profiles_empty_title: 'Select a profile',
profiles_empty_sub: 'Pick an agent profile from the sidebar to view and edit its settings, or create a new one.',
memory_notes_label: 'memory (notes)',
memory_saved: 'Memory saved',
my_notes: 'My Notes',
user_profile: 'User Profile',
no_notes_yet: 'No notes yet.',
no_profile_yet: 'No profile yet.',
workspace_choose_path: 'Choose workspace path',
workspace_choose_path_meta: 'Add a validated path and switch this conversation',
workspace_manage: 'Manage workspaces',
workspace_manage_meta: 'Open the Spaces panel',
workspace_use_title: 'Use in current session',
workspace_use: 'Use',
workspace_add_path_placeholder: 'Add workspace path (e.g. /home/user/my-project)',
workspace_paths_validated_hint: 'Paths are validated as existing directories before saving.',
workspace_drag_hint: 'Arrastra para reordenar',
workspace_reorder_failed: 'Error al reordenar',
workspace_added: 'Workspace added',
workspace_renamed: 'Espacio renombrado',
workspace_remove_confirm_title: 'Remove workspace',
workspace_remove_confirm_message: (path) => `Remove "${path}"?`,
workspace_removed: 'Workspace removed',
workspace_switch_prompt_title: 'Switch workspace',
workspace_switch_prompt_message: 'Enter an absolute workspace path to add and switch this conversation to.',
workspace_switch_prompt_confirm: 'Switch',
workspace_switch_prompt_placeholder: '/Users/you/project',
workspace_not_added: 'Workspace was not added',
workspace_already_saved: 'Workspace already saved — choose it from the list',
workspace_busy_switch: 'Cannot switch workspace while agent is running',
discard_file_edits_title: 'Discard file edits?',
discard_file_edits_message: 'Switching workspaces will discard unsaved file edits in the preview.',
workspace_switched_to: (name) => `Switched to ${name}`,
profiles_no_profiles: 'No profiles found.',
profile_api_keys_configured: 'API keys configured',
profile_gateway_running: 'Gateway running',
profile_gateway_stopped: 'Gateway stopped',
profile_active: 'ACTIVE',
profile_no_configuration: 'No configuration',
profile_skill_count: (count) => `${count} habilidad${count === 1 ? '' : 'es'}`,
profile_use: 'Use',
profile_switch_title: 'Switch to this profile',
profile_delete_title: 'Eliminar este perfil',
profile_default_label: '(predeterminado)',
profile_name_placeholder: 'Nombre del perfil (minúsculas, a-z, 0-9, guiones)',
profile_clone_label: 'Clonar configuración del perfil activo',
profile_base_url_placeholder: 'URL base (opcional, p. ej. http://localhost:11434)',
profile_api_key_placeholder: 'Clave API (opcional)',
manage_profiles: 'Manage profiles',
profiles_load_failed: 'Failed to load profiles',
profiles_busy_switch: 'Cannot switch profiles while agent is running',
profile_switched_new_conversation: (name) => `Switched to profile: ${name} — new conversation started`,
profile_switched: (name) => `Switched to profile: ${name}`,
profile_name_rule: 'Lowercase letters, numbers, hyphens, underscores only',
profile_base_url_rule: 'Base URL must start with http:// or https://',
profile_created: (name) => `Profile created: ${name}`,
profile_delete_confirm_title: (name) => `Delete profile "${name}"?`,
profile_delete_confirm_message: 'Todas las sesiones, configuración, habilidades y memoria de este perfil se eliminarán de forma permanente. Esta acción no se puede deshacer.',
profile_deleted: (name) => `Profile deleted: ${name}`,
active_conversation_none: 'No active conversation selected.',
active_conversation_meta: (title, count) => `${title} · ${count} message${count === 1 ? '' : 's'}`,
settings_unsaved_changes: 'You have unsaved changes.',
sign_out_failed: 'Error al cerrar sesión: ',
disable_auth_confirm_title: 'Desactivar protección por contraseña',
disable_auth_confirm_message: 'Anyone will be able to access this instance.',
auth_disabled: 'Autenticación desactivada — protección por contraseña eliminada',
disable_auth_failed: 'Failed to disable auth: ',
bg_error_single: (title) => `"${title}" has encountered an error`,
bg_error_multi: (count) => `${count} sessions have encountered an error`,
// skill form
skill_name: 'Nombre',
skill_category: 'Categoría',
skill_category_placeholder: 'Opcional, p. ej. devops',
skill_content: 'Contenido de SKILL.md',
skill_content_placeholder: 'Frontmatter YAML + cuerpo markdown',
skill_rename_not_supported: 'No se admite renombrar una habilidad. Crea una nueva y elimina la anterior.',
skill_metadata: 'Metadatos',
// cron form
cron_name_label: 'Nombre',
cron_name_placeholder: 'Opcional',
cron_schedule_label: 'Programación',
cron_schedule_hint: "Expresión cron o abreviatura como 'every 1h'.",
cron_prompt_label: 'Prompt',
cron_deliver_label: 'Entregar salida a',
cron_deliver_local: 'Local (solo guardar salida)',
cron_skills_label: 'Habilidades',
cron_skills_placeholder: 'Añadir habilidades (opcional)…',
cron_skills_edit_hint: 'La lista de habilidades no es editable después de crear.',
// workspace form
workspace_name_label: 'Nombre',
workspace_name_placeholder: 'Nombre opcional',
workspace_path_label: 'Ruta',
workspace_path_required: 'La ruta es obligatoria',
workspace_path_readonly: 'La ruta no se puede cambiar. Solo renombrar.',
workspace_new_title: 'Nuevo espacio',
// profile form
profile_name_label: 'Nombre',
profile_base_url_label: 'URL base',
profile_api_key_label: 'Clave API',
cmd_status: 'Show session info',
// Session management and settings keys (en fallback — pending translation)
session_archive: 'Archive conversation',
session_archive_desc: 'Hide this conversation until archived is shown',
session_archive_failed: 'Archive failed: ',
session_archived: 'Session archived',
session_delete: 'Delete conversation',
session_delete_desc: 'Permanently remove this conversation',
session_duplicate: 'Duplicate conversation',
session_duplicate_desc: 'Create a copy with the same workspace and model',
session_duplicate_failed: 'Duplicate failed: ',
session_stop_response: 'Stop response',
session_stop_response_desc: 'Cancel the running response for this conversation',
session_duplicated: 'Session duplicated',
session_move_project: 'Move to project',
session_move_project_desc_has: 'Change the project for this conversation',
session_move_project_desc_none: 'Assign a project to this conversation',
session_pin: 'Pin conversation',
session_pin_desc: 'Keep this conversation at the top',
session_pin_failed: 'Pin failed: ',
session_restore: 'Restore conversation',
session_restore_desc: 'Bring this conversation back into the main list',
session_restored: 'Session restored',
session_unpin: 'Unpin conversation',
session_unpin_desc: 'Remove from pinned',
session_select_mode: 'Seleccionar',
session_select_mode_desc: 'Selecciona conversaciones para gestión masiva',
session_select_all: 'Seleccionar todo',
session_deselect_all: 'Deseleccionar todo',
session_selected_count: '{0} seleccionadas',
session_batch_archive: 'Archivar',
session_batch_delete: 'Eliminar',
session_batch_move: 'Mover al proyecto',
session_batch_delete_confirm: '¿Eliminar {0} conversaciones?',
session_batch_archive_confirm: '¿Archivar {0} conversaciones?',
session_no_selection: 'Ninguna conversación seleccionada',
settings_dropdown_appearance: 'Appearance',
settings_dropdown_conversation: 'Conversation',
settings_dropdown_preferences: 'Preferences',
settings_dropdown_providers: 'Providers',
settings_dropdown_system: 'System',
settings_heading_subtitle: 'Preferences, conversation tools, and system controls.',
settings_heading_title: 'Control Center',
settings_section_appearance_meta: 'Theme, accent colors, and visual style.',
settings_section_appearance_title: 'Appearance',
settings_section_conversation_title: 'Conversation',
settings_section_preferences_meta: 'Defaults and UI behavior for Hermes Web UI.',
settings_section_preferences_title: 'Preferences',
settings_section_system_meta: 'Instance version and access controls.',
settings_check_now: 'Comprobar ahora',
settings_checking: 'Comprobando\u2026',
settings_up_to_date: 'Actualizado \u2713',
settings_updates_available: '{count} actualización(es) disponible(s)',
settings_updates_disabled: 'Comprobación de actualizaciones desactivada',
settings_update_check_failed: 'Error al comprobar actualizaciones',
settings_label_workspace_panel_open: 'Mantener panel de espacio abierto',
settings_desc_workspace_panel_open: 'Al activar, el panel de archivos se abre automáticamente en cada nueva sesión. Aún puedes cerrarlo manualmente.',
open_in_browser: 'Abrir en el navegador',
settings_section_system_title: 'System',
settings_tab_appearance: 'Appearance',
settings_tab_conversation: 'Conversation',
settings_tab_preferences: 'Preferences',
settings_tab_system: 'System',
status_no_tokens: 'No token data',
status_profile: 'Profile',
status_hermes_home: 'Hermes home',
status_started: 'Started',
status_tokens: 'Tokens',
status_unknown: 'Unknown',
cmd_yolo: 'Alternar modo YOLO (saltar aprobaciones)',
cmd_branch:'Fork this conversation into a new session',
cmd_branch_usage:'/branch [name] — fork conversation (optionally with a name)',
branch_forked:'Forked into new session',
branch_failed:'Fork failed: ',
fork_from_here:'Fork from here',
forked_from:'Forked from',
yolo_no_session: 'No hay sesión activa',
yolo_enabled: '⚡ Modo YOLO activado — aprobaciones omitidas',
yolo_disabled: 'Modo YOLO desactivado',
yolo_pill_label: 'YOLO',
yolo_pill_title_active: 'Modo YOLO activo — haz clic para desactivar',
approval_skip_all: '⚡ Saltar todo en esta sesión',
approval_skip_all_title: 'Saltar todas las solicitudes de aprobación en esta sesión',
// composer action tooltips
composer_send: 'Enviar mensaje',
composer_queue: 'Poner en cola',
composer_interrupt: 'Interrumpir y enviar',
composer_steer: 'Dirigir respuesta actual',
composer_stop: 'Detener generación',
composer_disabled_clarify: 'Responde a la solicitud de aclaración',
composer_disabled_compression: 'Esperando a que finalice la compresión',
composer_disabled_empty: 'Escribe un mensaje para enviar',
composer_mobile_workspace: 'Espacio de trabajo',
composer_mobile_model: 'Modelo',
composer_mobile_reasoning: 'Razonamiento',
composer_mobile_context: 'Contexto',
media_audio_label: 'Audio',
media_svg_label: 'Diagrama',
media_video_label: 'Vídeo',
csv_loading: 'Cargando CSV',
csv_too_large: 'Archivo CSV demasiado grande para mostrar en línea',
csv_no_data: 'El archivo CSV no tiene suficientes datos para mostrar como tabla',
csv_error: 'Error al cargar el archivo CSV',
csv_header_note: 'La primera fila se muestra como encabezado de tabla',
excalidraw_loading: 'Cargando diagrama',
excalidraw_too_large: 'Archivo Excalidraw demasiado grande para mostrar en línea',
excalidraw_invalid: 'Formato de archivo Excalidraw no válido',
excalidraw_error: 'Error al cargar archivo Excalidraw',
excalidraw_label: 'Diagrama',
excalidraw_download: 'Descargar',
excalidraw_empty: 'Diagrama vacío',
excalidraw_render_error: 'Error al renderizar el diagrama',
excalidraw_simplified: 'Vista previa SVG simplificada — no es idéntica al lienzo de Excalidraw',
pdf_loading: 'Cargando PDF {0}…',
pdf_too_large: 'PDF demasiado grande para vista previa',
pdf_no_pages: 'No se pudo renderizar la vista previa del PDF',
pdf_error: 'Error al cargar el PDF',
pdf_download: 'Descargar PDF',
html_loading: 'Cargando vista previa de HTML…',
html_too_large: 'HTML demasiado grande para vista previa',
html_error: 'Error al cargar la vista previa de HTML',
html_open_full: 'Abrir página completa',
html_sandbox_label: 'Vista previa de HTML',
// TTS (#499)
tts_listen: 'Escuchar',
tts_not_supported: 'Síntesis de voz no disponible',
settings_label_tts: 'Texto a voz para respuestas',
settings_desc_tts: 'Mostrar botón de altavoz en mensajes del asistente',
settings_label_tts_auto_read: 'Leer respuestas automáticamente',
settings_desc_tts_auto_read: 'Leer en voz alta las respuestas del asistente automáticamente',
// Composer voice-mode pref (#1488)
settings_label_voice_mode: 'Hands-free voice mode button', // TODO: translate
settings_desc_voice_mode: 'Show the voice-mode button (audio waveform) next to the dictation mic. Lets you speak naturally — Hermes auto-sends after a pause and reads replies aloud. Requires a browser that supports both speech recognition and TTS.', // TODO: translate
settings_label_tts_voice: 'Voz',
settings_desc_tts_voice: 'Seleccionar voz para síntesis de voz',
settings_label_tts_rate: 'Velocidad de voz',
settings_label_tts_pitch: 'Tono de voz',
checkpoint_date: 'Date', // TODO: translate
checkpoint_diff_files_changed: (n) => `${n} file${n === 1 ? '' : 's'} changed`, // TODO: translate
checkpoint_diff_no_changes: 'No differences found between this checkpoint and the current workspace.', // TODO: translate
checkpoint_diff_title: 'Changes in checkpoint', // TODO: translate
checkpoint_empty: 'No checkpoints found for this workspace.', // TODO: translate
checkpoint_error: 'Failed to load checkpoints', // TODO: translate
checkpoint_files: 'Files', // TODO: translate
checkpoint_loading: 'Loading checkpoints…', // TODO: translate
checkpoint_message: 'Message', // TODO: translate
checkpoint_restore: 'Restore', // TODO: translate
checkpoint_restore_confirm_message: (ckpt) => `Restore workspace to checkpoint "${ckpt}"? This will overwrite files with the saved versions. Files added after this checkpoint will not be deleted.`, // TODO: translate
checkpoint_restore_confirm_title: 'Restore checkpoint?', // TODO: translate
checkpoint_restored: 'Checkpoint restored', // TODO: translate
checkpoint_title: 'Checkpoints', // TODO: translate
checkpoint_view_diff: 'View diff', // TODO: translate
insights_activity_by_day: 'Activity by Day', // TODO: translate
insights_activity_by_hour: 'Activity by Hour', // TODO: translate
insights_cost: 'Estimated Cost', // TODO: translate
insights_footer: 'Showing data from the last {days} days', // TODO: translate
insights_input_tokens: 'Input', // TODO: translate
insights_messages: 'Messages', // TODO: translate
insights_models: 'Models', // TODO: translate
insights_no_cost: 'N/A', // TODO: translate
insights_output_tokens: 'Output', // TODO: translate
insights_peak_hour: 'Peak: {hour}', // TODO: translate
insights_sessions: 'Sessions', // TODO: translate
insights_title: 'Usage Analytics', // TODO: translate
insights_token_breakdown: 'Token Breakdown', // TODO: translate
insights_tokens: 'Tokens', // TODO: translate
insights_total: 'Total', // TODO: translate
settings_desc_api_redact: 'Self-hosted users can disable for transparency (not recommended for shared instances).', // TODO: translate
settings_label_api_redact: 'Redact sensitive data in API responses', // TODO: translate
voice_error: 'Voice not supported in this browser', // TODO: translate
voice_listening: 'Listening…', // TODO: translate
voice_mode_active: 'Voice mode on', // TODO: translate
voice_mode_off: 'Voice mode off', // TODO: translate
voice_speaking: 'Speaking…', // TODO: translate
voice_thinking: 'Thinking…', // TODO: translate
// Composer voice buttons (#1488)
voice_dictate: 'Dictate', // TODO: translate
voice_dictate_active: 'Stop dictation', // TODO: translate
voice_mode_toggle: 'Voice mode', // TODO: translate
voice_mode_toggle_active: 'Exit voice mode', // TODO: translate
subagent_children: 'Subagent sessions', // TODO: translate
},
de: {
_lang: 'de',
_label: 'Deutsch',
_speech: 'de-DE',
// boot.js
cancelling: 'Wird abgebrochen\u2026',
cancel_failed: 'Abbrechen fehlgeschlagen: ',
mic_denied: 'Mikrofonzugriff verweigert. Überprüfen Sie die Browserberechtigungen.',
mic_no_speech: 'Keine Sprache erkannt. Versuchen Sie es erneut.',
mic_network: 'Spracherkennung nicht verfügbar.',
mic_error: 'Spracheingabefehler: ',
session_imported: 'Sitzung importiert',
import_failed: 'Import fehlgeschlagen: ',
import_invalid_json: 'Ungültiges JSON',
image_pasted: 'Bild eingefügt: ',
// messages.js
edit_message: 'Nachricht bearbeiten',
regenerate: 'Antwort regenerieren',
copy: 'Kopieren',
copied: 'Kopiert!',
copy_failed: 'Kopieren fehlgeschlagen',
diff_loading: 'Lade Diff',
diff_error: 'Patch-Datei konnte nicht geladen werden',
diff_too_large: 'Patch-Datei zu groß für Inline-Anzeige',
tree_view: 'Baum',
raw_view: 'Rohdaten',
parse_failed_note: 'parse failed',
you: 'Du',
mcp_servers_title: 'MCP-Server',
mcp_servers_desc: 'MCP-Server in config.yaml verwalten.',
mcp_no_servers: 'Keine MCP-Server konfiguriert.',
mcp_add_server: '+ Server hinzufügen',
mcp_field_name: 'Servername',
mcp_transport_label: 'Transporttyp',
mcp_field_command: 'Befehl',
mcp_field_args: 'Argumente (kommagetrennt)',
mcp_field_url: 'URL',
mcp_field_timeout: 'Timeout (Sekunden)',
mcp_save: 'Speichern',
mcp_cancel: 'Abbrechen',
mcp_name_required: 'Servername ist erforderlich.',
mcp_url_required: 'URL für HTTP-Transport erforderlich.',
mcp_command_required: 'Befehl für stdio-Transport erforderlich.',
mcp_saved: 'MCP-Server gespeichert.',
mcp_save_failed: 'Fehler beim Speichern.',
mcp_delete_confirm_title: 'MCP-Server löschen',
mcp_delete_confirm_message: 'MCP-Server «{0}» löschen? Dies kann nicht rückgängig gemacht werden.',
mcp_deleted: 'MCP-Server gelöscht.',
mcp_delete_failed: 'Fehler beim Löschen.',
mcp_load_failed: 'Fehler beim Laden.',
thinking: 'Nachdenken',
expand_all: 'Alle ausklappen',
collapse_all: 'Alle einklappen',
edit_failed: 'Bearbeiten fehlgeschlagen: ',
regen_failed: 'Regeneration fehlgeschlagen: ',
reconnect_active: 'Eine Antwort wird noch generiert. Neu laden, wenn bereit?',
reconnect_finished: 'Eine Antwort war in Arbeit, als Sie zuletzt gegangen sind. Nachrichten könnten aktualisiert worden sein.',
// approval card
approval_heading: 'Genehmigung erforderlich',
approval_desc_prefix: 'Gefährlicher Befehl erkannt',
approval_btn_once: 'Einmal zulassen',
approval_btn_once_title: 'Diesen einen Befehl zulassen (Enter)',
approval_btn_session: 'Sitzung zulassen',
approval_btn_session_title: 'Für diese Konversationssitzung zulassen',
approval_btn_always: 'Immer zulassen',
approval_btn_always_title: 'Dieses Befehlsmuster immer zulassen',
approval_btn_deny: 'Ablehnen',
approval_btn_deny_title: 'Ablehnen \u2014 diesen Befehl nicht ausführen',
approval_responding: 'Antwortet\u2026',
clarify_heading: 'Klärung erforderlich',
clarify_hint: 'Wähle eine Option oder schreibe deine eigene Antwort unten.',
clarify_other: 'Andere',
clarify_send: 'Senden',
clarify_input_placeholder: 'Gib deine Antwort ein…',
clarify_responding: 'Antwortet\u2026',
untitled: 'Unbenannt',
n_messages: (n) => `${n} Nachrichten`,
load_older_messages: '↑ Nach oben scrollen oder klicken, um ältere Nachrichten zu laden',
queued_label: 'Wird nach Antwort gesendet',
queued_count: (n) => n === 1 ? '1 in Warteschlange' : `${n} in Warteschlange`,
queued_cancel: 'Nachricht abbrechen',
model_unavailable: ' (nicht verfügbar)',
model_unavailable_title: 'Dieses Modell ist nicht mehr in Ihrer aktuellen Provider-Liste',
provider_mismatch_warning: (m,p)=>`"${m}" funktioniert möglicherweise nicht mit Ihrem konfigurierten Provider (${p}). Trotzdem senden, oder \`hermes model\` im Terminal ausführen.`,
provider_mismatch_label: 'Provider-Konflikt',
model_not_found_label: 'Modell nicht gefunden',
// commands.js
cmd_help: 'Verfügbare Befehle auflisten',
archive_extracted: (n, c) => `${n} Datei(en) aus ${c} Archiv(en) entpackt`,
cmd_clear: 'Konversationsverlauf löschen',
cmd_compress: 'Kontext manuell komprimieren (Nutzung: /compress [Thema])',
ctx_compress_hint: 'Kontext komprimieren um Platz zu schaffen →',
ctx_compress_action: '⚠ Jetzt komprimieren um Kontext freizugeben',
cmd_compact_alias: 'Alte Alias für /compress',
cmd_model: 'Modell wechseln (z.B. /model gpt-4o)',
cmd_workspace: 'Workspace nach Namen wechseln',
cmd_terminal: 'Workspace-Terminal öffnen',
cmd_new: 'Neue Chat-Sitzung starten',
cmd_usage: 'Token-Verbrauchsanzeige umschalten',
cmd_theme: 'Darstellung wechseln (Theme: system/dark/light, Skin: default/ares/mono/slate/poseidon/sisyphus/charizard)',
cmd_personality: 'Agenten-Persönlichkeit wechseln',
cmd_skills: 'Verfügbare Hermes-Skills auflisten',
available_commands: 'Verfügbare Befehle:',
type_slash: 'Tippe / für Befehle',
conversation_cleared: 'Konversation gelöscht',
command_label: 'Befehl',
context_compaction_label: 'Kontextkomprimierung',
preserved_task_list_label: 'Beibehaltene Aufgabenliste',
reference_only_label: 'Nur Referenz',
model_usage: 'Nutzung: /model <name>',
no_model_match: 'Kein Modell gefunden für "',
switched_to: 'Gewechselt zu ',
workspace_usage: 'Nutzung: /workspace <name>',
no_workspace_match: 'Kein Workspace gefunden für "',
switched_workspace: 'Gewechselt zu Workspace: ',
workspace_switch_failed: 'Workspace-Wechsel fehlgeschlagen: ',
new_session: 'Neue Sitzung erstellt',
compressing: 'Kontext-Komprimierung wird angefordert...',
compress_running_label: 'Komprimierung',
compress_complete_label: 'Komprimierung abgeschlossen',
auto_compress_label: 'Automatische Komprimierung',
compress_failed_label: 'Komprimierung fehlgeschlagen',
focus_label: 'Thema',
token_usage_on: 'Token-Verbrauch an',
usage_personality_none: 'none', // TODO: translate
token_usage_off: 'Token-Verbrauch aus',
theme_usage: 'Nutzung: /theme ',
theme_set: 'Theme: ',
no_active_session: 'Keine aktive Sitzung',
model_scope_advisory: 'Gilt für diesen Chat ab Ihrer nächsten Nachricht.',
model_scope_toast: 'Gilt für diesen Chat ab Ihrer nächsten Nachricht.',
cmd_queue: 'Nachricht f\u00fcr den n\u00e4chsten Durchgang einreihen',
cmd_interrupt: 'Aktuellen Durchgang abbrechen und neue Nachricht senden',
cmd_steer: 'Korrektursignal einf\u00fcgen ohne Unterbrechung',
cmd_queue_no_msg: 'Verwendung: /queue <Nachricht>',
cmd_queue_not_busy: 'Keine aktive Aufgabe \u2014 normal senden',
cmd_queue_confirm: 'Nachricht eingereiht',
cmd_interrupt_no_msg: 'Verwendung: /interrupt <Nachricht>',
cmd_interrupt_confirm: 'Unterbrochen \u2014 neue Nachricht wird gesendet',
cmd_steer_no_msg: 'Verwendung: /steer <Nachricht>',
cmd_steer_fallback: 'Steer nicht verf\u00fcgbar \u2014 f\u00fcr n\u00e4chsten Durchgang eingereiht',
cmd_steer_delivered: 'Steer geliefert \u2014 der Agent sieht es bei seinem n\u00e4chsten Tool-Ergebnis',
steer_leftover_queued: 'Steer f\u00fcr n\u00e4chsten Durchgang eingereiht',
busy_steer_fallback: 'Steer nicht verf\u00fcgbar \u2014 f\u00fcr n\u00e4chsten Durchgang eingereiht',
busy_interrupt_confirm: 'Unterbrochen \u2014 neue Nachricht wird gesendet',
settings_label_busy_input_mode: 'Eingabemodus bei Besch\u00e4ftigung',
settings_desc_busy_input_mode: 'Steuert, was passiert, wenn Sie w\u00e4hrend der Agentenaktivit\u00e4t eine Nachricht senden. Warteschlange wartet; Unterbrechen bricht ab und startet neu; Steer f\u00fcgt eine Korrektur ein ohne zu unterbrechen.',
settings_busy_input_mode_queue: 'In Warteschlange einreihen',
settings_busy_input_mode_interrupt: 'Aktuellen Durchgang unterbrechen',
settings_busy_input_mode_steer: 'Steer (Korrektur ohne Unterbrechung)',
no_personalities: 'Keine Persönlichkeiten gefunden (füge sie in ~/.hermes/personalities/ hinzu)',
available_personalities: 'Verfügbare Persönlichkeiten:',
personality_switch_hint: '\n\nNutze `/personality <name>` zum Wechseln, oder `/personality none` zum Löschen.',
personalities_load_failed: 'Fehler beim Laden der Persönlichkeiten',
personality_cleared: 'Persönlichkeit gelöscht',
personality_set: 'Persönlichkeit: ',
failed_colon: 'Fehlgeschlagen: ',
// ui.js
no_workspace: 'Kein Workspace',
terminal_open_title: 'Workspace-Terminal öffnen',
terminal_no_workspace_title: 'Wähle einen Workspace, um das Terminal zu öffnen',
terminal_title: 'Terminal',
terminal_clear: 'Leeren',
terminal_copy_output: 'Ausgabe kopieren',
terminal_restart: 'Neu starten',
terminal_collapse: 'Einklappen',
terminal_expand: 'Ausklappen',
terminal_close: 'Schließen',
terminal_input_placeholder: 'Befehl ausführen...',
terminal_start_failed: 'Terminal konnte nicht gestartet werden: ',
terminal_input_failed: 'Terminal-Eingabe fehlgeschlagen: ',
terminal_copy_failed: 'Kopieren fehlgeschlagen: ',
terminal_error: 'Terminalfehler',
workspace_empty_no_path: 'Kein Workspace ausgewählt. Wähle einen Workspace unter Einstellungen \u2192 Workspace, um Dateien zu durchsuchen.',
workspace_empty_dir: 'Dieser Workspace ist leer.',
dialog_confirm_title: 'Aktion bestätigen',
dialog_prompt_title: 'Wert eingeben',
dialog_confirm_btn: 'Bestätigen',
// workspace.js
unsaved_confirm: 'Sie haben ungespeicherte Änderungen in der Vorschau. Verwerfen und fortfahren?',
discard: 'Verwerfen',
save: 'Speichern',
edit: 'Bearbeiten',
clear: 'Leeren',
create: 'Erstellen',
remove: 'Entfernen',
save_title: 'Änderungen speichern',
edit_title: 'Diese Datei bearbeiten',
saved: 'Gespeichert',
save_failed: 'Speichern fehlgeschlagen: ',
image_load_failed: 'Bild konnte nicht geladen werden',
file_open_failed: 'Datei konnte nicht geöffnet werden',
downloading: (name) => `Lade ${name} herunter\u2026`,
double_click_rename: 'Doppelklick zum Umbenennen',
renamed_to: 'Umbenannt in ',
rename_failed: 'Umbenennen fehlgeschlagen: ',
delete_title: 'Löschen',
delete_confirm: (name) => `${name} löschen?`,
delete_dir_confirm: (name) => `Ordner "${name}" und gesamten Inhalt löschen?`,
rename_title: 'Umbenennen',
rename_prompt: 'Neuer Name:',
deleted: 'Gelöscht ',
delete_failed: 'Löschen fehlgeschlagen: ',
reveal_in_finder: 'Im Dateimanager anzeigen',
reveal_failed: 'Anzeige fehlgeschlagen: ',
new_file_prompt: 'Neuer Dateiname (z.B. notes.md):',
project_name_prompt: 'Projektname:',
created: 'Erstellt ',
create_failed: 'Erstellen fehlgeschlagen: ',
new_folder_prompt: 'Neuer Ordnername:',
folder_created: 'Ordner erstellt ',
folder_create_failed: 'Ordner erstellen fehlgeschlagen: ',
workspace_auto_create_folder: 'Ordner erstellen, falls nicht vorhanden',
folder_add_as_space_btn: 'Als Bereich hinzufügen',
folder_add_as_space_msg: 'Diesen Ordner als neuen Bereich zur Liste hinzufügen?',
folder_add_as_space_title: 'Als Bereich hinzufügen?',
remove_title: 'Entfernen',
empty_dir: '(leer)',
upload_failed: 'Upload fehlgeschlagen: ',
all_uploads_failed: (n) => `Alle ${n} Upload(s) fehlgeschlagen`,
// settings panel
settings_title: 'Einstellungen',
settings_save_btn: 'Einstellungen speichern',
settings_label_model: 'Standard-Modell',
settings_desc_model: 'Wird für neue Chats verwendet. Bestehende Chats behalten ihr ausgewähltes Modell.',
settings_label_send_key: 'Sende-Taste',
settings_label_theme: 'Theme',
settings_label_skin: 'Skin',
settings_label_font_size: 'Font size',
font_size_small: 'Small',
font_size_default: 'Default',
font_size_large: 'Large',
settings_autosave_saving: 'Wird gespeichert…',
settings_autosave_saved: 'Gespeichert',
settings_autosave_failed: 'Speichern fehlgeschlagen',
settings_autosave_retry: 'Wiederholen',
settings_label_language: 'Sprache',
settings_label_token_usage: 'Token-Verbrauch anzeigen',
settings_label_sidebar_density: 'Seitenleistendichte',
cmd_reasoning: 'Toggle thinking visibility (show/hide), set effort level, or check current status',
settings_label_external_sessions: 'Externe Sitzungen anzeigen',
settings_label_sync_insights: 'Mit Insights synchronisieren',
settings_label_check_updates: 'Nach Updates suchen',
settings_label_bot_name: 'Assistenten-Name',
settings_label_password: 'Zugangspasswort',
settings_saved: 'Einstellungen gespeichert',
settings_save_failed: 'Speichern fehlgeschlagen: ',
settings_load_failed: 'Laden der Einstellungen fehlgeschlagen: ',
settings_saved_pw: 'Einstellungen gespeichert — Passwortschutz aktiviert und dieser Browser bleibt angemeldet',
settings_saved_pw_updated: 'Einstellungen gespeichert — Passwort aktualisiert',
// login page
login_title: 'Anmelden',
login_subtitle: 'Geben Sie Ihr Passwort ein, um fortzufahren',
login_placeholder: 'Passwort',
login_btn: 'Anmelden',
login_invalid_pw: 'Ungültiges Passwort',
login_conn_failed: 'Verbindung fehlgeschlagen',
dialog_confirm_title: 'Aktion bestätigen',
dialog_prompt_title: 'Wert eingeben',
dialog_confirm_btn: 'Bestätigen',
discard: 'Verwerfen',
clear: 'Leeren',
create: 'Erstellen',
remove: 'Entfernen',
project_name_prompt: 'Projektname:',
// Sidebar & Tabs
tab_chat: 'Chat',
tab_tasks: 'Aufgaben',
tab_skills: 'Skills',
tab_memory: 'Gedächtnis',
tab_workspaces: 'Spaces',
tab_profiles: 'Profile',
tab_kanban: 'Kanban',
kanban_board: 'Board',
kanban_visible_tasks: '{0} visible tasks',
kanban_search_tasks: 'Search tasks',
kanban_all_assignees: 'All assignees',
kanban_all_tenants: 'All tenants',
kanban_include_archived: 'Include archived',
kanban_no_matching_tasks: 'No matching tasks',
kanban_no_data: 'No Kanban data',
kanban_unavailable: 'Kanban unavailable',
kanban_read_only: 'Read-only view',
kanban_empty: 'Empty',
kanban_task: 'Task',
kanban_no_description: 'No description',
kanban_refresh: 'Refresh',
kanban_status_triage: 'Triage',
kanban_status_todo: 'Todo',
kanban_status_ready: 'Ready',
kanban_status_running: 'Running',
kanban_status_blocked: 'Blocked',
kanban_status_done: 'Done',
kanban_comments_count: 'Comments ({0})',
kanban_events_count: 'Events ({0})',
kanban_links: 'Links',
kanban_parents: 'Parents',
kanban_children: 'Children',
kanban_runs_count: 'Runs ({0})',
kanban_no_comments: 'No comments',
kanban_no_events: 'No events',
kanban_no_runs: 'No runs',
kanban_new_task: 'New task',
kanban_add_comment: 'Add comment',
kanban_only_mine: 'Only mine',
kanban_bulk_action: 'Bulk action',
kanban_nudge_dispatcher: 'Nudge dispatcher',
kanban_stats: 'Stats',
kanban_worker_log: 'Worker log',
kanban_block: 'Block',
kanban_unblock: 'Unblock',
kanban_back_to_board: 'Back to board',
kanban_lanes_by_profile: 'Lanes by profile',
kanban_new_board: 'New board…',
kanban_rename_board: 'Rename current board…',
kanban_archive_board: 'Archive current board…',
kanban_archive_board_confirm: 'Archive board "{name}"? Tasks remain on disk and the board can be restored from kanban/boards/_archived/.',
kanban_board_archived: 'Board archived',
kanban_board_name: 'Name',
kanban_board_slug: 'Slug (lowercase, hyphens)',
kanban_board_description: 'Description (optional)',
kanban_board_icon: 'Icon (emoji, optional)',
kanban_board_color: 'Color (optional)',
kanban_board_name_required: 'Name is required',
kanban_board_slug_required: 'Slug is required',
kanban_card_start: 'start',
kanban_card_complete: 'complete',
kanban_card_archive: 'archive',
kanban_unassigned: 'unassigned',
kanban_status_archived: 'Archived',
tab_todos: 'Todos',
tab_insights: 'Statistiken',
tab_settings: 'Einstellungen',
new_conversation: 'Neuer Chat',
filter_conversations: 'Chats filtern...',
scheduled_jobs: 'Geplante Aufgaben',
new_job: 'Neuer Job',
loading: 'Lädt...',
search_skills: 'Skills suchen...',
new_skill: 'Neuer Skill',
personal_memory: 'Persönliches Gedächtnis',
current_task_list: 'Aktuelle Aufgabenliste',
workspace_desc: 'Workspaces hinzufügen und wechseln.',
session_meta_messages: (n) => `${n} Nachr.`,
session_meta_children: (n) => `${n} ${n === 1 ? 'Subagent' : 'Subagents'}`,
new_profile: 'Neues Profil',
transcript: 'Protokoll',
download_transcript: 'Als Markdown herunterladen',
import: 'Importieren',
// Settings detail
settings_label_sound: 'Benachrichtigungston',
settings_desc_sound: 'Spielt einen Ton ab, wenn der Assistent eine Antwort beendet.',
settings_label_notifications: 'Browser-Benachrichtigungen',
settings_desc_notifications: 'Zeigt eine Systembenachrichtigung an, wenn eine Antwort fertiggestellt wird, während der Tab im Hintergrund ist.',
settings_desc_token_usage: 'Zeigt die Anzahl der Input/Output-Token unter jeder Antwort des Assistenten an. Auch umschaltbar mit /usage.',
settings_sidebar_density_compact: 'Kompakt',
settings_sidebar_density_detailed: 'Detailliert',
settings_desc_sidebar_density: 'Steuert, wie viele Metadaten die Sitzungsliste in der linken Seitenleiste anzeigt.',
settings_label_auto_title_refresh: 'Adaptive Titelaktualisierung',
settings_auto_title_refresh_off: 'Aus',
settings_auto_title_refresh_5: 'Alle 5 Antworten',
settings_auto_title_refresh_10: 'Alle 10 Antworten',
settings_auto_title_refresh_20: 'Alle 20 Antworten',
settings_desc_auto_title_refresh: 'Generiert den Sitzungstitel automatisch anhand des letzten Austauschs neu und hält ihn so aktuell, während sich das Gespräch entwickelt. Erfordert ein konfiguriertes LLM-Titelgenerierungsmodell.',
settings_desc_external_sessions: 'Zeigt Gespräche von CLI, Telegram, Discord, Slack und anderen Kanälen in der Sitzungsliste an. Klicken zum Importieren und Fortsetzen.',
settings_desc_sync_insights: 'Spiegelt den WebUI-Token-Verbrauch in die state.db, sodass hermes /insights Browser-Sitzungsdaten enthält. Standardmäßig aus.',
settings_desc_check_updates: 'Zeigt ein Banner an, wenn neuere Versionen der WebUI oder des Agenten verfügbar sind. Führt regelmäßig einen Git-Fetch im Hintergrund aus.',
settings_desc_bot_name: 'Anzeigename für den Assistenten in der UI. Standardmäßig Hermes.',
settings_desc_password: 'Geben Sie ein neues Passwort ein, um es zu setzen oder zu ändern. Leer lassen, um die aktuelle Einstellung beizubehalten.',
password_placeholder: 'Neues Passwort eingeben…',
password_env_var_locked: 'Die Umgebungsvariable HERMES_WEBUI_PASSWORD ist gesetzt und hat Vorrang. Entferne sie und starte den Server neu, um das Passwort hier zu verwalten.',
password_env_var_locked_placeholder: 'Gesperrt: HERMES_WEBUI_PASSWORD-Umgebungsvariable ist gesetzt',
disable_auth: 'Authentifizierung deaktivieren',
sign_out: 'Abmelden',
// Providers panel (English fallback — native translations welcome in follow-up PRs)
providers_tab_title: 'Providers',
providers_section_title: 'Providers',
providers_section_meta: 'Manage API keys for AI providers. Changes take effect immediately.',
providers_status_configured: 'API key configured',
providers_status_not_configured: 'No API key',
providers_status_oauth: 'OAuth',
providers_status_api_key: 'API key',
providers_status_not_configured_label: 'Not configured',
providers_oauth_hint: 'Authenticated via OAuth. No API key needed.',
providers_oauth_config_yaml_hint: 'Token configured via config.yaml. To update, edit the providers section in your config.yaml or run hermes auth.',
providers_oauth_not_configured_hint: 'Not authenticated. Run hermes auth in the terminal to configure this provider.',
providers_save: 'Save',
providers_remove: 'Remove',
providers_saving: 'Saving…',
providers_removing: 'Removing…',
providers_enter_key: 'Please enter an API key',
providers_empty: 'No configurable providers found.',
providers_key_updated: 'API key saved',
providers_key_removed: 'API key removed',
providers_key_placeholder_new: 'sk-...',
providers_key_placeholder_replace: 'Enter new key to replace…',
cancel: 'Abbrechen',
create_job: 'Job erstellen',
save_skill: 'Skill speichern',
editing: 'Bearbeitung',
// Empty state
empty_title: 'Wie kann ich helfen?',
empty_subtitle: 'Frage mich alles, führe Befehle aus, erkunde Dateien oder verwalte deine Aufgaben.',
suggest_files: 'Welche Dateien sind in diesem Workspace?',
suggest_schedule: 'Was steht heute auf meinem Plan?',
suggest_plan: 'Hilf mir, ein kleines Projekt zu planen.',
onboarding_password_will_enable: 'Wird aktiviert',
onboarding_password_will_replace: 'Wird ersetzt',
onboarding_password_keep_existing: 'Aktuelles Passwort beibehalten',
onboarding_password_remains_disabled: 'Bleibt deaktiviert',
profile_delete_confirm_message: 'Alle Sitzungen, Konfigurationen, Fähigkeiten und Erinnerungen dieses Profils werden dauerhaft gelöscht. Diese Aktion kann nicht rückgängig gemacht werden.',
// skill form
skill_name: 'Name',
skill_category: 'Kategorie',
skill_category_placeholder: 'Optional, z. B. devops',
skill_content: 'SKILL.md-Inhalt',
skill_content_placeholder: 'YAML-Frontmatter + Markdown-Text',
skill_rename_not_supported: 'Umbenennen einer Fähigkeit wird nicht unterstützt. Erstelle eine neue und lösche die alte.',
skill_metadata: 'Metadaten',
// cron form
cron_name_label: 'Name',
cron_duplicate: 'Duplizieren',
cron_duplicated: 'Aufgabe dupliziert (pausiert)',
cron_name_placeholder: 'Optional',
cron_schedule_label: 'Zeitplan',
cron_schedule_hint: "Cron-Ausdruck oder Kurzform wie 'every 1h'.",
cron_prompt_label: 'Prompt',
cron_deliver_label: 'Ausgabe senden an',
cron_deliver_local: 'Lokal (nur speichern)',
cron_skills_label: 'Fähigkeiten',
cron_skills_placeholder: 'Fähigkeiten hinzufügen (optional)…',
cron_skills_edit_hint: 'Die Fähigkeitenliste kann nach der Erstellung nicht bearbeitet werden.',
cron_status_running: 'läuft\u2026',
// workspace form
workspace_name_label: 'Name',
workspace_name_placeholder: 'Optionaler Anzeigename',
workspace_path_label: 'Pfad',
workspace_path_required: 'Pfad ist erforderlich',
workspace_path_readonly: 'Pfad kann nicht geändert werden. Nur umbenennen.',
workspace_new_title: 'Neuer Bereich',
// profile form
profile_name_label: 'Name',
profile_base_url_label: 'Basis-URL',
profile_api_key_label: 'API-Schlüssel',
// Session management and settings keys (en fallback — pending translation)
session_archive: 'Archive conversation',
session_archive_desc: 'Hide this conversation until archived is shown',
session_archive_failed: 'Archive failed: ',
session_archived: 'Session archived',
session_delete: 'Delete conversation',
session_delete_desc: 'Permanently remove this conversation',
session_duplicate: 'Duplicate conversation',
session_duplicate_desc: 'Create a copy with the same workspace and model',
session_duplicate_failed: 'Duplicate failed: ',
session_stop_response: 'Stop response',
session_stop_response_desc: 'Cancel the running response for this conversation',
session_duplicated: 'Session duplicated',
session_move_project: 'Move to project',
session_move_project_desc_has: 'Change the project for this conversation',
session_move_project_desc_none: 'Assign a project to this conversation',
session_pin: 'Pin conversation',
session_pin_desc: 'Keep this conversation at the top',
session_pin_failed: 'Pin failed: ',
session_restore: 'Restore conversation',
session_restore_desc: 'Bring this conversation back into the main list',
session_restored: 'Session restored',
session_unpin: 'Unpin conversation',
session_unpin_desc: 'Remove from pinned',
session_select_mode: 'Auswählen',
session_select_mode_desc: 'Konversationen für Massenverwaltung auswählen',
session_select_all: 'Alle auswählen',
session_deselect_all: 'Auswahl aufheben',
session_selected_count: '{0} ausgewählt',
session_batch_archive: 'Archivieren',
session_batch_delete: 'Löschen',
session_batch_move: 'Zum Projekt verschieben',
session_batch_delete_confirm: '{0} Konversationen löschen?',
session_batch_archive_confirm: '{0} Konversationen archivieren?',
session_no_selection: 'Keine Konversationen ausgewählt',
settings_dropdown_appearance: 'Appearance',
settings_dropdown_conversation: 'Conversation',
settings_dropdown_preferences: 'Preferences',
settings_dropdown_providers: 'Providers',
settings_dropdown_system: 'System',
settings_heading_subtitle: 'Preferences, conversation tools, and system controls.',
settings_heading_title: 'Control Center',
settings_section_appearance_meta: 'Theme, accent colors, and visual style.',
settings_section_appearance_title: 'Appearance',
settings_section_conversation_title: 'Conversation',
settings_section_preferences_meta: 'Defaults and UI behavior for Hermes Web UI.',
settings_section_preferences_title: 'Preferences',
settings_section_system_meta: 'Instance version and access controls.',
settings_check_now: 'Jetzt prüfen',
settings_checking: 'Prüfung\u2026',
settings_up_to_date: 'Aktuell \u2713',
settings_updates_available: '{count} Update(s) verfügbar',
settings_updates_disabled: 'Update-Prüfung deaktiviert',
settings_update_check_failed: 'Update-Prüfung fehlgeschlagen',
settings_label_workspace_panel_open: 'Arbeitsbereich-Panel standardmäßig öffnen',
settings_desc_workspace_panel_open: 'Wenn aktiviert, wird der Datei-Browser bei jeder neuen Sitzung automatisch geöffnet. Er kann jederzeit manuell geschlossen werden.',
workspace_drag_hint: 'Ziehen zum Neuordnen',
workspace_reorder_failed: 'Neuordnen fehlgeschlagen',
open_in_browser: 'Im Browser öffnen',
settings_section_system_title: 'System',
settings_tab_appearance: 'Appearance',
settings_tab_conversation: 'Conversation',
settings_tab_preferences: 'Preferences',
settings_tab_system: 'System',
status_no_tokens: 'No token data',
status_profile: 'Profile',
status_hermes_home: 'Hermes home',
status_started: 'Started',
status_tokens: 'Tokens',
status_unknown: 'Unknown',
cmd_yolo: 'YOLO-Modus umschalten',
yolo_no_session: 'Keine aktive Sitzung',
cmd_branch:'Fork this conversation into a new session',
cmd_branch_usage:'/branch [name] — fork conversation (optionally with a name)',
branch_forked:'Forked into new session',
branch_failed:'Fork failed: ',
fork_from_here:'Fork from here',
forked_from:'Forked from',
yolo_enabled: '⚡ YOLO-Modus AN — Genehmigungen übersprungen',
yolo_disabled: 'YOLO-Modus AUS',
yolo_pill_label: 'YOLO',
yolo_pill_title_active: 'YOLO-Modus aktiv — Klicken zum Deaktivieren',
approval_skip_all: '⚡ Alle in dieser Sitzung überspringen',
approval_skip_all_title: 'Alle Genehmigungsanfragen in dieser Sitzung überspringen',
// composer action tooltips
composer_send: 'Nachricht senden',
composer_queue: 'Nachricht einreihen',
composer_interrupt: 'Unterbrechen und senden',
composer_steer: 'Antwort steuern',
composer_stop: 'Generierung stoppen',
composer_disabled_clarify: 'Auf die Klärungsanfrage antworten',
composer_disabled_compression: 'Warte auf Abschluss der Komprimierung',
composer_disabled_empty: 'Nachricht eingeben zum Senden',
composer_mobile_workspace: 'Arbeitsbereich',
composer_mobile_model: 'Modell',
composer_mobile_reasoning: 'Reasoning',
composer_mobile_context: 'Kontext',
model_custom_label: 'Benutzerdefinierte Modell-ID',
model_custom_placeholder: 'z.B. openai/gpt-5.4',
model_search_placeholder: 'Modelle suchen…',
model_search_no_results: 'Keine Modelle gefunden',
model_group_configured: 'Konfiguriert',
ws_search_placeholder: 'Arbeitsbereiche suchen…',
ws_no_results: 'Keine Arbeitsbereiche gefunden',
session_toolsets: 'Session Toolsets', // TODO: translate
session_toolsets_desc: 'Restrict available tools for this session (blank = use global config)', // TODO: translate
session_toolsets_global: 'Global (default)', // TODO: translate
session_toolsets_custom: 'Custom', // TODO: translate
session_toolsets_placeholder: 'tool1, tool2, \u2026', // TODO: translate
session_toolsets_apply: 'Apply', // TODO: translate
session_toolsets_clear: 'Clear (use global)', // TODO: translate
session_toolsets_applied: 'Toolsets updated', // TODO: translate
session_toolsets_cleared: 'Toolsets cleared — using global config', // TODO: translate
session_toolsets_failed: 'Failed to update toolsets: ', // TODO: translate
session_time_unknown: 'Unbekannt',
session_time_minutes_ago: 'Vor {n} Minuten',
session_time_hours_ago: 'Vor {n} Stunden',
session_time_days_ago: 'Vor {n} Tagen',
session_time_last_week: 'Letzte Woche',
session_time_bucket_today: 'Heute',
session_time_bucket_yesterday: 'Gestern',
session_time_bucket_this_week: 'Diese Woche',
session_time_bucket_last_week: 'Letzte Woche',
session_time_bucket_older: 'Älter',
onboarding_badge: 'Ersteinrichtung',
onboarding_title: 'Willkommen bei Hermes',
onboarding_lead: 'Lassen Sie uns Ihren Agenten einrichten.',
onboarding_back: 'Zurück',
onboarding_continue: 'Weiter',
onboarding_skip: 'Überspringen',
onboarding_skipped: 'Einrichtung übersprungen',
onboarding_open: 'Einrichtung öffnen',
onboarding_step_system_title: 'Agent-Status',
onboarding_step_system_desc: 'Hermes Agent muss installiert und erreichbar sein.',
onboarding_step_setup_title: 'Einrichtung',
onboarding_step_setup_desc: 'Konfigurieren Sie einen Anbieter und ein Modell.',
onboarding_step_workspace_title: 'Arbeitsbereich',
onboarding_step_workspace_desc: 'Wählen Sie einen Arbeitsbereich für Ihre Dateien.',
onboarding_step_password_title: 'Passwort (optional)',
onboarding_step_password_desc: 'Sichern Sie den Zugriff mit einem Passwort.',
onboarding_step_finish_title: 'Fertig!',
onboarding_step_finish_desc: 'Ihr Agent ist bereit.',
onboarding_notice_system_ready: 'Agent ist bereit und erreichbar.',
onboarding_notice_system_unavailable: 'Agent nicht erreichbar. Bitte starten Sie Hermes Agent.',
onboarding_check_agent: 'Agent-Verbindung',
onboarding_check_agent_ready: 'Agent erreichbar',
onboarding_check_agent_missing: 'Agent nicht erreichbar',
onboarding_check_password: 'Passwortschutz',
onboarding_check_password_enabled: 'Passwort aktiviert',
onboarding_check_password_disabled: 'Kein Passwort',
onboarding_check_provider: 'Modellanbieter',
onboarding_check_provider_ready: 'Anbieter konfiguriert',
onboarding_check_provider_partial: 'Teilweise konfiguriert',
onboarding_check_provider_pending: 'Nicht konfiguriert',
onboarding_config_file: 'Konfigurationsdatei',
onboarding_env_file: 'Umgebungsdatei',
onboarding_unknown: 'Unbekannt',
onboarding_current_provider: 'Aktueller Anbieter',
onboarding_missing_imports: 'Fehlende Abhängigkeiten',
onboarding_notice_setup_required: 'Einrichtung erforderlich',
onboarding_notice_setup_already_ready: 'Bereits eingerichtet',
onboarding_oauth_provider_ready_title: 'Anbieter bereit',
onboarding_oauth_provider_ready_body: '{provider} ist konfiguriert. Kein API-Schlüssel erforderlich.',
onboarding_oauth_provider_not_ready_title: 'Anbieter nicht eingerichtet',
onboarding_oauth_provider_not_ready_body: '{provider} erfordert einen API-Schlüssel.',
onboarding_oauth_switch_hint: 'Zu OAuth wechseln',
onboarding_notice_workspace: 'Arbeitsbereich empfohlen',
onboarding_workspace_label: 'Arbeitsbereich',
onboarding_workspace_or_path: 'Name oder Pfad',
onboarding_workspace_placeholder: 'z.B. ~/projects/my-app',
onboarding_provider_label: 'Anbieter',
onboarding_quick_setup_badge: 'Schnelleinrichtung',
provider_category_easy_start: 'Einfach starten',
provider_category_self_hosted: 'Selbst gehostet',
provider_category_specialized: 'Spezialisiert',
onboarding_api_key_label: 'API-Schlüssel',
onboarding_api_key_placeholder: 'sk-…',
onboarding_api_key_label_optional: 'API key (optional)', // TODO: translate
onboarding_api_key_placeholder_optional: 'Leave blank for keyless servers', // TODO: translate
onboarding_api_key_help_keyless: 'Most LM Studio / Ollama / vLLM installs run keyless — leave this blank if your server doesn\'t require authentication. Use the Test connection button to verify.', // TODO: translate
oauth_login_codex: 'Login with Codex (ChatGPT)', // TODO: translate
oauth_codex_step1: 'Step 1: Visit this URL and enter the code', // TODO: translate
oauth_codex_step2: 'Step 2: Enter this code on the page', // TODO: translate
oauth_codex_polling: 'Waiting for authorization...', // TODO: translate
oauth_codex_success: 'Codex OAuth login successful!', // TODO: translate
oauth_codex_error: 'OAuth login failed', // TODO: translate
oauth_codex_expired: 'Code expired, please try again', // TODO: translate
onboarding_api_key_help_prefix: 'Gefunden unter',
onboarding_base_url_label: 'Base URL',
onboarding_base_url_placeholder: 'https://api.openai.com/v1',
onboarding_base_url_help: 'Verwenden Sie dies für OpenAI-kompatible Router, selbst gehostete Server, LiteLLM, Ollama, LM Studio, vLLM oder ähnliche Endpunkte.',
onboarding_model_label: 'Modell',
onboarding_workspace_help: 'Der Arbeitsbereich ist das Stammverzeichnis für Dateien und Terminal-Befehle.',
onboarding_custom_model_placeholder: 'Exakte Modell-ID eingeben',
onboarding_custom_model_help: 'Geben Sie die genaue Modell-ID ein, die Ihr Server erwartet.',
onboarding_notice_password_enabled: 'Passwortschutz aktiviert.',
onboarding_notice_password_recommended: 'Empfohlen für den öffentlichen Zugriff.',
onboarding_password_label: 'Passwort',
onboarding_password_placeholder: 'Passwort festlegen',
onboarding_password_help: 'Passwörter werden über die Einstellungs-API gespeichert und serverseitig gehasht.',
onboarding_notice_finish: 'Ihr Agent ist bereit!',
onboarding_not_set: 'Nicht festgelegt',
onboarding_password_skipped: 'Übersprungen',
onboarding_finish_help: 'Sie können dies später in den Einstellungen ändern.',
onboarding_error_choose_workspace: 'Bitte wählen Sie einen Arbeitsbereich.',
onboarding_error_choose_model: 'Bitte wählen Sie ein Modell.',
onboarding_error_provider_required: 'Anbieter erforderlich.',
onboarding_error_base_url_required: 'Base URL erforderlich.',
onboarding_probe_test_button: 'Test connection', // TODO: translate
onboarding_probe_probing: 'Testing connection…', // TODO: translate
onboarding_probe_ok: 'Connected. {n} model(s) available.', // TODO: translate
onboarding_probe_error_generic: 'Could not reach the configured base URL.', // TODO: translate
onboarding_probe_error_invalid_url: 'Base URL must start with http:// or https://.', // TODO: translate
onboarding_probe_error_dns: 'Could not resolve the host. Check the URL or use the host\'s IP address.', // TODO: translate
onboarding_probe_error_connect_refused: 'Connection refused — the server may not be running on that address. From inside Docker, try the host IP instead of localhost.', // TODO: translate
onboarding_probe_error_timeout: 'The endpoint did not respond in time. Check that the server is running and the URL is correct.', // TODO: translate
onboarding_probe_error_http_4xx: 'The endpoint returned a client error. Check authentication and the URL path (typically ends in /v1).', // TODO: translate
onboarding_probe_error_http_5xx: 'The endpoint returned a server error. Check the LM Studio / Ollama server logs.', // TODO: translate
onboarding_probe_error_parse: 'The endpoint did not return a model list in the expected shape. Verify the URL points to the OpenAI-compatible API root.', // TODO: translate
onboarding_probe_error_unreachable: 'Could not reach the configured base URL.', // TODO: translate
onboarding_error_probe_failed: 'Could not validate the configured base URL.', // TODO: translate
onboarding_error_workspace_required: 'Arbeitsbereich erforderlich.',
onboarding_error_model_required: 'Modell erforderlich.',
onboarding_complete: 'Einrichtung abgeschlossen!',
error_prefix: 'Fehler: ',
not_available: 'Nicht verfügbar',
never: 'Nie',
add: 'Hinzufügen',
add_failed: 'Hinzufügen fehlgeschlagen',
remove_failed: 'Entfernen fehlgeschlagen',
switch_failed: 'Wechsel fehlgeschlagen',
name_required: 'Name erforderlich.',
content_required: 'Inhalt erforderlich.',
view: 'Anzeigen',
dismiss: 'Verwerfen',
disable: 'Deaktivieren',
cron_no_jobs: 'Keine geplanten Aufgaben.',
cron_status_off: 'Inaktiv',
cron_status_paused: 'Pausiert',
cron_status_error: 'Fehler',
cron_status_active: 'Aktiv',
cron_status_needs_attention: 'Erfordert Aufmerksamkeit',
cron_attention_desc: 'Dieser Job hat Probleme.',
cron_attention_croniter_hint: 'Der Croniter-Ausdruck ist möglicherweise ungültig.',
cron_attention_resume: 'Fortsetzen',
cron_jobs_project: 'Cron-Jobs',
cron_attention_run_once: 'Einmal ausführen',
cron_attention_copy_diagnostics: 'Diagnose kopieren',
cron_diagnostics_copied: 'Diagnoseinformationen kopiert.',
cron_next: 'Nächstes: ',
cron_last: 'Letztes: ',
cron_run_now: 'Jetzt ausführen',
cron_pause: 'Pausieren',
cron_resume: 'Fortsetzen',
cron_job_name_placeholder: 'Aufgabenname',
cron_schedule_placeholder: '0 9 * * *',
cron_prompt_placeholder: 'Aufgabenbeschreibung',
cron_last_output: 'Letzte Ausgabe',
cron_all_runs: 'Alle Ausführungen',
cron_hide_runs: 'Ausführungen ausblenden',
cron_no_runs_yet: 'Noch keine Ausführungen.',
cron_schedule_required_example: 'z.B. 0 9 * * *, every 2h, 30m',
cron_schedule_required: 'Zeitplan erforderlich.',
cron_prompt_required: 'Beschreibung erforderlich.',
cron_job_created: 'Aufgabe erstellt.',
cron_job_triggered: 'Aufgabe gestartet.',
cron_job_paused: 'Aufgabe pausiert.',
cron_job_resumed: 'Aufgabe fortgesetzt.',
cron_job_updated: 'Aufgabe aktualisiert.',
cron_delete_confirm_title: 'Aufgabe löschen',
cron_delete_confirm_message: 'Sind Sie sicher?',
cron_job_deleted: 'Aufgabe gelöscht.',
cron_completion_status: 'Abschlussstatus',
status_failed: 'Fehlgeschlagen',
status_completed: 'Abgeschlossen',
todos_no_active: 'Keine aktiven Aufgaben.',
clear_conversation_title: 'Konversation löschen',
clear_conversation_message: 'Alle Nachrichten werden gelöscht.',
clear_failed: 'Löschen fehlgeschlagen.',
skills_no_match: 'Keine passende Fähigkeit.',
linked_files: 'Verknüpfte Dateien',
skill_load_failed: 'Fähigkeit konnte nicht geladen werden.',
skill_file_load_failed: 'Datei konnte nicht geladen werden.',
skill_name_required: 'Name erforderlich.',
skill_updated: 'Fähigkeit aktualisiert.',
skill_created: 'Fähigkeit erstellt.',
skill_deleted: 'Fähigkeit gelöscht.',
skill_delete_confirm: 'Fähigkeit wirklich löschen?',
skills_empty_title: 'Keine Fähigkeiten',
skills_empty_sub: 'Installieren Sie Fähigkeiten.',
skills_edit: 'Bearbeiten',
skills_delete: 'Löschen',
skills_back_to: 'Zurück',
tasks_empty_title: 'Keine Aufgaben',
tasks_empty_sub: 'Verwalten Sie geplante Aufgaben.',
workspaces_empty_title: 'Keine Arbeitsbereiche',
workspaces_empty_sub: 'Richten Sie Arbeitsbereiche ein.',
profiles_empty_title: 'Keine Profile',
profiles_empty_sub: 'Erstellen Sie Profile.',
memory_notes_label: 'Notizen',
memory_saved: 'Notiz gespeichert.',
my_notes: 'Meine Notizen',
user_profile: 'Benutzerprofil',
no_notes_yet: 'Noch keine Notizen.',
no_profile_yet: 'Noch kein Profil.',
workspace_choose_path: 'Arbeitsbereich wählen',
workspace_choose_path_meta: 'Wählen Sie ein Verzeichnis.',
workspace_manage: 'Arbeitsbereiche verwalten',
workspace_manage_meta: 'Hinzufügen, Umbenennen, Entfernen.',
workspace_use_title: 'Arbeitsbereich verwenden',
workspace_use: 'Arbeitsbereich',
workspace_add_path_placeholder: '~/projects/my-app',
workspace_paths_validated_hint: 'Pfad ist gültig.',
workspace_added: 'Arbeitsbereich hinzugefügt.',
workspace_renamed: 'Arbeitsbereich umbenannt.',
workspace_remove_confirm_title: 'Arbeitsbereich entfernen',
workspace_remove_confirm_message: 'Arbeitsbereich entfernen?',
workspace_removed: 'Arbeitsbereich entfernt.',
workspace_switch_prompt_title: 'Zum Arbeitsbereich wechseln',
workspace_switch_prompt_message: 'Wechsel zum Arbeitsbereich?',
workspace_switch_prompt_confirm: 'Wechseln',
workspace_switch_prompt_placeholder: 'Arbeitsbereichsname',
workspace_not_added: 'Arbeitsbereich nicht hinzugefügt.',
workspace_already_saved: 'Arbeitsbereich bereits vorhanden.',
workspace_busy_switch: 'Arbeitsbereich kann nicht gewechselt werden.',
discard_file_edits_title: 'Änderungen verwerfen',
discard_file_edits_message: 'Ungespeicherte Änderungen verwerfen?',
workspace_switched_to: 'Arbeitsbereich gewechselt zu: ',
profiles_no_profiles: 'Keine Profile vorhanden.',
profile_api_keys_configured: 'API-Schlüssel konfiguriert',
profile_gateway_running: 'Gateway läuft',
profile_gateway_stopped: 'Gateway gestoppt',
profile_active: 'Aktiv',
profile_no_configuration: 'Keine Konfiguration',
profile_skill_count: '{count} Fähigkeiten',
profile_use: 'Verwenden',
profile_switch_title: 'Profil wechseln',
profile_delete_title: 'Profil löschen',
profile_default_label: 'Standard',
profile_name_placeholder: 'Profilname',
profile_clone_label: 'Klonen',
profile_base_url_placeholder: 'https://api.openai.com/v1',
profile_api_key_placeholder: 'sk-…',
manage_profiles: 'Profile verwalten',
profiles_load_failed: 'Profile konnten nicht geladen werden.',
profiles_busy_switch: 'Profil kann nicht gewechselt werden.',
profile_switched_new_conversation: 'Profil gewechselt. Neue Konversation.',
profile_switched: 'Profil gewechselt.',
profile_name_rule: 'Nur alphanumerische Zeichen.',
profile_base_url_rule: 'Muss mit http:// oder https:// beginnen.',
profile_created: 'Profil erstellt.',
profile_delete_confirm_title: 'Profil löschen',
profile_deleted: 'Profil gelöscht.',
active_conversation_none: 'Keine aktive Konversation',
active_conversation_meta: 'Aktive Konversation',
settings_unsaved_changes: 'Ungespeicherte Änderungen',
sign_out_failed: 'Abmeldung fehlgeschlagen.',
disable_auth_confirm_title: 'Passwortschutz deaktivieren',
disable_auth_confirm_message: 'Zugriff ohne Authentifizierung?',
auth_disabled: 'Passwortschutz deaktiviert.',
disable_auth_failed: 'Deaktivieren fehlgeschlagen.',
bg_error_single: 'Hinterfrage {count} fehlgeschlagen.',
bg_error_multi: '{count} Hinterfragen fehlgeschlagen.',
media_audio_label: 'Audio',
media_svg_label: 'Diagramm',
media_video_label: 'Video',
csv_loading: 'CSV wird geladen',
csv_too_large: 'CSV-Datei zu groß für Inline-Anzeige',
csv_no_data: 'CSV-Datei enthält nicht genügend Daten',
csv_error: 'CSV-Datei konnte nicht geladen werden',
csv_header_note: 'Erste Zeile wird als Tabellenüberschrift angezeigt',
excalidraw_loading: 'Diagramm wird geladen',
excalidraw_too_large: 'Excalidraw-Datei zu groß für Inline-Anzeige',
excalidraw_invalid: 'Ungültiges Excalidraw-Dateiformat',
excalidraw_error: 'Excalidraw-Datei konnte nicht geladen werden',
excalidraw_label: 'Diagramm',
excalidraw_download: 'Herunterladen',
excalidraw_empty: 'Leeres Diagramm',
excalidraw_render_error: 'Diagramm konnte nicht gerendert werden',
excalidraw_simplified: 'Vereinfachte SVG-Vorschau — nicht pixelgenau zum Excalidraw-Canvas',
pdf_loading: 'PDF wird geladen {0}…',
pdf_too_large: 'PDF zu groß für Inline-Vorschau',
pdf_no_pages: 'PDF-Vorschau konnte nicht gerendert werden',
pdf_error: 'PDF konnte nicht geladen werden',
pdf_download: 'PDF herunterladen',
html_loading: 'HTML-Vorschau wird geladen…',
html_too_large: 'HTML zu groß für Inline-Vorschau',
html_error: 'HTML-Vorschau konnte nicht geladen werden',
html_open_full: 'Vollständige Seite öffnen',
html_sandbox_label: 'HTML-Vorschau',
// TTS (#499)
tts_listen: 'Anhören',
tts_not_supported: 'Sprachsynthese nicht verfügbar',
settings_label_tts: 'Text-zu-Sprache für Antworten',
settings_desc_tts: 'Lautsprecher-Symbol auf Assistenten-Nachrichten anzeigen',
settings_label_tts_auto_read: 'Antworten automatisch vorlesen',
settings_desc_tts_auto_read: 'Assistenten-Antworten automatisch vorlesen',
// Composer voice-mode pref (#1488)
settings_label_voice_mode: 'Hands-free voice mode button', // TODO: translate
settings_desc_voice_mode: 'Show the voice-mode button (audio waveform) next to the dictation mic. Lets you speak naturally — Hermes auto-sends after a pause and reads replies aloud. Requires a browser that supports both speech recognition and TTS.', // TODO: translate
settings_label_tts_voice: 'Stimme',
settings_desc_tts_voice: 'Stimme für Sprachsynthese auswählen',
settings_label_tts_rate: 'Sprechgeschwindigkeit',
settings_label_tts_pitch: 'Tonhöhe',
checkpoint_date: 'Date', // TODO: translate
checkpoint_diff_files_changed: (n) => `${n} file${n === 1 ? '' : 's'} changed`, // TODO: translate
checkpoint_diff_no_changes: 'No differences found between this checkpoint and the current workspace.', // TODO: translate
checkpoint_diff_title: 'Changes in checkpoint', // TODO: translate
checkpoint_empty: 'No checkpoints found for this workspace.', // TODO: translate
checkpoint_error: 'Failed to load checkpoints', // TODO: translate
checkpoint_files: 'Files', // TODO: translate
checkpoint_loading: 'Loading checkpoints…', // TODO: translate
checkpoint_message: 'Message', // TODO: translate
checkpoint_restore: 'Restore', // TODO: translate
checkpoint_restore_confirm_message: (ckpt) => `Restore workspace to checkpoint "${ckpt}"? This will overwrite files with the saved versions. Files added after this checkpoint will not be deleted.`, // TODO: translate
checkpoint_restore_confirm_title: 'Restore checkpoint?', // TODO: translate
checkpoint_restored: 'Checkpoint restored', // TODO: translate
checkpoint_title: 'Checkpoints', // TODO: translate
checkpoint_view_diff: 'View diff', // TODO: translate
insights_activity_by_day: 'Activity by Day', // TODO: translate
insights_activity_by_hour: 'Activity by Hour', // TODO: translate
insights_cost: 'Estimated Cost', // TODO: translate
insights_footer: 'Showing data from the last {days} days', // TODO: translate
insights_input_tokens: 'Input', // TODO: translate
insights_messages: 'Messages', // TODO: translate
insights_models: 'Models', // TODO: translate
insights_no_cost: 'N/A', // TODO: translate
insights_output_tokens: 'Output', // TODO: translate
insights_peak_hour: 'Peak: {hour}', // TODO: translate
insights_sessions: 'Sessions', // TODO: translate
insights_title: 'Usage Analytics', // TODO: translate
insights_token_breakdown: 'Token Breakdown', // TODO: translate
insights_tokens: 'Tokens', // TODO: translate
insights_total: 'Total', // TODO: translate
settings_desc_api_redact: 'Self-hosted users can disable for transparency (not recommended for shared instances).', // TODO: translate
settings_label_api_redact: 'Redact sensitive data in API responses', // TODO: translate
voice_error: 'Voice not supported in this browser', // TODO: translate
voice_listening: 'Listening…', // TODO: translate
voice_mode_active: 'Voice mode on', // TODO: translate
voice_mode_off: 'Voice mode off', // TODO: translate
voice_speaking: 'Speaking…', // TODO: translate
voice_thinking: 'Thinking…', // TODO: translate
// Composer voice buttons (#1488)
voice_dictate: 'Dictate', // TODO: translate
voice_dictate_active: 'Stop dictation', // TODO: translate
voice_mode_toggle: 'Voice mode', // TODO: translate
voice_mode_toggle_active: 'Exit voice mode', // TODO: translate
subagent_children: 'Subagent sessions', // TODO: translate
},
zh: {
_lang: 'zh',
_label: '\u7b80\u4f53\u4e2d\u6587',
_speech: 'zh-CN',
// boot.js
cancelling: '\u6b63\u5728\u53d6\u6d88...',
cancel_failed: '\u53d6\u6d88\u5931\u8d25\uff1a',
mic_denied: '\u9ea6\u514b\u98ce\u8bbf\u95ee\u88ab\u62d2\u7edd\uff0c\u8bf7\u68c0\u67e5\u6d4f\u89c8\u5668\u6743\u9650\u3002',
mic_no_speech: '\u6ca1\u6709\u68c0\u6d4b\u5230\u8bed\u97f3\uff0c\u8bf7\u518d\u8bd5\u4e00\u6b21\u3002',
mic_network: '\u8bed\u97f3\u8bc6\u522b\u5f53\u524d\u4e0d\u53ef\u7528\u3002',
mic_error: '\u8bed\u97f3\u8f93\u5165\u51fa\u9519\uff1a',
session_imported: '\u4f1a\u8bdd\u5df2\u5bfc\u5165',
import_failed: '\u5bfc\u5165\u5931\u8d25\uff1a',
import_invalid_json: 'JSON \u65e0\u6548',
image_pasted: '\u5df2\u7c98\u8d34\u56fe\u7247\uff1a',
// messages.js
edit_message: '\u7f16\u8f91\u6d88\u606f',
regenerate: '\u91cd\u65b0\u751f\u6210\u56de\u590d',
copy: '\u590d\u5236',
copied: '\u5df2\u590d\u5236',
copy_failed: '\u590d\u5236\u5931\u8d25',
diff_loading: '加载 diff',
diff_error: '无法加载 patch 文件',
diff_too_large: 'Patch 文件过大,无法内联显示',
tree_view: '树形',
raw_view: '原始',
parse_failed_note: '解析失败',
you: '\u4f60',
mcp_servers_title: 'MCP 服务器',
mcp_servers_desc: '管理 config.yaml 中配置的 MCP 服务器。',
mcp_no_servers: '未配置 MCP 服务器。',
mcp_add_server: '+ 添加服务器',
mcp_field_name: '服务器名称',
mcp_transport_label: '传输类型',
mcp_field_command: '命令',
mcp_field_args: '参数(逗号分隔)',
mcp_field_url: 'URL',
mcp_field_timeout: '超时(秒)',
mcp_save: '保存',
mcp_cancel: '取消',
mcp_name_required: '服务器名称为必填项。',
mcp_url_required: 'HTTP 传输需要 URL。',
mcp_command_required: 'stdio 传输需要命令。',
mcp_saved: 'MCP 服务器已保存。',
mcp_save_failed: 'MCP 服务器保存失败。',
mcp_delete_confirm_title: '删除 MCP 服务器',
mcp_delete_confirm_message: '确定删除 MCP 服务器「{0}」吗?此操作不可撤销。',
mcp_deleted: 'MCP 服务器已删除。',
mcp_delete_failed: 'MCP 服务器删除失败。',
mcp_load_failed: 'MCP 服务器加载失败。',
thinking: '\u601d\u8003\u8fc7\u7a0b',
expand_all: '\u5168\u90e8\u5c55\u5f00',
collapse_all: '\u5168\u90e8\u6298\u53e0',
edit_failed: '\u7f16\u8f91\u5931\u8d25\uff1a',
regen_failed: '\u91cd\u65b0\u751f\u6210\u5931\u8d25\uff1a',
reconnect_active: '\u56de\u590d\u4ecd\u5728\u751f\u6210\u4e2d\uff0c\u51c6\u5907\u597d\u540e\u8981\u91cd\u65b0\u52a0\u8f7d\u5417\uff1f',
reconnect_finished: '\u4f60\u79bb\u5f00\u65f6\u6709\u56de\u590d\u6b63\u5728\u751f\u6210\uff0c\u6d88\u606f\u5185\u5bb9\u53ef\u80fd\u5df2\u7ecf\u66f4\u65b0\u3002',
// approval card
approval_heading: '需要审批',
approval_desc_prefix: '检测到危险命令',
approval_btn_once: '允许一次',
approval_btn_once_title: '允许执行此命令一次(Enter',
approval_btn_session: '本次允许',
approval_btn_session_title: '本次会话期间允许',
approval_btn_always: '始终允许',
approval_btn_always_title: '始终允许此命令模式',
approval_btn_deny: '拒绝',
approval_btn_deny_title: '拒绝 — 不执行此命令',
approval_responding: '处理中…',
clarify_heading: '需要澄清',
clarify_hint: '请选择一个选项,或在下方输入你自己的回答。',
clarify_other: '其他',
clarify_send: '发送',
clarify_input_placeholder: '请输入你的回答…',
clarify_responding: '处理中…',
untitled: '\u672a\u547d\u540d',
n_messages: (n) => `${n} \u6761\u6d88\u606f`,
load_older_messages: '↑ 向上滚动或点击加载更早的消息',
queued_label: '响应后发送',
queued_count: (n) => n === 1 ? '1 条排队' : `${n} 条排队`,
queued_cancel: '取消排队消息',
model_unavailable: '\uff08\u4e0d\u53ef\u7528\uff09',
model_unavailable_title: '\u8fd9\u4e2a\u6a21\u578b\u5df2\u7ecf\u4e0d\u5728\u5f53\u524d provider \u5217\u8868\u4e2d',
provider_mismatch_warning: (m,p)=>`\"${m}\" \u53ef\u80fd\u65e0\u6cd5\u5728\u5f53\u524d\u914d\u7f6e\u7684\u63d0\u4f9b\u5546 (${p}) \u4e0b\u5de5\u4f5c\u3002\u76f4\u63a5\u53d1\u9001\uff0c\u6216\u5728\u7ec8\u7aef\u8fd0\u884c \`hermes model\` \u5207\u6362\u3002`,
provider_mismatch_label: '\u63d0\u4f9b\u5546\u4e0d\u5339\u914d',
model_not_found_label: '\u672a\u627e\u5230\u6a21\u578b',
model_custom_label: '\u81ea\u5b9a\u4e49\u6a21\u578b ID',
model_custom_placeholder: '\u4f8b\u5982 openai/gpt-5.4',
model_search_placeholder: '\u641c\u7d22\u6a21\u578b\u2026',
model_search_no_results: '\u672a\u627e\u5230\u6a21\u578b',
model_group_configured: '已配置',
ws_search_placeholder: '搜索工作区…',
ws_no_results: '未找到工作区',
session_toolsets: 'Session Toolsets', // TODO: translate
session_toolsets_desc: 'Restrict available tools for this session (blank = use global config)', // TODO: translate
session_toolsets_global: 'Global (default)', // TODO: translate
session_toolsets_custom: 'Custom', // TODO: translate
session_toolsets_placeholder: 'tool1, tool2, \u2026', // TODO: translate
session_toolsets_apply: 'Apply', // TODO: translate
session_toolsets_clear: 'Clear (use global)', // TODO: translate
session_toolsets_applied: 'Toolsets updated', // TODO: translate
session_toolsets_cleared: 'Toolsets cleared — using global config', // TODO: translate
session_toolsets_failed: 'Failed to update toolsets: ', // TODO: translate
model_scope_advisory: '\u4ece\u4e0b\u4e00\u6761\u6d88\u606f\u8d77\u5e94\u7528\u4e8e\u5f53\u524d\u5bf9\u8bdd\u3002',
model_scope_toast: '\u4ece\u4e0b\u4e00\u6761\u6d88\u606f\u8d77\u5e94\u7528\u4e8e\u5f53\u524d\u5bf9\u8bdd\u3002',
// commands.js
cmd_help: '\u67e5\u770b\u53ef\u7528\u547d\u4ee4',
cmd_clear: '\u6e05\u7a7a\u5f53\u524d\u5bf9\u8bdd\u6d88\u606f',
cmd_compress: '\u624b\u52a8\u538b\u7f29\u5bf9\u8bdd\u4e0a\u4e0b\u6587\uff08\u7528\u6cd5\uff1a/compress [\u4e3b\u9898]\uff09',
ctx_compress_hint: '\u538b\u7f29\u4e0a\u4e0b\u6587\u4ee5\u91ca\u653e\u7a7a\u95f4 →',
ctx_compress_action: '\u26a0 \u7acb\u5373\u538b\u7f29\u4ee5\u91ca\u653e\u4e0a\u4e0b\u6587',
cmd_compact_alias: '\u65e7\u522b\u540d\uff1a/compress',
cmd_model: '\u5207\u6362\u6a21\u578b\uff08\u4f8b\u5982 /model gpt-4o\uff09',
cmd_workspace: '\u6309\u540d\u79f0\u5207\u6362\u5de5\u4f5c\u533a',
cmd_terminal: '\u6253\u5f00\u5de5\u4f5c\u533a Terminal',
cmd_new: '\u65b0\u5efa\u804a\u5929\u4f1a\u8bdd',
cmd_usage: '\u5207\u6362 token \u7528\u91cf\u663e\u793a',
cmd_theme: '\u5207\u6362\u5916\u89c2\uff08\u4e3b\u9898\uff1asystem/dark/light\uff0c\u76ae\u80a4\uff1adefault/ares/mono/slate/poseidon/sisyphus/charizard\uff09',
cmd_personality: '\u5207\u6362 Agent \u4eba\u8bbe',
cmd_skills: '\u5217\u51fa\u53ef\u7528\u7684 Hermes \u6280\u80fd',
available_commands: '\u53ef\u7528\u547d\u4ee4\uff1a',
type_slash: '\u8f93\u5165 / \u53ef\u67e5\u770b\u547d\u4ee4',
conversation_cleared: '\u5bf9\u8bdd\u5df2\u6e05\u7a7a',
command_label: '\u547d\u4ee4',
context_compaction_label: '\u4e0a\u4e0b\u6587\u538b\u7f29',
preserved_task_list_label: '\u4fdd\u7559\u7684\u4efb\u52a1\u5217\u8868',
reference_only_label: '\u4ec5\u4f9b\u53c2\u8003',
model_usage: '\u7528\u6cd5\uff1a/model <name>',
no_model_match: '\u6ca1\u6709\u5339\u914d\u201c',
switched_to: '\u5df2\u5207\u6362\u5230 ',
workspace_usage: '\u7528\u6cd5\uff1a/workspace <name>',
no_workspace_match: '\u6ca1\u6709\u5339\u914d\u201c',
switched_workspace: '\u5df2\u5207\u6362\u5de5\u4f5c\u533a\uff1a',
workspace_switch_failed: '\u5de5\u4f5c\u533a\u5207\u6362\u5931\u8d25\uff1a',
new_session: '\u5df2\u65b0\u5efa\u4f1a\u8bdd',
compressing: '\u6b63\u5728\u8bf7\u6c42\u538b\u7f29\u4e0a\u4e0b\u6587...',
compress_running_label: '\u538b\u7f29\u4e2d',
compress_complete_label: '\u538b\u7f29\u5b8c\u6210',
auto_compress_label: '\u81ea\u52a8\u538b\u7f29',
compress_failed_label: '\u538b\u7f29\u5931\u8d25',
focus_label: '\u4e3b\u9898',
token_usage_on: 'Token \u7528\u91cf\u663e\u793a\u5df2\u5f00\u542f',
usage_personality_none: 'none', // TODO: translate
token_usage_off: 'Token \u7528\u91cf\u663e\u793a\u5df2\u5173\u95ed',
theme_usage: '\u7528\u6cd5\uff1a/theme ',
theme_set: '\u4e3b\u9898\uff1a',
no_active_session: '\u5f53\u524d\u6ca1\u6709\u6d3b\u52a8\u4f1a\u8bdd',
cmd_queue: '\u5c06\u6d88\u606f\u52a0\u5165\u4e0b\u4e00\u8f6e\u7684\u961f\u5217',
cmd_interrupt: '\u53d6\u6d88\u5f53\u524d\u56de\u5408\u5e76\u53d1\u9001\u65b0\u6d88\u606f',
cmd_steer: '\u7528\u7ea0\u6b63\u4fe1\u606f\u5f15\u5bfc\u4ee3\u7406\uff08\u56de\u9000\u4e3a\u4e2d\u65ad\uff09',
cmd_queue_no_msg: '\u7528\u6cd5\uff1a/queue <\u6d88\u606f>',
cmd_queue_not_busy: '\u6ca1\u6709\u6d3b\u52a8\u4efb\u52a1 \u2014 \u76f4\u63a5\u53d1\u9001\u5373\u53ef',
cmd_queue_confirm: '\u6d88\u606f\u5df2\u52a0\u5165\u961f\u5217',
cmd_interrupt_no_msg: '\u7528\u6cd5\uff1a/interrupt <\u6d88\u606f>',
cmd_interrupt_confirm: '\u5df2\u4e2d\u65ad \u2014 \u6b63\u5728\u53d1\u9001\u65b0\u6d88\u606f',
cmd_steer_no_msg: '\u7528\u6cd5\uff1a/steer <\u6d88\u606f>',
cmd_steer_fallback: 'Steer \u4e0d\u53ef\u7528 \u2014 \u5df2\u4e2d\u65ad\u5e76\u52a0\u5165\u961f\u5217',
cmd_steer_delivered: 'Steer \u5df2\u4ea4\u4ed8 \u2014 \u4ee3\u7406\u5c06\u5728\u4e0b\u4e00\u4e2a\u5de5\u5177\u7ed3\u679c\u4e2d\u770b\u5230',
steer_leftover_queued: 'Steer \u5df2\u52a0\u5165\u4e0b\u8f6e\u961f\u5217',
busy_steer_fallback: 'Steer \u4e0d\u53ef\u7528 \u2014 \u5df2\u4e2d\u65ad',
busy_interrupt_confirm: '\u5df2\u4e2d\u65ad \u2014 \u6b63\u5728\u53d1\u9001\u65b0\u6d88\u606f',
settings_label_busy_input_mode: '\u5fd9\u788c\u8f93\u5165\u6a21\u5f0f',
settings_desc_busy_input_mode: '\u63a7\u5236\u5728\u4ee3\u7406\u8fd0\u884c\u65f6\u53d1\u9001\u6d88\u606f\u7684\u884c\u4e3a\u3002\u961f\u5217\u7b49\u5f85\uff1b\u4e2d\u65ad\u53d6\u6d88\u5e76\u91cd\u65b0\u5f00\u59cb\uff1bSteer\u4e2d\u9014\u6ce8\u5165\u7ea0\u6b63\uff0c\u4e0d\u4e2d\u65ad\u3002',
settings_busy_input_mode_queue: '\u52a0\u5165\u961f\u5217',
settings_busy_input_mode_interrupt: '\u4e2d\u65ad\u5f53\u524d\u56de\u5408',
settings_busy_input_mode_steer: 'Steer\uff08\u4e2d\u65ad + \u53d1\u9001\uff09',
workspace_empty_no_path: '未选择工作区。请在 设置 → 工作区 中设置工作区以浏览文件。',
workspace_empty_dir: '此工作区为空。',
no_personalities: '\u6ca1\u6709\u627e\u5230\u4eba\u8bbe\uff08\u53ef\u6dfb\u52a0\u5230 ~/.hermes/personalities/\uff09',
available_personalities: '\u53ef\u7528\u4eba\u8bbe\uff1a',
personality_switch_hint: '\n\n\u4f7f\u7528 `/personality <name>` \u5207\u6362\uff0c\u6216\u7528 `/personality none` \u6e05\u7a7a\u3002',
personalities_load_failed: '\u52a0\u8f7d\u4eba\u8bbe\u5931\u8d25',
personality_cleared: '\u4eba\u8bbe\u5df2\u6e05\u7a7a',
personality_set: '\u5f53\u524d\u4eba\u8bbe\uff1a',
failed_colon: '\u5931\u8d25\uff1a',
// ui.js
no_workspace: '\u672a\u9009\u62e9\u5de5\u4f5c\u533a',
terminal_open_title: '\u6253\u5f00\u5de5\u4f5c\u533a Terminal',
terminal_no_workspace_title: '\u8bf7\u5148\u9009\u62e9\u5de5\u4f5c\u533a\u518d\u6253\u5f00 Terminal',
terminal_title: 'Terminal',
terminal_clear: '\u6e05\u7a7a',
terminal_copy_output: '\u590d\u5236\u8f93\u51fa',
terminal_restart: '\u91cd\u542f',
terminal_collapse: '\u6298\u53e0',
terminal_expand: '\u5c55\u5f00',
terminal_close: '\u5173\u95ed',
terminal_input_placeholder: '\u8f93\u5165\u547d\u4ee4...',
terminal_start_failed: 'Terminal \u542f\u52a8\u5931\u8d25\uff1a',
terminal_input_failed: 'Terminal \u8f93\u5165\u5931\u8d25\uff1a',
terminal_copy_failed: '\u590d\u5236\u5931\u8d25\uff1a',
terminal_error: 'Terminal \u9519\u8bef',
dialog_confirm_title: '\u786e\u8ba4\u64cd\u4f5c',
dialog_prompt_title: '\u8f93\u5165\u5185\u5bb9',
dialog_confirm_btn: '\u786e\u8ba4',
// workspace.js
unsaved_confirm: '\u9884\u89c8\u533a\u6709\u672a\u4fdd\u5b58\u4fee\u6539\uff0c\u8981\u653e\u5f03\u66f4\u6539\u5e76\u7ee7\u7eed\u8df3\u8f6c\u5417\uff1f',
discard: '\u653e\u5f03',
save: '\u4fdd\u5b58',
edit: '\u7f16\u8f91',
clear: '\u6e05\u7a7a',
create: '\u521b\u5efa',
remove: '\u79fb\u9664',
save_title: '\u4fdd\u5b58\u4fee\u6539',
edit_title: '\u7f16\u8f91\u6b64\u6587\u4ef6',
saved: '\u5df2\u4fdd\u5b58',
save_failed: '\u4fdd\u5b58\u5931\u8d25\uff1a',
image_load_failed: '\u56fe\u7247\u52a0\u8f7d\u5931\u8d25',
file_open_failed: '\u65e0\u6cd5\u6253\u5f00\u6587\u4ef6',
downloading: (name) => `\u6b63\u5728\u4e0b\u8f7d ${name}...`,
double_click_rename: '\u53cc\u51fb\u91cd\u547d\u540d',
renamed_to: '\u5df2\u91cd\u547d\u540d\u4e3a ',
rename_failed: '\u91cd\u547d\u540d\u5931\u8d25\uff1a',
delete_title: '\u5220\u9664',
delete_confirm: (name) => `\u8981\u5220\u9664 ${name} \u5417\uff1f`,
delete_dir_confirm: (name) => `删除文件夹 "${name}" 及其所有内容?`,
rename_title: '重命名',
rename_prompt: '新名称:',
deleted: '\u5df2\u5220\u9664 ',
delete_failed: '\u5220\u9664\u5931\u8d25\uff1a',
reveal_in_finder: '\u5728\u6587\u4ef6\u7ba1\u7406\u5668\u4e2d\u663e\u793a',
reveal_failed: '\u663e\u793a\u5931\u8d25\uff1a',
new_file_prompt: '\u65b0\u6587\u4ef6\u540d\uff08\u4f8b\u5982 notes.md\uff09\uff1a',
project_name_prompt: '\u9879\u76ee\u540d\u79f0\uff1a',
created: '\u5df2\u521b\u5efa ',
create_failed: '\u521b\u5efa\u5931\u8d25\uff1a',
new_folder_prompt: '\u65b0\u6587\u4ef6\u5939\u540d\u79f0\uff1a',
folder_created: '\u5df2\u521b\u5efa\u6587\u4ef6\u5939 ',
folder_create_failed: '\u521b\u5efa\u6587\u4ef6\u5939\u5931\u8d25\uff1a',
workspace_auto_create_folder: '\u5982\u679c\u6587\u4ef6\u5939\u4e0d\u5b58\u5728\u5219\u521b\u5efa',
folder_add_as_space_btn: '\u6dfb\u52a0\u4e3a\u5de5\u4f5c\u533a',
folder_add_as_space_msg: '\u662f\u5426\u5c06\u6b64\u6587\u4ef6\u5939\u6dfb\u52a0\u4e3a\u65b0\u7684\u5de5\u4f5c\u533a\uff1f',
folder_add_as_space_title: '\u6dfb\u52a0\u4e3a\u5de5\u4f5c\u533a\uff1f',
remove_title: '\u79fb\u9664',
empty_dir: '(\u7a7a)',
upload_failed: '\u4e0a\u4f20\u5931\u8d25\uff1a',
all_uploads_failed: (n) => `${n} \u4e2a\u6587\u4ef6\u5168\u90e8\u4e0a\u4f20\u5931\u8d25`,
// settings panel
settings_title: '\u8bbe\u7f6e',
settings_save_btn: '\u4fdd\u5b58\u8bbe\u7f6e',
settings_label_model: '\u9ed8\u8ba4\u6a21\u578b',
settings_desc_model: '\u7528\u4e8e\u65b0\u5bf9\u8bdd\u3002\u73b0\u6709\u5bf9\u8bdd\u4fdd\u6301\u5404\u81ea\u9009\u5b9a\u7684\u6a21\u578b\u3002',
settings_label_send_key: '\u53d1\u9001\u5feb\u6377\u952e',
settings_label_theme: '\u4e3b\u9898',
settings_label_skin: '\u76ae\u80a4',
settings_label_font_size: '\u5b57\u4f53\u5927\u5c0f',
font_size_small: '\u5c0f',
font_size_default: '\u9ed8\u8ba4',
font_size_large: '\u5927',
settings_autosave_saving: '\u4fdd\u5b58\u4e2d…',
settings_autosave_saved: '\u5df2\u4fdd\u5b58',
settings_autosave_failed: '\u4fdd\u5b58\u5931\u8d25',
settings_autosave_retry: '\u91cd\u8bd5',
settings_label_language: '\u8bed\u8a00',
settings_label_token_usage: '\u663e\u793a token \u7528\u91cf',
settings_label_sidebar_density: '侧边栏密度',
cmd_reasoning: 'Toggle thinking visibility (show/hide), set effort level, or check current status',
settings_label_external_sessions: '显示外部会话',
settings_label_sync_insights: '\u540c\u6b65\u5230 insights',
settings_label_check_updates: '\u68c0\u67e5\u66f4\u65b0',
settings_label_bot_name: '\u52a9\u624b\u540d\u79f0',
settings_label_password: '\u8bbf\u95ee\u5bc6\u7801',
settings_saved: '\u8bbe\u7f6e\u5df2\u4fdd\u5b58',
settings_save_failed: '\u4fdd\u5b58\u5931\u8d25\uff1a',
settings_load_failed: '\u8bbe\u7f6e\u52a0\u8f7d\u5931\u8d25\uff1a',
settings_saved_pw: '\u8bbe\u7f6e\u5df2\u4fdd\u5b58\uff0c\u5df2\u542f\u7528\u5bc6\u7801\u4fdd\u62a4\uff0c\u5f53\u524d\u6d4f\u89c8\u5668\u4f1a\u4fdd\u6301\u767b\u5f55',
settings_saved_pw_updated: '\u8bbe\u7f6e\u5df2\u4fdd\u5b58\uff0c\u5bc6\u7801\u5df2\u66f4\u65b0',
// login page
login_title: '\u767b\u5f55',
login_subtitle: '\u8f93\u5165\u5bc6\u7801\u7ee7\u7eed\u4f7f\u7528',
login_placeholder: '\u5bc6\u7801',
login_btn: '\u767b\u5f55',
login_invalid_pw: '\u5bc6\u7801\u9519\u8bef',
login_conn_failed: '\u8fde\u63a5\u5931\u8d25',
// sidebar & navigation
tab_chat: '聊天',
tab_memory: '记忆',
tab_skills: '技能',
tab_tasks: '任务',
tab_kanban: 'Kanban',
kanban_board: 'Board',
kanban_visible_tasks: '{0} visible tasks',
kanban_search_tasks: 'Search tasks',
kanban_all_assignees: 'All assignees',
kanban_all_tenants: 'All tenants',
kanban_include_archived: 'Include archived',
kanban_no_matching_tasks: 'No matching tasks',
kanban_no_data: 'No Kanban data',
kanban_unavailable: 'Kanban unavailable',
kanban_read_only: 'Read-only view',
kanban_empty: 'Empty',
kanban_task: 'Task',
kanban_no_description: 'No description',
kanban_refresh: 'Refresh',
kanban_status_triage: 'Triage',
kanban_status_todo: 'Todo',
kanban_status_ready: 'Ready',
kanban_status_running: 'Running',
kanban_status_blocked: 'Blocked',
kanban_status_done: 'Done',
kanban_comments_count: 'Comments ({0})',
kanban_events_count: 'Events ({0})',
kanban_links: 'Links',
kanban_parents: 'Parents',
kanban_children: 'Children',
kanban_runs_count: 'Runs ({0})',
kanban_no_comments: 'No comments',
kanban_no_events: 'No events',
kanban_no_runs: 'No runs',
kanban_new_task: 'New task',
kanban_add_comment: 'Add comment',
kanban_only_mine: 'Only mine',
kanban_bulk_action: 'Bulk action',
kanban_nudge_dispatcher: 'Nudge dispatcher',
kanban_stats: 'Stats',
kanban_worker_log: 'Worker log',
kanban_block: 'Block',
kanban_unblock: 'Unblock',
kanban_back_to_board: 'Back to board',
kanban_lanes_by_profile: 'Lanes by profile',
kanban_new_board: 'New board…',
kanban_rename_board: 'Rename current board…',
kanban_archive_board: 'Archive current board…',
kanban_archive_board_confirm: 'Archive board "{name}"? Tasks remain on disk and the board can be restored from kanban/boards/_archived/.',
kanban_board_archived: 'Board archived',
kanban_board_name: 'Name',
kanban_board_slug: 'Slug (lowercase, hyphens)',
kanban_board_description: 'Description (optional)',
kanban_board_icon: 'Icon (emoji, optional)',
kanban_board_color: 'Color (optional)',
kanban_board_name_required: 'Name is required',
kanban_board_slug_required: 'Slug is required',
kanban_card_start: 'start',
kanban_card_complete: 'complete',
kanban_card_archive: 'archive',
kanban_unassigned: 'unassigned',
kanban_status_archived: 'Archived',
tab_todos: '待办',
tab_insights: '统计',
tab_workspaces: '工作区',
tab_profiles: '配置',
tab_settings: '设置',
new_conversation: '新建对话',
filter_conversations: '筛选对话…',
session_time_unknown: '未知',
session_time_minutes_ago: (n) => `${n}`,
session_time_hours_ago: (n) => `${n}小时`,
session_time_days_ago: (n) => `${n}`,
session_time_last_week: '1周',
session_time_bucket_today: '今天',
session_time_bucket_yesterday: '昨天',
session_time_bucket_this_week: '本周',
session_time_bucket_last_week: '上周',
session_time_bucket_older: '更早',
scheduled_jobs: '定时任务',
new_job: '新任务',
search_skills: '搜索技能…',
new_skill: '新技能',
save_skill: '保存技能',
personal_memory: '个人记忆',
current_task_list: '当前任务列表',
workspace_desc: '为你的会话添加并切换工作区。',
session_meta_messages: (n) => `${n} 条消息`,
session_meta_children: (n) => `${n} 子会话`,
new_profile: '新配置',
transcript: '记录',
download_transcript: '下载为 Markdown',
import: '导入',
editing: '编辑中',
empty_title: '有什么可以帮您?',
empty_subtitle: '随时提问、运行命令、浏览文件或管理定时任务。',
cancel: '取消',
loading: '加载中…',
create_job: '创建任务',
suggest_plan: '帮我规划一个小项目。',
suggest_schedule: '今天有什么安排?',
suggest_files: '这个工作区有哪些文件?',
sign_out: '退出登录',
// Providers panel (English fallback — native translations welcome in follow-up PRs)
providers_tab_title: 'Providers',
providers_section_title: 'Providers',
providers_section_meta: 'Manage API keys for AI providers. Changes take effect immediately.',
providers_status_configured: 'API key configured',
providers_status_not_configured: 'No API key',
providers_status_oauth: 'OAuth',
providers_status_api_key: 'API key',
providers_status_not_configured_label: 'Not configured',
providers_oauth_hint: 'Authenticated via OAuth. No API key needed.',
providers_oauth_config_yaml_hint: 'Token configured via config.yaml. To update, edit the providers section in your config.yaml or run hermes auth.',
providers_oauth_not_configured_hint: 'Not authenticated. Run hermes auth in the terminal to configure this provider.',
providers_save: 'Save',
providers_remove: 'Remove',
providers_saving: 'Saving…',
providers_removing: 'Removing…',
providers_enter_key: 'Please enter an API key',
providers_empty: 'No configurable providers found.',
providers_key_updated: 'API key saved',
providers_key_removed: 'API key removed',
providers_key_placeholder_new: 'sk-...',
providers_key_placeholder_replace: 'Enter new key to replace…',
password_placeholder: '输入新密码…',
password_env_var_locked: '当前已设置 HERMES_WEBUI_PASSWORD 环境变量并具有优先级。请取消该变量并重启服务器,才能在此管理密码。',
password_env_var_locked_placeholder: '已锁定:已设置 HERMES_WEBUI_PASSWORD 环境变量',
disable_auth: '停用认证',
settings_label_sound: '通知声音',
settings_label_notifications: '浏览器通知',
settings_desc_sound: '助手完成回复时播放提示音。',
settings_desc_notifications: '当标签页在后台时,回复完成后显示系统通知。',
settings_desc_token_usage: '在助手每次回复下方显示输入/输出 token 数量。也可以用 /usage 切换。',
settings_sidebar_density_compact: '紧凑',
settings_sidebar_density_detailed: '详细',
settings_desc_sidebar_density: '控制左侧会话列表展示多少元信息。',
settings_label_auto_title_refresh: '\u81ea\u9002\u5e94\u6807\u9898\u66f4\u65b0',
settings_auto_title_refresh_off: '\u5173\u95ed',
settings_auto_title_refresh_5: '\u6bcf 5 \u8f6e\u5bf9\u8bdd',
settings_auto_title_refresh_10: '\u6bcf 10 \u8f6e\u5bf9\u8bdd',
settings_auto_title_refresh_20: '\u6bcf 20 \u8f6e\u5bf9\u8bdd',
settings_desc_auto_title_refresh: '\u57fa\u4e8e\u6700\u65b0\u5bf9\u8bdd\u81ea\u52a8\u91cd\u65b0\u751f\u6210\u4f1a\u8bdd\u6807\u9898\uff0c\u4f7f\u5176\u968f\u5bf9\u8bdd\u53d1\u5c55\u4fdd\u6301\u76f8\u5173\u3002\u9700\u8981\u914d\u7f6e LLM \u6807\u9898\u751f\u6210\u6a21\u578b\u3002',
settings_desc_external_sessions: '在会话列表中显示来自 CLI、Telegram、Discord、Slack 等渠道的对话。点击可导入并继续对话。',
settings_desc_sync_insights: '将 WebUI token 使用情况同步到 state.db,使 hermes /insights 包含浏览器会话数据。默认关闭。',
settings_desc_check_updates: '当有更新的 WebUI 或助手版本时显示横幅。会在后台定期执行 git fetch。',
settings_desc_bot_name: '助手在 UI 中的显示名称。默认为 Hermes。',
settings_desc_password: '输入新密码以设置或更改。留空保持当前设置。',
// onboarding
onboarding_badge: '首次运行',
onboarding_title: '欢迎使用 Hermes Web UI',
archive_extracted: (n, c) => `${c} 个压缩包中解压了 ${n} 个文件`,
onboarding_lead: '快速引导将验证 Hermes、保存真实的提供商配置、选择工作区和模型,并可选设置密码保护应用。',
onboarding_back: '返回',
onboarding_continue: '继续',
onboarding_skip: '跳过设置',
onboarding_skipped: '设置已跳过 — 使用现有配置。',
onboarding_open: '打开 Hermes',
onboarding_step_system_title: '系统检查',
onboarding_step_system_desc: '验证 Hermes Agent 与配置可见性。',
onboarding_step_setup_title: '提供商设置',
onboarding_step_setup_desc: '保存最小可用的 Hermes 提供商配置。',
onboarding_step_workspace_title: '工作区 + 模型',
onboarding_step_workspace_desc: '为新会话和聊天选择默认值。',
onboarding_step_password_title: '可选密码',
onboarding_step_password_desc: '在分享前为 Web UI 添加保护。',
onboarding_step_finish_title: '完成',
onboarding_step_finish_desc: '确认信息并进入应用。',
onboarding_notice_system_ready: 'Hermes Agent 看起来可从 Web UI 访问。',
onboarding_notice_system_unavailable: 'Hermes Agent 尚未完全可用。Bootstrap 可以安装它,但提供商设置可能仍需要终端。',
onboarding_check_agent: 'Hermes Agent',
onboarding_check_agent_ready: '已检测且可导入',
onboarding_check_agent_missing: '缺失或仅部分可导入',
onboarding_check_password: '密码',
onboarding_check_password_enabled: '已启用',
onboarding_check_password_disabled: '尚未启用',
onboarding_check_provider: '提供商配置',
onboarding_check_provider_ready: '可开始聊天',
onboarding_check_provider_partial: '已保存但不完整',
onboarding_check_provider_pending: '需要验证',
onboarding_config_file: '配置文件:',
onboarding_env_file: '.env 文件:',
onboarding_unknown: '未知',
onboarding_current_provider: '当前配置:',
onboarding_missing_imports: '缺失导入:',
onboarding_notice_setup_required: '请先在此选择一个简单的提供商路径。高级 OAuth 流程暂时仍建议在 Hermes CLI 中完成。',
onboarding_notice_setup_already_ready: '已检测到可用的 Hermes 提供商配置。你可以保留它,或在这里替换。',
onboarding_oauth_provider_ready_title: '提供商已完成认证',
onboarding_oauth_provider_ready_body: '此实例已配置为使用通过 Hermes CLI 设置的 OAuth 提供商(<strong>{provider}</strong>)。这里不需要 API key,点击继续即可完成设置。',
onboarding_oauth_provider_not_ready_title: 'OAuth 提供商尚未认证',
onboarding_oauth_provider_not_ready_body: '此实例已配置为使用 <strong>{provider}</strong>,该提供商使用 OAuth 而非 API key。请在终端运行 <code>hermes auth</code> 或 <code>hermes model</code> 完成认证,然后重新加载 Web UI。',
onboarding_oauth_switch_hint: '或者在下方选择其他提供商,切换到 API key 配置:',
onboarding_notice_workspace: '这些值复用与正式应用相同的设置 API。',
onboarding_workspace_label: '工作区',
onboarding_workspace_or_path: '或输入工作区路径',
onboarding_workspace_placeholder: '/home/you/workspace',
onboarding_provider_label: '设置模式',
onboarding_quick_setup_badge: '快速设置',
provider_category_easy_start: '快速开始',
provider_category_self_hosted: '本地 / 开源',
provider_category_specialized: '专业服务',
onboarding_api_key_label: 'API key',
onboarding_api_key_placeholder: '留空可保留已保存的 key',
onboarding_api_key_label_optional: 'API key (optional)', // TODO: translate
onboarding_api_key_placeholder_optional: 'Leave blank for keyless servers', // TODO: translate
onboarding_api_key_help_keyless: 'Most LM Studio / Ollama / vLLM installs run keyless — leave this blank if your server doesn\'t require authentication. Use the Test connection button to verify.', // TODO: translate
oauth_login_codex: 'Login with Codex (ChatGPT)', // TODO: translate
oauth_codex_step1: 'Step 1: Visit this URL and enter the code', // TODO: translate
oauth_codex_step2: 'Step 2: Enter this code on the page', // TODO: translate
oauth_codex_polling: 'Waiting for authorization...', // TODO: translate
oauth_codex_success: 'Codex OAuth login successful!', // TODO: translate
oauth_codex_error: 'OAuth login failed', // TODO: translate
oauth_codex_expired: 'Code expired, please try again', // TODO: translate
onboarding_api_key_help_prefix: '会作为密钥保存到 Hermes .env 文件中,变量名为',
onboarding_base_url_label: 'Base URL',
onboarding_base_url_placeholder: 'https://your-endpoint.example/v1',
onboarding_base_url_help: '用于 OpenAI 兼容路由、自托管服务、LiteLLM、Ollama、LM Studio、vLLM 或类似端点。',
onboarding_model_label: '默认模型',
onboarding_workspace_help: '选择设置完成后 Hermes 在新聊天中使用的模型。',
onboarding_custom_model_placeholder: 'your-model-name',
onboarding_custom_model_help: '对于自定义端点,请填写服务端要求的精确模型 ID。',
onboarding_notice_password_enabled: '已配置密码。仅在你想替换时输入新密码。',
onboarding_notice_password_recommended: '可选,但如果你会把 UI 暴露到 localhost 之外,建议设置。',
onboarding_password_label: '密码(可选)',
onboarding_password_placeholder: '留空则跳过',
onboarding_password_help: '密码通过现有设置 API 保存,并在服务端进行哈希处理。',
onboarding_notice_finish: '你之后仍可在设置中修改这些选项。',
onboarding_not_set: '未设置',
onboarding_password_will_enable: '将启用',
onboarding_password_will_replace: '将被替换',
onboarding_password_keep_existing: '保留当前密码',
onboarding_password_remains_disabled: '将保持禁用',
onboarding_password_skipped: '暂时跳过',
onboarding_finish_help: '完成后会在设置中写入 <code>onboarding_completed</code>,并进入常规应用界面。',
onboarding_error_choose_workspace: '继续前请先选择工作区。',
onboarding_error_choose_model: '继续前请先选择模型。',
onboarding_error_provider_required: '继续前请先选择设置模式。',
onboarding_error_base_url_required: '自定义端点必须填写 Base URL。',
onboarding_probe_test_button: 'Test connection', // TODO: translate
onboarding_probe_probing: 'Testing connection…', // TODO: translate
onboarding_probe_ok: 'Connected. {n} model(s) available.', // TODO: translate
onboarding_probe_error_generic: 'Could not reach the configured base URL.', // TODO: translate
onboarding_probe_error_invalid_url: 'Base URL must start with http:// or https://.', // TODO: translate
onboarding_probe_error_dns: 'Could not resolve the host. Check the URL or use the host\'s IP address.', // TODO: translate
onboarding_probe_error_connect_refused: 'Connection refused — the server may not be running on that address. From inside Docker, try the host IP instead of localhost.', // TODO: translate
onboarding_probe_error_timeout: 'The endpoint did not respond in time. Check that the server is running and the URL is correct.', // TODO: translate
onboarding_probe_error_http_4xx: 'The endpoint returned a client error. Check authentication and the URL path (typically ends in /v1).', // TODO: translate
onboarding_probe_error_http_5xx: 'The endpoint returned a server error. Check the LM Studio / Ollama server logs.', // TODO: translate
onboarding_probe_error_parse: 'The endpoint did not return a model list in the expected shape. Verify the URL points to the OpenAI-compatible API root.', // TODO: translate
onboarding_probe_error_unreachable: 'Could not reach the configured base URL.', // TODO: translate
onboarding_error_probe_failed: 'Could not validate the configured base URL.', // TODO: translate
onboarding_error_workspace_required: '必须填写工作区。',
onboarding_error_model_required: '必须填写模型。',
onboarding_complete: '引导完成',
// panel/runtime i18n
error_prefix: '错误:',
not_available: '无',
never: '从未',
add: '添加',
add_failed: '添加失败:',
remove_failed: '移除失败:',
switch_failed: '切换失败:',
name_required: '名称不能为空',
content_required: '内容不能为空',
view: '查看',
dismiss: '忽略',
disable: '停用',
cron_no_jobs: '未找到定时任务。',
cron_status_off: '关闭',
cron_status_paused: '暂停',
cron_status_error: '错误',
cron_status_active: '运行中',
cron_status_running: '执行中\u2026',
cron_status_needs_attention: '需要处理',
cron_attention_desc: '这个重复定时任务没有下次运行时间。调度器可能没能计算出下一次运行。',
cron_attention_croniter_hint: 'Gateway 运行环境可能缺少 croniter 包。请用支持 cron 的环境重启 Gateway,然后恢复这个任务。',
cron_attention_resume: '恢复并重新计算',
cron_jobs_project: '定时任务',
cron_attention_run_once: '立即运行一次',
cron_attention_copy_diagnostics: '复制诊断信息',
cron_diagnostics_copied: '定时任务诊断信息已复制',
cron_next: '下次',
cron_last: '上次',
cron_run_now: '立即运行',
cron_pause: '暂停',
cron_resume: '恢复',
cron_job_name_placeholder: '任务名称',
cron_schedule_placeholder: '调度表达式',
cron_prompt_placeholder: '提示词',
cron_last_output: '最近输出',
cron_all_runs: '全部运行记录',
cron_hide_runs: '隐藏记录',
cron_no_runs_yet: '(暂无运行记录)',
cron_schedule_required_example: '必须填写调度(例如 "0 9 * * *" 或 "every 1h"',
cron_schedule_required: '必须填写调度',
cron_prompt_required: '必须填写提示词',
cron_job_created: '任务已创建',
cron_job_triggered: '任务已触发',
cron_job_paused: '任务已暂停',
cron_job_resumed: '任务已恢复',
cron_job_updated: '任务已更新',
cron_delete_confirm_title: '删除定时任务',
cron_delete_confirm_message: '此操作无法撤销。',
cron_job_deleted: '任务已删除',
cron_completion_status: (name, status) => `定时任务“${name}${status}`,
status_failed: '失败',
status_completed: '完成',
todos_no_active: '此会话暂无活动任务列表。',
clear_conversation_title: '清空对话',
clear_conversation_message: '要清空所有消息吗?此操作无法撤销。',
clear_failed: '清空失败:',
skills_no_match: '没有匹配的技能。',
linked_files: '关联文件',
skill_load_failed: '加载技能失败:',
skill_file_load_failed: '加载文件失败:',
skill_name_required: '技能名称不能为空',
skill_updated: '技能已更新',
skill_created: '技能已创建',
memory_notes_label: '记忆(备注)',
memory_saved: '记忆已保存',
my_notes: '我的备注',
user_profile: '用户画像',
no_notes_yet: '暂无备注。',
no_profile_yet: '暂无用户画像。',
workspace_choose_path: '选择工作区路径',
workspace_choose_path_meta: '添加已校验路径并切换当前会话',
workspace_manage: '管理工作区',
workspace_manage_meta: '打开 Spaces 面板',
workspace_use_title: '用于当前会话',
workspace_use: '使用',
workspace_add_path_placeholder: '添加工作区路径(例如 /home/user/my-project',
workspace_paths_validated_hint: '保存前会校验路径是否为已存在目录。',
workspace_drag_hint: '拖动以重新排序',
workspace_reorder_failed: '重新排序失败',
workspace_added: '工作区已添加',
workspace_renamed: '工作区已重命名',
workspace_remove_confirm_title: '移除工作区',
workspace_remove_confirm_message: (path) => `要移除"${path}"吗?`,
workspace_removed: '工作区已移除',
workspace_switch_prompt_title: '切换工作区',
workspace_switch_prompt_message: '输入绝对路径以添加并切换当前会话的工作区。',
workspace_switch_prompt_confirm: '切换',
workspace_switch_prompt_placeholder: '/Users/you/project',
workspace_not_added: '工作区未添加成功',
workspace_already_saved: '工作区已存在,请在列表中选择',
workspace_busy_switch: 'Agent 运行中,无法切换工作区',
discard_file_edits_title: '放弃文件编辑?',
discard_file_edits_message: '切换工作区将丢弃预览区未保存的文件修改。',
workspace_switched_to: (name) => `已切换到 ${name}`,
profiles_no_profiles: '未找到配置档。',
profile_api_keys_configured: '已配置 API 密钥',
profile_gateway_running: '网关运行中',
profile_gateway_stopped: '网关已停止',
profile_active: '当前',
profile_no_configuration: '无配置',
profile_skill_count: (count) => `${count} 个技能`,
profile_use: '使用',
profile_switch_title: '切换到此配置档',
profile_delete_title: '删除此配置档',
profile_default_label: '(默认)',
profile_name_placeholder: '配置档名称(小写字母、a-z、0-9、连字符)',
profile_clone_label: '复制当前配置档的配置',
profile_base_url_placeholder: 'Base URL(可选,例如 http://localhost:11434',
profile_api_key_placeholder: 'API 密钥(可选)',
manage_profiles: '管理配置档',
profiles_load_failed: '加载配置档失败',
profiles_busy_switch: 'Agent 运行中,无法切换配置档',
profile_switched_new_conversation: (name) => `已切换到配置档:${name},并新建对话`,
profile_switched: (name) => `已切换到配置档:${name}`,
profile_name_rule: '仅允许小写字母、数字、连字符和下划线',
profile_base_url_rule: 'Base URL 必须以 http:// 或 https:// 开头',
profile_created: (name) => `配置档已创建:${name}`,
profile_delete_confirm_title: (name) => `删除配置档“${name}”?`,
profile_delete_confirm_message: '该配置档的所有会话、配置、技能和记忆将被永久删除。此操作无法撤销。',
profile_deleted: (name) => `配置档已删除:${name}`,
active_conversation_none: '当前未选择活动会话。',
active_conversation_meta: (title, count) => `${title} · ${count} 条消息`,
settings_unsaved_changes: '你有未保存的更改。',
sign_out_failed: '退出登录失败:',
disable_auth_confirm_title: '停用密码保护',
disable_auth_confirm_message: '任何人都可以访问此实例。',
auth_disabled: '认证已停用,密码保护已移除',
disable_auth_failed: '停用认证失败:',
bg_error_single: (title) => `${title}”出现错误`,
bg_error_multi: (count) => `${count} 个会话出现错误`,
skill_deleted: '技能已删除',
skill_delete_confirm: '删除技能 "{0}"',
skills_empty_title: '选择一个技能',
skills_empty_sub: '从侧边栏中选择一个技能以查看其内容,或创建一个新技能。',
skills_edit: '编辑',
skills_delete: '删除',
skills_back_to: '返回 {0}',
tasks_empty_title: '选择一个计划任务',
tasks_empty_sub: '从侧边栏中选择一个任务以查看其详情和运行记录,或创建一个新任务。',
workspaces_empty_title: '选择一个空间',
workspaces_empty_sub: '从侧边栏中选择一个空间以查看其文件和设置,或添加一个新空间。',
profiles_empty_title: '选择一个配置文件',
profiles_empty_sub: '从侧边栏中选择一个代理配置文件以查看和编辑其设置,或创建一个新配置文件。',
// skill form
skill_name: '名称',
skill_category: '分类',
skill_category_placeholder: '可选,例如 devops',
skill_content: 'SKILL.md 内容',
skill_content_placeholder: 'YAML frontmatter + markdown 正文',
skill_rename_not_supported: '不支持重命名技能。请创建新技能并删除旧技能。',
skill_metadata: '元数据',
// cron form
cron_name_label: '名称',
cron_name_placeholder: '可选',
cron_schedule_label: '计划',
cron_schedule_hint: "Cron 表达式或简写,例如 'every 1h'。",
cron_prompt_label: '提示词',
cron_deliver_label: '输出位置',
cron_deliver_local: '本地(仅保存输出)',
cron_skills_label: '技能',
cron_skills_placeholder: '添加技能(可选)…',
cron_skills_edit_hint: '创建后无法再编辑技能列表。',
cron_duplicate: '\u590d\u5236',
cron_duplicated: '\u4efb\u52a1\u5df2\u590d\u5236\uff08\u5df2\u6682\u505c\uff09',
// workspace form
workspace_name_label: '名称',
workspace_name_placeholder: '可选的友好名称',
workspace_path_label: '路径',
workspace_path_required: '路径是必填项',
workspace_path_readonly: '路径不可更改。只能重命名。',
workspace_new_title: '新空间',
// profile form
profile_name_label: '名称',
profile_base_url_label: '基础 URL',
profile_api_key_label: 'API 密钥',
// Session management and settings keys (en fallback — pending translation)
session_archive: 'Archive conversation',
session_archive_desc: 'Hide this conversation until archived is shown',
session_archive_failed: 'Archive failed: ',
session_archived: 'Session archived',
session_delete: 'Delete conversation',
session_delete_desc: 'Permanently remove this conversation',
session_duplicate: 'Duplicate conversation',
session_duplicate_desc: 'Create a copy with the same workspace and model',
session_duplicate_failed: 'Duplicate failed: ',
session_stop_response: 'Stop response',
session_stop_response_desc: 'Cancel the running response for this conversation',
session_duplicated: 'Session duplicated',
session_move_project: 'Move to project',
session_move_project_desc_has: 'Change the project for this conversation',
session_move_project_desc_none: 'Assign a project to this conversation',
session_pin: 'Pin conversation',
session_pin_desc: 'Keep this conversation at the top',
session_pin_failed: 'Pin failed: ',
session_restore: 'Restore conversation',
session_restore_desc: 'Bring this conversation back into the main list',
session_restored: 'Session restored',
session_unpin: 'Unpin conversation',
session_unpin_desc: 'Remove from pinned',
session_select_mode: '选择',
session_select_mode_desc: '选择会话以批量管理',
session_select_all: '全选',
session_deselect_all: '取消全选',
session_selected_count: '已选 {0} 个',
session_batch_archive: '归档',
session_batch_delete: '删除',
session_batch_move: '移动到项目',
session_batch_delete_confirm: '删除 {0} 个会话?',
session_batch_archive_confirm: '归档 {0} 个会话?',
session_no_selection: '未选择任何会话',
settings_dropdown_appearance: 'Appearance',
settings_dropdown_conversation: 'Conversation',
settings_dropdown_preferences: 'Preferences',
settings_dropdown_providers: 'Providers',
settings_dropdown_system: 'System',
settings_heading_subtitle: 'Preferences, conversation tools, and system controls.',
settings_heading_title: 'Control Center',
settings_section_appearance_meta: 'Theme, accent colors, and visual style.',
settings_section_appearance_title: 'Appearance',
settings_section_conversation_title: 'Conversation',
settings_section_preferences_meta: 'Defaults and UI behavior for Hermes Web UI.',
settings_section_preferences_title: 'Preferences',
settings_section_system_meta: 'Instance version and access controls.',
settings_check_now: '立即检查',
settings_checking: '检查中\u2026',
settings_up_to_date: '已是最新 \u2713',
settings_updates_available: '有 {count} 个更新可用',
settings_updates_disabled: '更新检查已禁用',
settings_update_check_failed: '更新检查失败',
settings_label_workspace_panel_open: '默认保持工作区面板打开',
settings_desc_workspace_panel_open: '启用后,工作区/文件浏览器面板会在每次新会话时自动打开。您仍可随时手动关闭。',
open_in_browser: '在浏览器中打开',
settings_section_system_title: 'System',
settings_tab_appearance: 'Appearance',
settings_tab_conversation: 'Conversation',
settings_tab_preferences: 'Preferences',
settings_tab_system: 'System',
status_no_tokens: 'No token data',
status_profile: 'Profile',
status_hermes_home: 'Hermes home',
status_started: 'Started',
status_tokens: 'Tokens',
status_unknown: 'Unknown',
cmd_yolo: 'YOLO 模式切换',
yolo_no_session: '无活动会话',
yolo_enabled: '⚡ YOLO 模式已开启 — 将跳过所有审批',
cmd_branch:'Fork this conversation into a new session',
cmd_branch_usage:'/branch [name] — fork conversation (optionally with a name)',
branch_forked:'Forked into new session',
branch_failed:'Fork failed: ',
fork_from_here:'Fork from here',
forked_from:'Forked from',
yolo_disabled: 'YOLO 模式已关闭',
yolo_pill_label: 'YOLO',
yolo_pill_title_active: 'YOLO 模式激活 — 点击关闭',
approval_skip_all: '⚡ 本次会话全部跳过',
approval_skip_all_title: '跳过本次会话的所有审批提示',
// composer action tooltips
composer_send: '发送消息',
composer_queue: '消息加入队列',
composer_interrupt: '中断并发送',
composer_steer: '引导当前响应',
composer_stop: '停止生成',
composer_disabled_clarify: '请回复上方的澄清请求',
composer_disabled_compression: '等待压缩完成',
composer_disabled_empty: '请输入消息后发送',
composer_mobile_workspace: '工作区',
composer_mobile_model: '模型',
composer_mobile_reasoning: '推理',
composer_mobile_context: '上下文',
pdf_loading: '正在加载 PDF {0}…',
pdf_too_large: 'PDF 文件过大,无法内联预览',
pdf_no_pages: '无法渲染 PDF 预览',
pdf_error: 'PDF 加载失败',
pdf_download: '下载 PDF',
html_loading: '正在加载 HTML 预览…',
html_too_large: 'HTML 文件过大,无法内联预览',
html_error: 'HTML 预览加载失败',
html_open_full: '打开完整页面',
html_sandbox_label: 'HTML 预览',
media_audio_label: '音频',
media_svg_label: '图表',
media_video_label: '视频',
csv_loading: '加载 CSV',
csv_too_large: 'CSV 文件过大,无法内联渲染',
csv_no_data: 'CSV 文件数据不足,无法渲染为表格',
csv_error: '加载 CSV 文件失败',
csv_header_note: '第一行显示为表格标题',
excalidraw_loading: '加载图表',
excalidraw_too_large: 'Excalidraw 文件过大,无法内联渲染',
excalidraw_invalid: '无效的 Excalidraw 文件格式',
excalidraw_error: '加载 Excalidraw 文件失败',
excalidraw_label: '图表',
excalidraw_download: '下载',
excalidraw_empty: '空图表',
excalidraw_render_error: '渲染图表失败',
excalidraw_simplified: '简化 SVG 预览 — 与 Excalidraw 画布不完全相同',
// TTS (#499)
tts_listen: '收听',
tts_not_supported: '语音合成不可用',
settings_label_tts: '回复语音合成',
settings_desc_tts: '在助手消息上显示扬声器按钮',
settings_label_tts_auto_read: '自动朗读回复',
settings_desc_tts_auto_read: '自动朗读助手回复',
// Composer voice-mode pref (#1488)
settings_label_voice_mode: 'Hands-free voice mode button', // TODO: translate
settings_desc_voice_mode: 'Show the voice-mode button (audio waveform) next to the dictation mic. Lets you speak naturally — Hermes auto-sends after a pause and reads replies aloud. Requires a browser that supports both speech recognition and TTS.', // TODO: translate
settings_label_tts_voice: '语音',
settings_desc_tts_voice: '选择语音合成声音',
settings_label_tts_rate: '语速',
settings_label_tts_pitch: '音调',
checkpoint_date: 'Date', // TODO: translate
checkpoint_diff_files_changed: (n) => `${n} file${n === 1 ? '' : 's'} changed`, // TODO: translate
checkpoint_diff_no_changes: 'No differences found between this checkpoint and the current workspace.', // TODO: translate
checkpoint_diff_title: 'Changes in checkpoint', // TODO: translate
checkpoint_empty: 'No checkpoints found for this workspace.', // TODO: translate
checkpoint_error: 'Failed to load checkpoints', // TODO: translate
checkpoint_files: 'Files', // TODO: translate
checkpoint_loading: 'Loading checkpoints…', // TODO: translate
checkpoint_message: 'Message', // TODO: translate
checkpoint_restore: 'Restore', // TODO: translate
checkpoint_restore_confirm_message: (ckpt) => `Restore workspace to checkpoint "${ckpt}"? This will overwrite files with the saved versions. Files added after this checkpoint will not be deleted.`, // TODO: translate
checkpoint_restore_confirm_title: 'Restore checkpoint?', // TODO: translate
checkpoint_restored: 'Checkpoint restored', // TODO: translate
checkpoint_title: 'Checkpoints', // TODO: translate
checkpoint_view_diff: 'View diff', // TODO: translate
insights_activity_by_day: 'Activity by Day', // TODO: translate
insights_activity_by_hour: 'Activity by Hour', // TODO: translate
insights_cost: 'Estimated Cost', // TODO: translate
insights_footer: 'Showing data from the last {days} days', // TODO: translate
insights_input_tokens: 'Input', // TODO: translate
insights_messages: 'Messages', // TODO: translate
insights_models: 'Models', // TODO: translate
insights_no_cost: 'N/A', // TODO: translate
insights_output_tokens: 'Output', // TODO: translate
insights_peak_hour: 'Peak: {hour}', // TODO: translate
insights_sessions: 'Sessions', // TODO: translate
insights_title: 'Usage Analytics', // TODO: translate
insights_token_breakdown: 'Token Breakdown', // TODO: translate
insights_tokens: 'Tokens', // TODO: translate
insights_total: 'Total', // TODO: translate
settings_desc_api_redact: 'Self-hosted users can disable for transparency (not recommended for shared instances).', // TODO: translate
settings_label_api_redact: 'Redact sensitive data in API responses', // TODO: translate
voice_error: 'Voice not supported in this browser', // TODO: translate
voice_listening: 'Listening…', // TODO: translate
voice_mode_active: 'Voice mode on', // TODO: translate
voice_mode_off: 'Voice mode off', // TODO: translate
voice_speaking: 'Speaking…', // TODO: translate
voice_thinking: 'Thinking…', // TODO: translate
// Composer voice buttons (#1488)
voice_dictate: 'Dictate', // TODO: translate
voice_dictate_active: 'Stop dictation', // TODO: translate
voice_mode_toggle: 'Voice mode', // TODO: translate
voice_mode_toggle_active: 'Exit voice mode', // TODO: translate
subagent_children: 'Subagent sessions', // TODO: translate
},
// Traditional Chinese (zh-Hant)
'zh-Hant': {
_lang: 'zh-Hant',
_label: '\u7e41\u9ad4\u4e2d\u6587',
_speech: 'zh-TW',
// boot.js
cancelling: '\u6b63\u5728\u53d6\u6d88...',
cancel_failed: '\u53d6\u6d88\u5931\u6557\uff1a',
mic_denied: '\u9ea6\u514b\u98a8\u8a2a\u554f\u88ab\u62d2\u7d75\uff0c\u8acb\u6aa2\u67e5\u700f\u89bd\u5668\u6b0a\u9650\u3002',
mic_no_speech: '\u6c92\u6709\u6aa2\u6e2c\u5230\u8a71\u97f3\uff0c\u8acb\u518d\u5617\u4e00\u6b21\u3002',
mic_network: '\u8a71\u97f3\u8b58\u5225\u76ee\u524d\u4e0d\u53ef\u7528\u3002',
mic_error: '\u8a71\u97f3\u8f38\u5165\u51fa\u932f\uff1a',
session_imported: '\u6703\u8a71\u5df2\u5c0e\u5165',
import_failed: '\u5c0e\u5165\u5931\u6557\uff1a',
import_invalid_json: 'JSON \u7121\u6548',
image_pasted: '\u5df2\u7c98\u8cbc\u5716\u7247\uff1a',
// messages.js
edit_message: '\u7de8\u8f2f\u8a0a\u606f',
regenerate: '\u91cd\u65b0\u751f\u6210\u56de\u8986',
copy: '\u8907\u88fd',
copied: '\u5df2\u8907\u88fd',
copy_failed: '\u8907\u88fd\u5931\u6557',
diff_loading: '載入 diff',
diff_error: '無法載入 patch 檔案',
diff_too_large: 'Patch 檔案過大,無法內聯顯示',
tree_view: '樹狀',
raw_view: '原始',
parse_failed_note: '解析失敗',
you: '\u4f60',
mcp_servers_title: 'MCP 伺服器',
mcp_servers_desc: '管理 config.yaml 中設定的 MCP 伺服器。',
mcp_no_servers: '未設定 MCP 伺服器。',
mcp_add_server: '+ 新增伺服器',
mcp_field_name: '伺服器名稱',
mcp_transport_label: '傳輸類型',
mcp_field_command: '命令',
mcp_field_args: '參數(以逗號分隔)',
mcp_field_url: 'URL',
mcp_field_timeout: '逾時(秒)',
mcp_save: '儲存',
mcp_cancel: '取消',
mcp_name_required: '伺服器名稱為必填。',
mcp_url_required: 'HTTP 傳輸需要 URL。',
mcp_command_required: 'stdio 傳輸需要命令。',
mcp_saved: 'MCP 伺服器已儲存。',
mcp_save_failed: '儲存 MCP 伺服器失敗。',
mcp_delete_confirm_title: '刪除 MCP 伺服器',
mcp_delete_confirm_message: '刪除 MCP 伺服器「{0}」?此操作無法復原。',
mcp_deleted: 'MCP 伺服器已刪除。',
mcp_delete_failed: '刪除 MCP 伺服器失敗。',
mcp_load_failed: '載入 MCP 伺服器失敗。',
thinking: '\u601d\u8003\u904e\u7a0b',
expand_all: '\u5168\u90e8\u5c55\u958b',
collapse_all: '\u5168\u90e8\u6298\u758a',
edit_failed: '\u7de8\u8f2f\u5931\u6557\uff1a',
regen_failed: '\u91cd\u65b0\u751f\u6210\u5931\u6557\uff1a',
reconnect_active: '\u56de\u8986\u4ecd\u5728\u751f\u6210\u4e2d\uff0c\u6e96\u5099\u597d\u5f8c\u8981\u91cd\u65b0\u52a0\u8f09\u55ce\uff1f',
reconnect_finished: '\u4f60\u96e2\u958b\u6642\u6709\u56de\u8986\u6b63\u5728\u751f\u6210\uff0c\u8a0a\u606f\u5167\u5bb9\u53ef\u80fd\u5df2\u7d93\u66f4\u65b0\u3002',
// approval card
approval_heading: '\u9700\u8981\u5be9\u6838',
approval_desc_prefix: '\u6aa2\u6e2c\u5230\u5371\u96aa\u547d\u4ee4',
approval_btn_once: '\u5141\u8a31\u4e00\u6b21',
approval_btn_once_title: '\u5141\u8a31\u57f7\u884c\u6b64\u547d\u4ee4\u4e00\u6b21\uff08Enter\uff09',
approval_btn_session: '\u672c\u6b21\u5141\u8a31',
approval_btn_session_title: '\u672c\u6b21\u6703\u8a71\u671f\u9593\u5141\u8a31',
approval_btn_always: '始終允許',
approval_btn_always_title: '始終允許此命令模式',
approval_btn_deny: '\u62d2\u7d55',
approval_btn_deny_title: '\u62d2\u7edd — \u4e0d\u57f7\u884c\u6b64\u547d\u4ee4',
approval_responding: '\u8655\u7406\u4e2d\u2026',
clarify_heading: '\u9700\u8981\u91d0\u6e05',
clarify_hint: '\u8acb\u9078\u64c7\u4e00\u500b\u9078\u9805\uff0c\u6216\u5728\u4e0b\u65b9\u8f38\u5165\u4f60\u81ea\u5df1\u7684\u56de\u7b54\u3002',
clarify_other: '\u5176\u4ed6',
clarify_send: '\u9001\u51fa',
clarify_input_placeholder: '\u8f38\u5165\u4f60\u7684\u56de\u7b54\u2026',
clarify_responding: '\u8655\u7406\u4e2d\u2026',
untitled: '\u672a\u547d\u540d',
n_messages: (n) => `${n} \u689d\u8a0a\u606f`,
load_older_messages: '↑ 向上捲動或點擊以載入較早的訊息',
model_unavailable: '\uff08\u4e0d\u53ef\u7528\uff09',
model_unavailable_title: '\u6b64\u6a21\u578b\u5df2\u7d93\u4e0d\u5728\u7576\u524d provider \u5217\u8868\u4e2d',
provider_mismatch_warning: (m,p)=>`\"${m}\" \u53ef\u80fd\u7121\u6cd5\u5728\u7576\u524d\u914d\u7f6e\u7684\u63d0\u4f9b\u8005 (${p}) \u4e0b\u904b\u4f5c\u3002\u5c1a\u9001\uff0c\u6216\u5728\u7d42\u7aef\u57f7\u884c \`hermes model\` \u5207\u63db\u3002`,
provider_mismatch_label: '\u63d0\u4f9b\u8005\u4e0d\u76f8\u7b26',
model_not_found_label: '\u672a\u627e\u5230\u6a21\u578b',
// commands.js
cmd_help: '\u67e5\u770b\u53ef\u7528\u547d\u4ee4',
cmd_clear: '\u6e05\u7a7a\u7576\u524d\u5c0d\u8a71\u8a0a\u606f',
cmd_compress: '\u624b\u52d5\u58d3\u7e2e\u5c0d\u8a71\u4e0a\u4e0b\u6587\uff08\u7528\u6cd5\uff1a/compress [\u4e3b\u984c]\uff09',
ctx_compress_hint: '\u58d3\u7e2e\u4e0a\u4e0b\u6587\u4ee5\u91cb\u653e\u7a7a\u9593 →',
ctx_compress_action: '\u26a0 \u7acb\u5373\u58d3\u7e2e\u4ee5\u91cb\u653e\u4e0a\u4e0b\u6587',
cmd_compact_alias: '\u820a\u5225\u540d\uff1a/compress',
cmd_model: '\u5207\u63db\u6a21\u578b\uff08\u4f8b\u5982 /model gpt-4o\uff09',
cmd_workspace: '\u6309\u540d\u7a31\u5207\u63db\u5de5\u4f5c\u5340',
cmd_terminal: '\u6253\u958b\u5de5\u4f5c\u5340 Terminal',
cmd_new: '\u65b0\u5efa\u804a\u5929\u6703\u8a71',
cmd_usage: '\u5207\u63db token \u7528\u91cf\u986f\u793a',
cmd_theme: '\u5207\u63db\u5916\u89c0\uff08\u4e3b\u984c\uff1asystem/dark/light\uff0c\u76ae\u819a\uff1adefault/ares/mono/slate/poseidon/sisyphus/charizard\uff09',
cmd_personality: '\u5207\u63db Agent \u4eba\u8a2d',
cmd_skills: '\u5217\u51fa\u53ef\u7528\u7684 Hermes \u6280\u80fd',
available_commands: '\u53ef\u7528\u547d\u4ee4\uff1a',
type_slash: '\u8f38\u5165 / \u53ef\u67e5\u770b\u547d\u4ee4',
conversation_cleared: '\u5c0d\u8a71\u5df2\u6e05\u7a7a',
command_label: '\u547d\u4ee4',
context_compaction_label: '\u4e0a\u4e0b\u6587\u58d3\u7e2e',
preserved_task_list_label: '\u4fdd\u7559\u7684\u4efb\u52d9\u6e05\u55ae',
reference_only_label: '\u50c5\u4f9b\u53c3\u8003',
model_usage: '\u7528\u6cd5\uff1a/model <name>',
no_model_match: '\u6c92\u6709\u5339\u914d\u201c',
switched_to: '\u5df2\u5207\u63db\u5230 ',
workspace_usage: '\u7528\u6cd5\uff1a/workspace <name>',
no_workspace_match: '\u6c92\u6709\u5339\u914d\u201c',
switched_workspace: '\u5df2\u5207\u63db\u5de5\u4f5c\u5340\uff1a',
workspace_switch_failed: '\u5de5\u4f5c\u5340\u5207\u63db\u5931\u6557\uff1a',
new_session: '\u5df2\u65b0\u5efa\u6703\u8a71',
compressing: '\u6b63\u5728\u8981\u6c42\u58d3\u7e2e\u4e0a\u4e0b\u6587...',
compress_running_label: '\u58d3\u7e2e\u4e2d',
compress_complete_label: '\u58d3\u7e2e\u5b8c\u6210',
auto_compress_label: '\u81ea\u52d5\u58d3\u7e2e',
compress_failed_label: '\u58d3\u7e2e\u5931\u6557',
focus_label: '\u4e3b\u984c',
token_usage_on: 'Token \u7528\u91cf\u986f\u793a\u5df2\u958b\u555f',
token_usage_off: 'Token \u7528\u91cf\u986f\u793a\u5df2\u95dc\u9589',
theme_usage: '\u7528\u6cd5\uff1a/theme ',
theme_set: '\u4e3b\u984c\uff1a',
no_active_session: '\u7576\u524d\u6c92\u6709\u6d3b\u52d5\u6703\u8a71',
workspace_empty_no_path: '未選擇工作區。請在 設定 → 工作區 中設定工作區以瀏覽檔案。',
workspace_empty_dir: '此工作區為空。',
no_personalities: '\u6c92\u6709\u627e\u5230\u4eba\u8a2d\uff08\u53ef\u6dfb\u52a0\u5230 ~/.hermes/personalities/\uff09',
available_personalities: '\u53ef\u7528\u4eba\u8a2d\uff1a',
personality_switch_hint: '\n\n\u4f7f\u7528 `/personality <name>` \u5207\u63db\uff0c\u6216\u7528 `/personality none` \u6e05\u7a7a\u3002',
personalities_load_failed: '\u52a0\u8f7d\u4eba\u8a2d\u5931\u6557',
personality_cleared: '\u4eba\u8a2d\u5df2\u6e05\u7a7a',
personality_set: '\u7576\u524d\u4eba\u8a2d\uff1a',
failed_colon: '\u5931\u6557\uff1a',
// ui.js
no_workspace: '\u672a\u9078\u64c7\u5de5\u4f5c\u5340',
terminal_open_title: '\u6253\u958b\u5de5\u4f5c\u5340 Terminal',
terminal_no_workspace_title: '\u8acb\u5148\u9078\u64c7\u5de5\u4f5c\u5340\u518d\u6253\u958b Terminal',
terminal_title: 'Terminal',
terminal_clear: '\u6e05\u7a7a',
terminal_copy_output: '\u8907\u88fd\u8f38\u51fa',
terminal_restart: '\u91cd\u555f',
terminal_collapse: '\u6536\u5408',
terminal_expand: '\u5c55\u958b',
terminal_close: '\u95dc\u9589',
terminal_input_placeholder: '\u8f38\u5165\u547d\u4ee4...',
terminal_start_failed: 'Terminal \u555f\u52d5\u5931\u6557\uff1a',
terminal_input_failed: 'Terminal \u8f38\u5165\u5931\u6557\uff1a',
terminal_copy_failed: '\u8907\u88fd\u5931\u6557\uff1a',
terminal_error: 'Terminal \u932f\u8aa4',
// workspace.js
unsaved_confirm: '\u9810\u89bd\u5340\u6709\u672a\u5132\u5b58\u4fee\u6539\uff0c\u8981\u653e\u68c4\u66f4\u6539\u5e76\u7e7c\u7e8c\u8df3\u8ee2\u55ce\uff1f',
save: '\u5132\u5b58',
edit: '\u7de8\u8f2f',
save_title: '\u5132\u5b58\u4fee\u6539',
edit_title: '\u7de8\u8f2f\u6b64\u6587\u4ef6',
saved: '\u5df2\u5132\u5b58',
save_failed: '\u5132\u5b58\u5931\u6557\uff1a',
image_load_failed: '\u5716\u7247\u52a0\u8f09\u5931\u6557',
file_open_failed: '\u7121\u6cd5\u6253\u958b\u6587\u4ef6',
downloading: (name) => `\u6b63\u5728\u4e0b\u8f09 ${name}...`,
double_click_rename: '\u96d9\u64ca\u91cd\u547d\u540d',
renamed_to: '\u5df2\u91cd\u547d\u540d\u70ba ',
rename_failed: '\u91cd\u547d\u540d\u5931\u6557\uff1a',
delete_title: '\u522a\u9664',
delete_confirm: (name) => `\u8981\u522a\u9664 ${name} \u55ce\uff1f`,
delete_dir_confirm: (name) => `刪除資料夾 "${name}" 及其所有內容?`,
rename_title: '重新命名',
rename_prompt: '新名稱:',
deleted: '\u5df2\u522a\u9664 ',
delete_failed: '\u522a\u9664\u5931\u6557\uff1a',
reveal_in_finder: '\u5728\u6a94\u6848\u7ba1\u7406\u54e1\u4e2d\u986f\u793a',
reveal_failed: '\u986f\u793a\u5931\u6557\uff1a',
new_file_prompt: '\u65b0\u6587\u4ef6\u540d\uff08\u4f8b\u5982 notes.md\uff09\uff1a',
created: '\u5df2\u5275\u5efa ',
create_failed: '\u5275\u5efa\u5931\u6557\uff1a',
new_folder_prompt: '\u65b0\u6587\u4ef6\u593e\u540d\u7a31\uff1a',
folder_created: '\u5df2\u5275\u5efa\u6587\u4ef6\u593e ',
folder_create_failed: '\u5275\u5efa\u6587\u4ef6\u593e\u5931\u6557\uff1a',
workspace_auto_create_folder: '\u8cc7\u6599\u593e\u4e0d\u5b58\u5728\u6642\u5247\u5efa\u7acb',
folder_add_as_space_btn: '\u65b0\u589e\u70ba\u5de5\u4f5c\u5340',
folder_add_as_space_msg: '\u662f\u5426\u5c07\u6b64\u8cc7\u6599\u593e\u65b0\u589e\u70ba\u5de5\u4f5c\u5340\uff1f',
folder_add_as_space_title: '\u65b0\u589e\u70ba\u5de5\u4f5c\u5340\uff1f',
remove_title: '\u79fb\u9664',
empty_dir: '(空)',
upload_failed: '上傳失敗:',
all_uploads_failed: (n) => `${n} 個檔案全部上傳失敗`,
session_pin: '釘選對話',
session_unpin: '取消釘選',
session_pin_desc: '將此對話置頂',
session_unpin_desc: '從置頂移除',
session_pin_failed: '釘選失敗:',
session_move_project: '移至專案',
session_move_project_desc_has: '變更此對話的專案',
session_move_project_desc_none: '為此對話指定專案',
session_archive: '封存對話',
session_restore: '還原對話',
session_archive_desc: '隱藏此對話,直到開啟顯示封存',
session_restore_desc: '將此對話移回主清單',
session_archived: '對話已封存',
session_restored: '對話已還原',
session_archive_failed: '封存失敗:',
session_duplicate: '複製對話',
session_duplicate_desc: '建立一個相同工作區與模型的副本',
session_duplicated: '對話已複製',
session_duplicate_failed: '複製失敗:',
session_stop_response: 'Stop response',
session_stop_response_desc: 'Cancel the running response for this conversation',
session_delete: '刪除對話',
session_delete_desc: '永久移除這個對話',
session_select_mode: '選取',
session_select_mode_desc: '選取會話以批次管理',
session_select_all: '全選',
session_deselect_all: '取消全選',
session_selected_count: '已選 {0} 個',
session_batch_archive: '封存',
session_batch_delete: '刪除',
session_batch_move: '移至專案',
session_batch_delete_confirm: '刪除 {0} 個會話?',
session_batch_archive_confirm: '封存 {0} 個會話?',
session_no_selection: '未選取任何會話',
// settings panel
settings_heading_title: '控制中心',
settings_heading_subtitle: '偏好設定、對話工具與系統控制。',
settings_section_conversation_title: '對話',
settings_section_appearance_title: '外觀',
settings_section_appearance_meta: '主題、強調色與視覺風格。',
settings_section_preferences_title: '偏好設定',
settings_section_preferences_meta: 'Hermes Web UI 的預設值與介面行為。',
settings_section_system_title: '系統',
settings_section_system_meta: '實例版本與存取控制。',
settings_check_now: '立即檢查',
settings_checking: '檢查中\u2026',
settings_up_to_date: '已是最新 \u2713',
settings_updates_available: '有 {count} 個更新可用',
settings_updates_disabled: '更新檢查已禁用',
settings_update_check_failed: '更新檢查失敗',
settings_label_workspace_panel_open: '預設保持工作區面板開啓',
settings_desc_workspace_panel_open: '啟用後,工作區/檔案瀏覽器面板會在每次新會話時自動開啓。您仍可隨時手動關閉。',
open_in_browser: '在瀏覽器中開啓',
settings_dropdown_conversation: '對話',
settings_dropdown_appearance: '外觀',
settings_dropdown_preferences: '偏好設定',
settings_dropdown_providers: '供應商',
settings_dropdown_system: '系統',
settings_tab_conversation: '對話',
settings_tab_appearance: '外觀',
settings_tab_preferences: '偏好設定',
settings_tab_system: '系統',
settings_title: '\u8a2d\u5b9a',
settings_save_btn: '\u5132\u5b58\u8a2d\u5b9a',
settings_label_model: '\u9ed8\u8a8d\u6a21\u578b',
settings_desc_model: '\u7528\u65bc\u65b0\u6703\u8a71\u3002\u73fe\u6709\u6703\u8a71\u6703\u4fdd\u7559\u5404\u81ea\u9078\u5b9a\u7684\u6a21\u578b\u3002',
settings_label_send_key: '\u767c\u9001\u5feb\u6377\u9375',
settings_label_theme: '\u4e3b\u984c',
settings_label_skin: '佈景',
settings_label_font_size: '\u5b57\u9ad4\u5927\u5c0f',
font_size_small: '\u5c0f',
font_size_default: '\u9810\u8a2d',
font_size_large: '\u5927',
settings_autosave_saving: '\u5132\u5b58\u4e2d…',
settings_autosave_saved: '\u5df2\u5132\u5b58',
settings_autosave_failed: '\u5132\u5b58\u5931\u6557',
settings_autosave_retry: '\u91cd\u8a66',
settings_label_language: '\u8a9e\u8a00',
settings_label_token_usage: '\u986f\u793a token \u7528\u91cf',
settings_label_sidebar_density: '側邊欄密度',
cmd_reasoning: '切換思考區塊可見性(顯示/隱藏)或設定努力等級',
settings_label_external_sessions: '顯示外部會話',
settings_label_sync_insights: '\u540c\u6b65\u5230 insights',
settings_label_check_updates: '\u6aa2\u67e5\u66f4\u65b0',
settings_label_bot_name: '\u52a9\u624b\u540d\u7a31',
settings_label_password: '\u8a2a\u554f\u5bc6\u78bc',
settings_saved: '\u8a2d\u5b9a\u5df2\u5132\u5b58',
settings_save_failed: '\u5132\u5b58\u5931\u6557\uff1a',
settings_load_failed: '\u8a2d\u5b9a\u52a0\u8f09\u5931\u6557\uff1a',
archive_extracted: (n, c) => `\u5f9e ${c} \u500b\u58d3\u7e2e\u5305\u4e2d\u89e3\u58d3\u7e2e\u4e86 ${n} \u500b\u6a94\u6848`,
settings_saved_pw: '\u8a2d\u5b9a\u5df2\u5132\u5b58\uff0c\u5bc6\u78bc\u4fdd\u8b77\u5df2\u555f\u7528\uff0c\u7576\u524d\u700f\u89bd\u5668\u6703\u4fdd\u6301\u767b\u5165',
settings_saved_pw_updated: '\u8a2d\u5b9a\u5df2\u5132\u5b58\uff0c\u5bc6\u78bc\u5df2\u66f4\u65b0',
// login page
login_title: '\u767b\u5f55',
login_subtitle: '\u8f38\u5165\u5bc6\u78bc\u7e7c\u7e8c\u4f7f\u7528',
login_placeholder: '\u5bc6\u78bc',
login_btn: '\u767b\u5f55',
login_invalid_pw: '\u5bc6\u78bc\u932f\u8aa4',
login_conn_failed: '\u9023\u63a5\u5931\u6557',
// missing keys from English
dialog_confirm_title: '確認操作',
dialog_prompt_title: '輸入內容',
dialog_confirm_btn: '確認',
discard: '放棄',
clear: '清空',
create: '建立',
remove: '移除',
project_name_prompt: '專案名稱:',
tab_chat: '\u804a\u5929',
tab_memory: '\u8a18\u61b6',
tab_skills: '\u6280\u80fd',
tab_tasks: '\u4efb\u52d9',
tab_todos: '待辦',
tab_insights: '統計',
tab_workspaces: '\u5de5\u4f5c\u5340',
new_conversation: '新對話',
filter_conversations: '篩選對話',
scheduled_jobs: '排程任務',
new_job: '\u65b0\u4efb\u52d9',
search_skills: '\u641c\u5c0b\u6280\u80fd',
new_skill: '\u65b0\u6280\u80fd',
save_skill: '\u5132\u5b58\u6280\u80fd',
personal_memory: '\u500b\u4eba\u8a18\u61b6',
current_task_list: '\u76ee\u524d\u4efb\u52d9\u6e05\u55ae',
session_meta_messages: (n) => `${n} 則訊息`,
session_meta_children: (n) => `${n} 則子`,
new_profile: '\u65b0\u914d\u7f6e\u6a94',
transcript: '\u8a18\u9304',
download_transcript: '\u4e0b\u8f09\u8a18\u9304',
import: '\u5c0e\u5165',
editing: '\u7de8\u8f2f\u4e2d',
empty_title: '有什麼可以幫忙?',
empty_subtitle: '點擊上方按鈕開始對話',
cancel: '\u53d6\u6d88',
loading: '\u52a0\u8f09\u4e2d',
create_job: '\u5efa\u7acb\u4efb\u52d9',
suggest_plan: '幫我規劃一個小專案',
suggest_schedule: '今天的時程如何?',
suggest_files: '這個工作區有哪些檔案?',
sign_out: '\u767b\u51fa',
password_placeholder: '\u5bc6\u78bc',
password_env_var_locked: '\u76ee\u524d\u5df2\u8a2d\u5b9a HERMES_WEBUI_PASSWORD \u74b0\u5883\u8b8a\u6578\u4e14\u512a\u5148\u751f\u6548\u3002\u8acb\u53d6\u6d88\u8a2d\u5b9a\u4e26\u91cd\u65b0\u555f\u52d5\u4f3a\u670d\u5668\uff0c\u624d\u80fd\u5728\u6b64\u7ba1\u7406\u5bc6\u78bc\u3002',
password_env_var_locked_placeholder: '\u5df2\u9396\u5b9a\uff1a\u5df2\u8a2d\u5b9a HERMES_WEBUI_PASSWORD \u74b0\u5883\u8b8a\u6578',
disable_auth: '\u505c\u7528\u9a57\u8b49',
settings_label_sound: '\u901a\u77e5\u8072\u97f3',
settings_label_notifications: '\u700f\u89bd\u901a\u77e5',
settings_desc_sound: '助手完成回答時播放聲音。',
settings_desc_notifications: '當分頁在後台時,有回答完成時會顯示系統通知。',
settings_desc_token_usage: '\u5728\u52a9\u624b\u6bcf\u6b21\u56de\u7b54\u4e0b\u65b9\u986f\u793a Input/Output token \u6578\u91cf\u3002\u4e5f\u53ef\u4ee5\u7528 /usage \u5207\u63db\u3002',
settings_sidebar_density_compact: '精簡',
settings_sidebar_density_detailed: '詳細',
settings_desc_sidebar_density: '控制左側對話清單要顯示多少額外資訊。',
settings_label_auto_title_refresh: '\u81ea\u9002\u61c9\u6a19\u984c\u66f4\u65b0',
settings_auto_title_refresh_off: '\u95dc\u9589',
settings_auto_title_refresh_5: '\u6bcf 5 \u8f2a\u5c0d\u8a71',
settings_auto_title_refresh_10: '\u6bcf 10 \u8f2a\u5c0d\u8a71',
settings_auto_title_refresh_20: '\u6bcf 20 \u8f2a\u5c0d\u8a71',
settings_desc_auto_title_refresh: '\u57fa\u65bc\u6700\u65b0\u5c0d\u8a71\u81ea\u52d5\u91cd\u65b0\u751f\u6210\u6703\u8a71\u6a19\u984c\uff0c\u4f7f\u5176\u968f\u5c0d\u8a71\u767c\u5c55\u4fdd\u6301\u76f8\u95dc\u3002\u9700\u8981\u914d\u7f6e LLM \u6a19\u984c\u751f\u6210\u6a21\u578b\u3002',
settings_desc_external_sessions: '在會話列表中顯示來自 CLI、Telegram、Discord、Slack 等管道的對話。點擊可導入並繼續對話。',
settings_desc_sync_insights: '將 WebUI token 使用情況同步到 state.db,使 hermes /insights 包含瀏覽器會話數據。預設未啟用。',
settings_desc_check_updates: '當有更新的 WebUI 或助手版本時顯示標記。將在後台正常執行 Git-Fetch。',
settings_desc_bot_name: '助手在 UI 中的顯示名稱。預設未更改。',
settings_desc_password: '\u8a2d\u5b9a WebUI \u767b\u5165\u5bc6\u78bc\u3002\u5047\u5982\u5df2\u8a2d\u7f6e\uff0c\u6bcf\u6b21\u52a0\u8f09\u90fd\u9700\u8981\u767b\u5165\u3002',
onboarding_password_will_enable: '\u5c07\u6703\u555f\u7528',
onboarding_password_will_replace: '\u5c07\u6703\u53d6\u4ee3',
onboarding_password_keep_existing: '\u4fdd\u7559\u76ee\u524d\u5bc6\u78bc',
onboarding_password_remains_disabled: '\u6703\u7e7c\u7e8c\u4fdd\u6301\u95dc\u9589',
settings_label_sound: '\u901a\u77e5\u8072\u97f3',
// boot.js
cancelling: '\u6b63\u5728\u53d6\u6d88...',
cancel_failed: '\u53d6\u6d88\u5931\u6557\uff1a',
mic_denied: '\u9ea6\u514b\u98a8\u8a2a\u554f\u88ab\u62d2\u7d75\uff0c\u8acb\u6aa2\u67e5\u700f\u89bd\u5668\u6b0a\u9650\u3002',
mic_no_speech: '\u6c92\u6709\u6aa2\u6e2c\u5230\u8a71\u97f3\uff0c\u8acb\u518d\u5617\u4e00\u6b21\u3002',
mic_network: '\u8a71\u97f3\u8b58\u5225\u76ee\u524d\u4e0d\u53ef\u7528\u3002',
mic_error: '\u8a71\u97f3\u8f38\u5165\u51fa\u932f\uff1a',
session_imported: '\u6703\u8a71\u5df2\u5c0e\u5165',
import_failed: '\u5c0e\u5165\u5931\u6557\uff1a',
import_invalid_json: 'JSON \u7121\u6548',
image_pasted: '\u5df2\u7c98\u8cbc\u5716\u7247\uff1a',
// messages.js
edit_message: '\u7de8\u8f2f\u8a0a\u606f',
regenerate: '\u91cd\u65b0\u751f\u6210\u56de\u8986',
copy: '\u8907\u88fd',
copied: '\u5df2\u8907\u88fd',
// ui.js
workspace_desc: '\u8acb\u9078\u64c7\u5de5\u4f5c\u5340\uff0c\u6216\u8f09\u5165\u65b0\u540d\u7a31\u5beb\u4e00\u500b',
tab_profiles: '\u914d\u7f6e',
tab_settings: '\u8a2d\u5b9a',
profile_delete_confirm_message: '\u6b64\u914d\u7f6e\u6a94\u7684\u6240\u6709\u6703\u8a71\u3001\u8a2d\u5b9a\u3001\u6280\u80fd\u548c\u8a18\u61b6\u5c07\u88ab\u6c38\u4e45\u522a\u9664\u3002\u6b64\u64cd\u4f5c\u7121\u6cd5\u64a4\u92b7\u3002',
workspace_renamed: '\u5de5\u4f5c\u5340\u5df2\u91cd\u65b0\u547d\u540d',
cron_name_placeholder: '\u9078\u586b',
active_conversation_meta: (n) => `${n} 則訊息`,
all_uploads_failed: (n) => `${n} 個上傳失敗`,
cron_job_name_placeholder: '\u4efb\u52d9\u540d\u7a31',
cron_prompt_placeholder: '\u63d0\u793a\u8a5e',
cron_schedule_placeholder: '\u6392\u7a0b',
delete_confirm: (name) => `刪除「${name}」?`,
downloading: (filename) => `正在下載 ${filename}`,
n_messages: (n) => `${n} 則訊息`,
load_older_messages: '↑ 向上捲動或點擊以載入較早的訊息',
onboarding_api_key_help_prefix: '\u900f\u904e\u4ee5\u4e0b\u65b9\u5f0f\u5132\u5b58\u70ba Hermes .env \u6a94\u6848\u4e2d\u7684\u6a5f\u5bc6',
onboarding_api_key_label: 'API \u91d1\u9470',
onboarding_api_key_placeholder: '\u7559\u7a7a\u4ee5\u4fdd\u7559\u5df2\u5132\u5b58\u7684\u91d1\u9470',
onboarding_api_key_label_optional: 'API key (optional)', // TODO: translate
onboarding_api_key_placeholder_optional: 'Leave blank for keyless servers', // TODO: translate
onboarding_api_key_help_keyless: 'Most LM Studio / Ollama / vLLM installs run keyless — leave this blank if your server doesn\'t require authentication. Use the Test connection button to verify.', // TODO: translate
onboarding_back: '\u4e0a\u4e00\u6b65',
onboarding_badge: '\u9996\u6b21\u57f7\u884c',
onboarding_base_url_help: '\u7528\u65bc OpenAI \u76f8\u5bb9\u8def\u7531\u5668\u3001\u81ea\u67b6\u4f3a\u670d\u5668\u3001LiteLLM\u3001Ollama\u3001LM Studio\u3001vLLM \u7b49\u7aef\u9ede\u3002',
onboarding_base_url_label: '\u57fa\u790e URL',
onboarding_base_url_placeholder: 'https://your-endpoint.example/v1',
onboarding_check_agent: 'Hermes Agent',
onboarding_check_agent_missing: '\u907a\u5931\u6216\u50c5\u90e8\u5206\u53ef\u7528',
onboarding_check_agent_ready: '\u5df2\u5075\u6e2c\u5230\u4e26\u53ef\u4f9b\u532f\u5165',
onboarding_check_password: '\u5bc6\u78bc',
onboarding_check_password_disabled: '\u5c1a\u672a\u555f\u7528',
onboarding_check_password_enabled: '\u5df2\u555f\u7528',
onboarding_check_provider: '\u63d0\u4f9b\u8005\u914d\u7f6e',
onboarding_check_provider_partial: '\u5df2\u5132\u5b58\u4f46\u672a\u5b8c\u6210',
onboarding_check_provider_pending: '\u9700\u8981\u9a57\u8b49',
onboarding_check_provider_ready: '\u53ef\u958b\u59cb\u804a\u5929',
onboarding_complete: '\u521d\u59cb\u8a2d\u5b9a\u5b8c\u6210',
onboarding_config_file: '\u8a2d\u5b9a\u6a94\uff1a',
onboarding_continue: '\u7e7c\u7e8c',
onboarding_current_provider: '\u76ee\u524d\u914d\u7f6e\uff1a',
onboarding_custom_model_help: '\u5c0d\u65bc\u81ea\u8a02\u7aef\u9ede\uff0c\u8acb\u6307\u5b9a\u60a8\u7684\u4f3a\u670d\u5668\u9810\u671f\u7684\u6a21\u578b ID\u3002',
onboarding_custom_model_placeholder: 'your_model_name',
onboarding_env_file: '.env \u6a94\u6848\uff1a',
onboarding_error_base_url_required: '\u81ea\u8a02\u7aef\u9ede\u9700\u8981\u57fa\u790e URL\u3002',
onboarding_probe_test_button: 'Test connection', // TODO: translate
onboarding_probe_probing: 'Testing connection…', // TODO: translate
onboarding_probe_ok: 'Connected. {n} model(s) available.', // TODO: translate
onboarding_probe_error_generic: 'Could not reach the configured base URL.', // TODO: translate
onboarding_probe_error_invalid_url: 'Base URL must start with http:// or https://.', // TODO: translate
onboarding_probe_error_dns: 'Could not resolve the host. Check the URL or use the host\'s IP address.', // TODO: translate
onboarding_probe_error_connect_refused: 'Connection refused — the server may not be running on that address. From inside Docker, try the host IP instead of localhost.', // TODO: translate
onboarding_probe_error_timeout: 'The endpoint did not respond in time. Check that the server is running and the URL is correct.', // TODO: translate
onboarding_probe_error_http_4xx: 'The endpoint returned a client error. Check authentication and the URL path (typically ends in /v1).', // TODO: translate
onboarding_probe_error_http_5xx: 'The endpoint returned a server error. Check the LM Studio / Ollama server logs.', // TODO: translate
onboarding_probe_error_parse: 'The endpoint did not return a model list in the expected shape. Verify the URL points to the OpenAI-compatible API root.', // TODO: translate
onboarding_probe_error_unreachable: 'Could not reach the configured base URL.', // TODO: translate
onboarding_error_probe_failed: 'Could not validate the configured base URL.', // TODO: translate
onboarding_error_choose_model: '\u8acb\u5148\u9078\u64c7\u6a21\u578b\u518d\u7e7c\u7e8c\u3002',
onboarding_error_choose_workspace: '\u8acb\u5148\u9078\u64c7\u5de5\u4f5c\u5340\u518d\u7e7c\u7e8c\u3002',
onboarding_error_model_required: '\u9700\u8981\u6a21\u578b\u3002',
onboarding_error_provider_required: '\u8acb\u5148\u9078\u64c7\u8a2d\u5b9a\u6a21\u5f0f\u518d\u7e7c\u7e8c\u3002',
onboarding_error_workspace_required: '\u9700\u8981\u5de5\u4f5c\u5340\u3002',
onboarding_finish_help: '\u5b8c\u6210\u5f8c\uff0c<code>onboarding_completed</code> \u5c07\u5132\u5b58\u5728\u8a2d\u5b9a\u4e2d\uff0c\u60a8\u5c07\u9032\u5165\u6b63\u5e38\u61c9\u7528\u7a0b\u5f0f\u3002',
onboarding_lead: '\u5feb\u901f\u9010\u6b65\u8a2d\u5b9a\uff1a\u6aa2\u67e5 Hermes\u3001\u5132\u5b58\u63d0\u4f9b\u8005\u914d\u7f6e\u3001\u9078\u64c7\u5de5\u4f5c\u5340\u8207\u6a21\u578b\uff0c\u4e26\u53ef\u9078\u64c7\u52a0\u5165\u5bc6\u78bc\u4fdd\u8b77\u3002',
onboarding_missing_imports: '\u7f3a\u5c11\u7684\u532f\u5165\uff1a',
onboarding_model_label: '\u9810\u8a2d\u6a21\u578b',
onboarding_not_set: '\u672a\u8a2d\u5b9a',
onboarding_notice_finish: '\u60a8\u4e4b\u5f8c\u53ef\u4ee5\u96a8\u6642\u56de\u5230\u8a2d\u5b9a\u9801\u9762\u8b8a\u66f4\u9019\u4e9b\u503c\u3002',
onboarding_notice_password_enabled: '\u5bc6\u78bc\u5df2\u8a2d\u5b9a\u3002\u50c5\u5728\u9700\u8981\u53d6\u4ee3\u6642\u8f38\u5165\u65b0\u5bc6\u78bc\u3002',
onboarding_notice_password_recommended: '\u9078\u586b\uff0c\u4f46\u5efa\u8b70\u5728\u975e localhost \u74b0\u5883\u4f7f\u7528\u3002',
onboarding_notice_setup_already_ready: '\u5df2\u5075\u6e2c\u5230\u53ef\u7528\u7684 Hermes \u63d0\u4f9b\u8005\u914d\u7f6e\u3002\u60a8\u53ef\u4ee5\u4fdd\u7559\u6216\u5728\u6b64\u53d6\u4ee3\u3002',
onboarding_notice_setup_required: '\u5728\u6b64\u9078\u64c7\u5feb\u901f\u63d0\u4f9b\u8005\u8a2d\u5b9a\u8def\u5f91\u3002\u9032\u968e OAuth \u8a2d\u5b9a\u4ecd\u8acb\u4f7f\u7528 Hermes CLI\u3002',
onboarding_notice_system_ready: 'Hermes Agent \u53ef\u5f9e Web UI \u5b58\u53d6\u3002',
onboarding_notice_system_unavailable: 'Hermes Agent \u5c1a\u672a\u5b8c\u5168\u53ef\u7528\u3002\u5f15\u5c0e\u7a0b\u5f0f\u53ef\u80fd\u5b89\u88dd\u5b83\uff0c\u4f46\u63d0\u4f9b\u8005\u8a2d\u5b9a\u53ef\u80fd\u4ecd\u9700\u7d42\u7aef\u6a5f\u3002',
onboarding_notice_workspace: '\u9019\u4e9b\u503c\u4f7f\u7528\u8207\u4e00\u822c\u61c9\u7528\u7a0b\u5f0f\u76f8\u540c\u7684\u8a2d\u5b9a API\u3002',
onboarding_oauth_provider_not_ready_body: '\u6b64\u5be6\u4f8b\u8a2d\u5b9a\u4f7f\u7528 <strong>{provider}</strong>\uff0c\u5b83\u4f7f\u7528 OAuth \u800c\u975e API \u91d1\u9470\u3002\u8acb\u5728\u7d42\u7aef\u6a5f\u4e2d\u57f7\u884c <code>hermes auth</code> \u6216 <code>hermes model</code> \u9032\u884c\u6388\u6b0a\uff0c\u7136\u5f8c\u91cd\u65b0\u6574\u7406 Web UI\u3002',
onboarding_oauth_provider_not_ready_title: 'OAuth \u63d0\u4f9b\u8005\u5c1a\u672a\u6388\u6b0a',
onboarding_oauth_provider_ready_body: '\u6b64\u5be6\u4f8b\u8a2d\u5b9a\u4f7f\u7528\u900f\u904e Hermes CLI \u914d\u7f6e\u7684 OAuth \u63d0\u4f9b\u8005\uff08<strong>{provider}</strong>\uff09\u3002\u7121\u9700 API \u91d1\u9470 \u2014 \u6309\u7e7c\u7e8c\u5b8c\u6210\u8a2d\u5b9a\u3002',
onboarding_oauth_provider_ready_title: '\u63d0\u4f9b\u8005\u5df2\u6388\u6b0a',
onboarding_oauth_switch_hint: '\u6216\u9078\u64c7\u4e0b\u65b9\u5176\u4ed6\u63d0\u4f9b\u8005\u4ee5\u5207\u63db\u5230 API \u91d1\u9470\u8a2d\u5b9a\uff1a',
onboarding_open: '\u958b\u555f Hermes',
onboarding_password_help: '\u5bc6\u78bc\u900f\u904e\u73fe\u6709\u8a2d\u5b9a API \u5132\u5b58\uff0c\u4e26\u5728\u4f3a\u670d\u5668\u7aef\u9032\u884c\u96dc\u6e4a\u8655\u7406\u3002',
onboarding_password_label: '\u5bc6\u78bc\uff08\u9078\u586b\uff09',
onboarding_password_placeholder: '\u7559\u7a7a\u4ee5\u8df3\u904e',
onboarding_password_remains_disabled: '\u5c07\u4fdd\u6301\u505c\u7528',
onboarding_password_skipped: '\u66ab\u6642\u8df3\u904e',
onboarding_password_will_enable: '\u5c07\u555f\u7528',
onboarding_password_will_replace: '\u5c07\u53d6\u4ee3',
onboarding_provider_label: '\u8a2d\u5b9a\u6a21\u5f0f',
onboarding_quick_setup_badge: '\u5feb\u901f\u8a2d\u5b9a',
oauth_login_codex: 'Login with Codex (ChatGPT)', // TODO: translate
oauth_codex_step1: 'Step 1: Visit this URL and enter the code', // TODO: translate
oauth_codex_step2: 'Step 2: Enter this code on the page', // TODO: translate
oauth_codex_polling: 'Waiting for authorization...', // TODO: translate
oauth_codex_success: 'Codex OAuth login successful!', // TODO: translate
oauth_codex_error: 'OAuth login failed', // TODO: translate
oauth_codex_expired: 'Code expired, please try again', // TODO: translate
provider_category_easy_start: '\u5feb\u901f\u958b\u59cb',
provider_category_self_hosted: '\u672c\u5730 / \u958b\u6e90',
provider_category_specialized: '\u5c08\u696d\u670d\u52d9',
onboarding_skip: '\u8df3\u904e\u8a2d\u5b9a',
onboarding_skipped: '\u5df2\u8df3\u904e\u8a2d\u5b9a \u2014 \u4f7f\u7528\u73fe\u6709\u914d\u7f6e\u3002',
onboarding_step_finish_desc: '\u6aa2\u8996\u8a2d\u5b9a\u4e26\u9032\u5165\u61c9\u7528\u7a0b\u5f0f\u3002',
onboarding_step_finish_title: '\u5b8c\u6210',
onboarding_step_password_desc: '\u5206\u4eab\u524d\u4fdd\u8b77 Web UI\u3002',
onboarding_step_password_title: '\u9078\u586b\u5bc6\u78bc',
onboarding_step_setup_desc: '\u5132\u5b58\u6700\u5c0f\u53ef\u7528\u7684 Hermes \u63d0\u4f9b\u8005\u914d\u7f6e\u3002',
onboarding_step_setup_title: '\u63d0\u4f9b\u8005\u8a2d\u5b9a',
onboarding_step_system_desc: '\u9a57\u8b49 Hermes Agent \u8207\u914d\u7f6e\u53ef\u898b\u6027\u3002',
onboarding_step_system_title: '\u7cfb\u7d71\u6aa2\u67e5',
onboarding_step_workspace_desc: '\u70ba\u65b0\u6703\u8a71\u9078\u64c7\u9810\u8a2d\u503c\u3002',
onboarding_step_workspace_title: '\u5de5\u4f5c\u5340\u8207\u6a21\u578b',
onboarding_title: '\u6b61\u8fce\u4f7f\u7528 Hermes Web UI',
onboarding_unknown: '\u672a\u77e5',
onboarding_workspace_help: '\u9078\u64c7 Hermes \u5728\u8a2d\u5b9a\u5b8c\u6210\u5f8c\u7528\u65bc\u65b0\u804a\u5929\u5ba4\u7684\u6a21\u578b\u3002',
onboarding_workspace_label: '\u5de5\u4f5c\u5340',
onboarding_workspace_or_path: '\u6216\u8f38\u5165\u5de5\u4f5c\u5340\u8def\u5f91',
onboarding_workspace_placeholder: '/home/you/workspace',
project_name_prompt: '\u5c08\u6848\u540d\u7a31\uff1a',
provider_mismatch_warning: (provider) => `提供者不符:會話使用 ${provider}`,
session_meta_messages: (n) => `${n} 則訊息`,
session_meta_children: (n) => `${n} 則子`,
settings_label_model: '\u9810\u8a2d\u6a21\u578b',
skill_created: '\u6280\u80fd\u5df2\u5efa\u7acb',
skill_file_load_failed: '\u8f09\u5165\u6a94\u6848\u5931\u6557\uff1a',
skill_load_failed: '\u8f09\u5165\u6280\u80fd\u5931\u6557\uff1a',
skill_name_required: '\u9700\u8981\u6280\u80fd\u540d\u7a31',
skill_updated: '\u6280\u80fd\u5df2\u66f4\u65b0',
skills_no_match: '\u627e\u4e0d\u5230\u7b26\u5408\u7684\u6280\u80fd\u3002',
slash_skill_badge: '\u6280\u80fd',
slash_skill_desc: '\u547c\u53eb\u6b64\u6280\u80fd',
title_change_hint: '\u4f7f\u7528 /title <\u65b0\u540d\u7a31> \u91cd\u65b0\u547d\u540d\u3002',
title_current: '\u76ee\u524d\u6a19\u984c',
title_set: '\u6a19\u984c\u5df2\u8a2d\u70ba',
todos_no_active: '\u6b64\u6703\u8a71\u4e2d\u7121\u6d3b\u8e8d\u4efb\u52d9\u6e05\u55ae\u3002',
upload_failed: '\u4e0a\u50b3\u5931\u6557\uff1a',
active_conversation_none: '\u672a\u9078\u53d6\u6d3b\u8e8d\u6703\u8a71\u3002',
add: '\u65b0\u589e',
add_failed: '\u65b0\u589e\u5931\u6557\uff1a',
auth_disabled: '\u9a57\u8b49\u5df2\u505c\u7528 \u2014 \u5bc6\u78bc\u4fdd\u8b77\u5df2\u95dc\u9589',
cancel_unavailable: '\u7121\u6cd5\u53d6\u6d88\u3002',
clear_conversation_message: '\u6e05\u9664\u6240\u6709\u8a0a\u606f\uff1f\u6b64\u64cd\u4f5c\u7121\u6cd5\u5fa9\u539f\u3002',
clear_conversation_title: '\u6e05\u9664\u5c0d\u8a71',
clear_failed: '\u6e05\u9664\u5931\u6557\uff1a',
content_required: '\u9700\u8981\u5167\u5bb9',
create_failed: '\u5efa\u7acb\u5931\u6557\uff1a',
delete_failed: '\u522a\u9664\u5931\u6557\uff1a',
disable: '\u505c\u7528',
disable_auth: '\u505c\u7528\u9a57\u8b49',
disable_auth_confirm_message: '\u4efb\u4f55\u4eba\u90fd\u53ef\u4ee5\u5b58\u53d6\u6b64\u5be6\u4f8b\u3002',
disable_auth_confirm_title: '\u505c\u7528\u5bc6\u78bc\u4fdd\u8b77',
disable_auth_failed: '\u505c\u7528\u9a57\u8b49\u5931\u6557\uff1a',
discard_file_edits_message: '\u5207\u63db\u5de5\u4f5c\u5340\u5c07\u653e\u68c4\u672a\u5132\u5b58\u7684\u9810\u89bd\u8b8a\u66f4\u3002',
discard_file_edits_title: '\u653e\u68c4\u6a94\u6848\u7de8\u8f2f\uff1f',
dismiss: '\u95dc\u9589',
edit: '\u7de8\u8f2f',
error_prefix: '\u932f\u8aa4\uff1a',
linked_files: '\u95dc\u806f\u6a94\u6848',
manage_profiles: '\u7ba1\u7406\u8a2d\u5b9a\u6a94',
memory_notes_label: '\u8a18\u61b6\uff08\u5099\u8a3b\uff09',
model_custom_label: '\u81ea\u8a02\u6a21\u578b ID',
model_custom_placeholder: '\u4f8b\u5982 openai/gpt-5.4',
model_search_no_results: '\u627e\u4e0d\u5230\u6a21\u578b',
model_group_configured: '已設定',
ws_search_placeholder: '搜尋工作區…',
ws_no_results: '找不到工作區',
model_search_placeholder: '\u641c\u5c0b\u6a21\u578b\u2026',
session_toolsets: 'Session Toolsets', // TODO: translate
session_toolsets_desc: 'Restrict available tools for this session (blank = use global config)', // TODO: translate
session_toolsets_global: 'Global (default)', // TODO: translate
session_toolsets_custom: 'Custom', // TODO: translate
session_toolsets_placeholder: 'tool1, tool2, \u2026', // TODO: translate
session_toolsets_apply: 'Apply', // TODO: translate
session_toolsets_clear: 'Clear (use global)', // TODO: translate
session_toolsets_applied: 'Toolsets updated', // TODO: translate
session_toolsets_cleared: 'Toolsets cleared — using global config', // TODO: translate
session_toolsets_failed: 'Failed to update toolsets: ', // TODO: translate
model_scope_advisory: '\u5f9e\u4e0b\u4e00\u5247\u8a0a\u606f\u8d77\u9069\u7528\u65bc\u6b64\u6703\u8a71\u3002',
model_scope_toast: '\u5f9e\u4e0b\u4e00\u5247\u8a0a\u606f\u8d77\u9069\u7528\u65bc\u6b64\u6703\u8a71\u3002',
my_notes: '\u6211\u7684\u5099\u8a3b',
name_required: '\u9700\u8981\u540d\u7a31',
never: '\u5f9e\u4e0d',
no_active_session: '\u7121\u6d3b\u8e8d\u6703\u8a71',
cmd_queue: '\u5c07\u8a0a\u606f\u52a0\u5165\u4e0b\u4e00\u8f2a\u7684\u4f47\u5217',
cmd_interrupt: '\u53d6\u6d88\u7576\u524d\u56de\u5408\u4e26\u767c\u9001\u65b0\u8a0a\u606f',
cmd_steer: '\u5728\u56de\u5408\u9032\u884c\u4e2d\u6ce8\u5165\u7d3a\u6b63\uff0c\u4e0d\u4e2d\u65b7\u4ee3\u7406',
cmd_queue_no_msg: '\u7528\u6cd5\uff1a/queue <\u8a0a\u606f>',
cmd_queue_not_busy: '\u6c92\u6709\u6d3b\u52d5\u4efb\u52d9 \u2014 \u76f4\u63a5\u767c\u9001\u5373\u53ef',
cmd_queue_confirm: '\u8a0a\u606f\u5df2\u52a0\u5165\u4f47\u5217',
cmd_interrupt_no_msg: '\u7528\u6cd5\uff1a/interrupt <\u8a0a\u606f>',
cmd_interrupt_confirm: '\u5df2\u4e2d\u65ad \u2014 \u6b63\u5728\u767c\u9001\u65b0\u8a0a\u606f',
cmd_steer_no_msg: '\u7528\u6cd5\uff1a/steer <\u8a0a\u606f>',
cmd_steer_fallback: 'Steer \u4e0d\u53ef\u7528 \u2014 \u5df2\u52a0\u5165\u4e0b\u4e00\u8f2a\u4f47\u5217',
cmd_steer_delivered: 'Steer \u5df2\u9001\u9054 \u2014 \u4ee3\u7406\u5c07\u5728\u4e0b\u4e00\u500b\u5de5\u5177\u7d50\u679c\u4e2d\u770b\u5230',
steer_leftover_queued: 'Steer \u5df2\u52a0\u5165\u4e0b\u4e00\u8f2a\u4f47\u5217',
busy_steer_fallback: 'Steer \u4e0d\u53ef\u7528 \u2014 \u5df2\u52a0\u5165\u4e0b\u4e00\u8f2a\u4f47\u5217',
busy_interrupt_confirm: '\u5df2\u4e2d\u65ad \u2014 \u6b63\u5728\u767c\u9001\u65b0\u8a0a\u606f',
settings_label_busy_input_mode: '\u5fd9\u788c\u8f38\u5165\u6a21\u5f0f',
settings_desc_busy_input_mode: '\u63a7\u5236\u5728\u4ee3\u7406\u904b\u884c\u6642\u767c\u9001\u8a0a\u606f\u7684\u884c\u70ba\u3002\u4f47\u5217\u7b49\u5f85\uff1b\u4e2d\u65b7\u53d6\u6d88\u4e26\u91cd\u65b0\u958b\u59cb\uff1bSteer\u4e2d\u9014\u6ce8\u5165\u7d3a\u6b63\uff0c\u4e0d\u4e2d\u65b7\u3002',
settings_busy_input_mode_queue: '\u52a0\u5165\u4f47\u5217',
settings_busy_input_mode_interrupt: '\u4e2d\u65ad\u7576\u524d\u56de\u5408',
settings_busy_input_mode_steer: 'Steer\uff08\u4e2d\u9014\u7d3a\u6b63\uff09',
no_active_task: '\u7121\u57f7\u884c\u4e2d\u7684\u4efb\u52d9\u53ef\u505c\u6b62\u3002',
no_notes_yet: '\u5c1a\u7121\u5099\u8a3b\u3002',
no_profile_yet: '\u5c1a\u7121\u8a2d\u5b9a\u6a94\u3002',
not_available: '\u7121',
profile_active: '\u555f\u7528\u4e2d',
profile_api_key_placeholder: 'API \u91d1\u9470\uff08\u9078\u586b\uff09',
profile_api_keys_configured: 'API \u91d1\u9470\u5df2\u8a2d\u5b9a',
profile_base_url_placeholder: '\u57fa\u672c URL\uff08\u9078\u586b\uff0c\u4f8b\u5982 http://localhost:11434\uff09',
profile_base_url_rule: '\u57fa\u672c URL \u5fc5\u9808\u4ee5 http:// \u6216 https:// \u958b\u982d',
profile_clone_label: '\u5f9e\u555f\u7528\u4e2d\u7684\u8a2d\u5b9a\u6a94\u8907\u88fd\u914d\u7f6e',
profile_created: (name) => `設定檔 ${name} 已建立`,
profile_default_label: '\uff08\u9810\u8a2d\uff09',
profile_delete_confirm_title: (name) => `刪除設定檔「${name}」?`,
profile_deleted: (name) => `設定檔 ${name} 已刪除`,
profile_gateway_running: 'Gateway \u57f7\u884c\u4e2d',
profile_gateway_stopped: 'Gateway \u5df2\u505c\u6b62',
profile_name_placeholder: '\u8a2d\u5b9a\u6a94\u540d\u7a31\uff08\u5c0f\u5beb\u5b57\u6bcd\u3001\u6578\u5b57\u3001\u9023\u5b57\u865f\uff09',
profile_name_rule: '\u50c5\u9650\u5c0f\u5beb\u5b57\u6bcd\u3001\u6578\u5b57\u3001\u9023\u5b57\u865f\u548c\u5e95\u7dda',
profile_no_configuration: '\u7121\u914d\u7f6e',
profile_skill_count: (n) => `${n} 個技能`,
profile_switch_title: '\u5207\u63db\u5230\u6b64\u8a2d\u5b9a\u6a94',
profile_switched: (name) => `已切換到 ${name}`,
profile_switched_new_conversation: (name) => `已切換到 ${name}(新會話)`,
profile_use: '\u4f7f\u7528',
profiles_busy_switch: 'Agent \u57f7\u884c\u4e2d\u7121\u6cd5\u5207\u63db\u8a2d\u5b9a\u6a94',
profiles_load_failed: '\u8f09\u5165\u8a2d\u5b9a\u6a94\u5931\u6557',
profiles_no_profiles: '\u627e\u4e0d\u5230\u8a2d\u5b9a\u6a94\u3002',
remove: '\u79fb\u9664',
remove_failed: '\u79fb\u9664\u5931\u6557\uff1a',
rename_failed: '\u91cd\u65b0\u547d\u540d\u5931\u6557\uff1a',
retry_failed: '\u91cd\u8a66\u5931\u6557\uff1a',
save: '\u5132\u5b58',
save_failed: '\u5132\u5b58\u5931\u6557\uff1a',
session_time_bucket_last_week: '\u4e0a\u9031',
session_time_bucket_older: '\u66f4\u65e9',
session_time_bucket_this_week: '\u672c\u9031',
session_time_bucket_today: '\u4eca\u5929',
session_time_bucket_yesterday: '\u6628\u5929',
session_time_days_ago: (d) => `${d}\u5929`,
session_time_hours_ago: (h) => `${h}\u5c0f\u6642`,
session_time_last_week: '1\u9031',
session_time_minutes_ago: (m) => `${m}\u5206`,
session_time_unknown: '\u672a\u77e5',
settings_unsaved_changes: '\u60a8\u6709\u672a\u5132\u5b58\u7684\u8b8a\u66f4\u3002',
sign_out_failed: '\u767b\u51fa\u5931\u6557\uff1a',
stream_stopped: '\u56de\u61c9\u5df2\u505c\u6b62\u3002',
switch_failed: '\u5207\u63db\u5931\u6557\uff1a',
undid_messages_suffix: '\u5247\u8a0a\u606f\u3002',
undid_n_messages: '\u5df2\u79fb\u9664',
undo_exchange: '\u5fa9\u539f\u6700\u5f8c\u4e00\u8f2a',
undo_failed: '\u5fa9\u539f\u5931\u6557\uff1a',
user_profile: '\u4f7f\u7528\u8005\u8a2d\u5b9a\u6a94',
view: '\u6aa2\u8996',
workspace_add_path_placeholder: '\u65b0\u589e\u5de5\u4f5c\u5340\u8def\u5f91\uff08\u4f8b\u5982 /Users/you/project\uff09',
workspace_added: '\u5de5\u4f5c\u5340\u5df2\u65b0\u589e',
workspace_already_saved: '\u5de5\u4f5c\u5340\u5df2\u5132\u5b58 \u2014 \u5f9e\u6e05\u55ae\u4e2d\u9078\u53d6',
workspace_busy_switch: 'Agent \u57f7\u884c\u4e2d\u7121\u6cd5\u5207\u63db\u5de5\u4f5c\u5340',
workspace_choose_path: '\u9078\u64c7\u5de5\u4f5c\u5340\u8def\u5f91',
workspace_choose_path_meta: '\u65b0\u589e\u9a57\u8b49\u904e\u7684\u8def\u5f91\u4e26\u5207\u63db\u6b64\u6703\u8a71',
workspace_manage: '\u7ba1\u7406\u5de5\u4f5c\u5340',
workspace_manage_meta: '\u958b\u555f Spaces \u9762\u677f',
workspace_not_added: '\u5de5\u4f5c\u5340\u672a\u65b0\u589e',
workspace_paths_validated_hint: '\u8def\u5f91\u6703\u5148\u9a57\u8b49\u662f\u5426\u5b58\u5728\u518d\u5132\u5b58\u3002',
workspace_drag_hint: '拖曳以重新排列',
workspace_reorder_failed: '重新排列失敗',
workspace_remove_confirm_message: (name) => `移除工作區「${name}」?`,
workspace_remove_confirm_title: '\u79fb\u9664\u5de5\u4f5c\u5340',
workspace_removed: '\u5de5\u4f5c\u5340\u5df2\u79fb\u9664',
workspace_switch_prompt_confirm: '\u5207\u63db',
workspace_switch_prompt_message: '\u8f38\u5165\u5de5\u4f5c\u5340\u7684\u7d55\u5c0d\u8def\u5f91\u4ee5\u65b0\u589e\u4e26\u5207\u63db\u6b64\u6703\u8a71\u3002',
workspace_switch_prompt_placeholder: '/Users/you/project',
workspace_switch_prompt_title: '\u5207\u63db\u5de5\u4f5c\u5340',
workspace_switched_to: (name) => `已切換到 ${name}`,
workspace_use: '\u4f7f\u7528',
workspace_use_title: '\u5728\u7576\u524d\u6703\u8a71\u4e2d\u4f7f\u7528',
bg_complete: '\u80cc\u666f\u4efb\u52d9\u5b8c\u6210',
bg_error_multi: (n) => `${n} 個背景任務失敗`,
cmd_status: '顯示會話資訊',
memory_saved: '記憶已儲存',
profile_delete_title: '刪除此設定檔',
bg_error_single: (n) => `${n} 個背景任務失敗`,
bg_failed: '\u80cc\u666f\u4efb\u52d9\u5931\u6557\uff1a',
bg_label: '\u80cc\u666f\u7d50\u679c\uff1a',
bg_no_answer: '\uff08\u7121\u56de\u61c9\uff09',
bg_running: '\u80cc\u666f\u57f7\u884c\u4e2d\u2026',
btw_asking: '\u6b63\u5728\u8a62\u554f\u9644\u5e36\u554f\u984c\u2026',
btw_done: '\u9644\u5e36\u554f\u984c\u5df2\u56de\u7b54',
btw_failed: '\u9644\u5e36\u554f\u984c\u5931\u6557\uff1a',
btw_label: '\u9644\u5e36\u554f\u984c \u2014 \u4e0d\u5728\u6b77\u53f2\u8a18\u9304\u4e2d',
btw_no_answer: '\u672a\u6536\u5230\u56de\u61c9\u3002',
cmd_background: '\u5728\u80cc\u666f\u57f7\u884c\u63d0\u793a\u8a5e',
cmd_background_usage: '/background <\u63d0\u793a\u8a5e> \u2014 \u5e73\u884c\u57f7\u884c\u4e0d\u963b\u585e',
cmd_btw: '\u63d0\u51fa\u9644\u5e36\u554f\u984c\uff08\u66ab\u6642\u6027\uff09',
cmd_btw_usage: '/btw <\u554f\u984c> \u2014 \u4f7f\u7528\u7576\u524d\u6703\u8a71\u80cc\u666f\u63d0\u554f',
cmd_compact: '\u58d3\u7e2e\u5c0d\u8a71\u4e0a\u4e0b\u6587',
cmd_retry: '\u91cd\u65b0\u767c\u9001\u6700\u5f8c\u4e00\u689d\u8a0a\u606f',
cmd_stop: '\u505c\u6b62\u7576\u524d\u56de\u61c9',
cmd_title: '\u53d6\u5f97\u6216\u8a2d\u5b9a\u6703\u8a71\u6a19\u984c',
cmd_undo: '\u79fb\u9664\u6700\u5f8c\u4e00\u8f2a\u5c0d\u8a71',
cmd_voice: '\u5207\u63db\u9ea5\u514b\u98a8\u8f38\u5165',
cmd_voice_use_mic: '\u9ede\u64ca\u7de8\u8f2f\u5668\u4e2d\u7684\u9ea5\u514b\u98a8\u6309\u9215\u3002',
cmd_webui_only_session: '\u6b64\u6307\u4ee4\u4e0d\u9069\u7528\u65bc CLI \u532f\u5165\u7684\u6703\u8a71\u3002',
cron_all_runs: '\u6240\u6709\u57f7\u884c',
cron_completion_status: (n) => `${n} 次完成`,
cron_delete_confirm_message: '\u6b64\u64cd\u4f5c\u7121\u6cd5\u5fa9\u539f\u3002',
cron_delete_confirm_title: '\u522a\u9664\u6392\u7a0b\u4efb\u52d9',
cron_hide_runs: '\u96b1\u85cf\u57f7\u884c\u8a18\u9304',
cron_job_created: '\u6392\u7a0b\u4efb\u52d9\u5df2\u5efa\u7acb',
cron_duplicate: '\u8907\u88fd',
cron_duplicated: '\u4efb\u52d9\u5df2\u8907\u88fd\uff08\u5df2\u66ab\u505c\uff09',
cron_job_deleted: '\u6392\u7a0b\u4efb\u52d9\u5df2\u522a\u9664',
cron_job_name_placeholder: '\u4efb\u52d9\u540d\u7a31',
cron_job_paused: '\u6392\u7a0b\u4efb\u52d9\u5df2\u66ab\u505c',
cron_job_resumed: '\u6392\u7a0b\u4efb\u52d9\u5df2\u6062\u5fa9',
cron_job_triggered: '\u6392\u7a0b\u4efb\u52d9\u5df2\u89f8\u767c',
cron_job_updated: '\u6392\u7a0b\u4efb\u52d9\u5df2\u66f4\u65b0',
cron_last: '\u4e0a\u6b21',
cron_last_output: '\u6700\u5f8c\u8f38\u51fa',
cron_next: '\u4e0b\u6b21',
cron_no_jobs: '\u627e\u4e0d\u5230\u6392\u7a0b\u4efb\u52d9\u3002',
cron_no_runs_yet: '\uff08\u5c1a\u7121\u57f7\u884c\u8a18\u9304\uff09',
cron_pause: '\u66ab\u505c',
cron_prompt_placeholder: '\u63d0\u793a\u8a5e',
cron_prompt_required: '\u9700\u8981\u63d0\u793a\u8a5e',
cron_resume: '\u6062\u5fa9',
cron_run_now: '\u7acb\u5373\u57f7\u884c',
cron_schedule_placeholder: '\u6392\u7a0b',
cron_schedule_required: '\u9700\u8981\u6392\u7a0b',
cron_schedule_required_example: '\u9700\u8981\u6392\u7a0b\uff08\u4f8b\u5982 "0 9 * * *" \u6216 "every 1h"\uff09',
cron_status_active: '\u6d3b\u8e8d\u4e2d',
cron_status_running: '\u57f7\u884c\u4e2d\u2026',
cron_status_error: '\u932f\u8aa4',
cron_status_off: '\u672a\u555f\u7528',
cron_status_paused: '\u5df2\u66ab\u505c',
cron_status_needs_attention: '\u9700\u8981\u8655\u7406',
cron_attention_desc: '\u9019\u500b\u91cd\u8907\u6392\u7a0b\u4efb\u52d9\u6c92\u6709\u4e0b\u6b21\u57f7\u884c\u6642\u9593\u3002\u6392\u7a0b\u5668\u53ef\u80fd\u7121\u6cd5\u8a08\u7b97\u4e0b\u4e00\u6b21\u57f7\u884c\u3002',
cron_attention_croniter_hint: 'Gateway \u57f7\u884c\u74b0\u5883\u53ef\u80fd\u7f3a\u5c11 croniter \u5957\u4ef6\u3002\u8acb\u7528\u652f\u63f4 cron \u7684\u74b0\u5883\u91cd\u555f Gateway\uff0c\u7136\u5f8c\u6062\u5fa9\u9019\u500b\u4efb\u52d9\u3002',
cron_attention_resume: '\u6062\u5fa9\u4e26\u91cd\u65b0\u8a08\u7b97',
cron_jobs_project: '\u5b9a\u6642\u4efb\u52d9',
cron_attention_run_once: '\u7acb\u5373\u57f7\u884c\u4e00\u6b21',
cron_attention_copy_diagnostics: '\u8907\u88fd\u8a3a\u65b7\u8cc7\u8a0a',
cron_diagnostics_copied: '\u6392\u7a0b\u4efb\u52d9\u8a3a\u65b7\u8cc7\u8a0a\u5df2\u8907\u88fd',
providers_empty: '\u627e\u4e0d\u5230\u53ef\u8a2d\u5b9a\u7684\u63d0\u4f9b\u8005\u3002',
providers_enter_key: '\u8acb\u8f38\u5165 API \u91d1\u9470',
providers_key_placeholder_new: 'sk-...',
providers_key_placeholder_replace: '\u8f38\u5165\u65b0\u91d1\u9470\u4ee5\u53d6\u4ee3\u2026',
providers_key_removed: 'API \u91d1\u9470\u5df2\u79fb\u9664',
providers_key_updated: 'API \u91d1\u9470\u5df2\u5132\u5b58',
providers_oauth_hint: '\u5df2\u900f\u904e OAuth \u9a57\u8b49\u3002\u7121\u9700 API \u91d1\u9470\u3002',
providers_oauth_config_yaml_hint: '\u5df2\u900f\u904e config.yaml \u8a2d\u5b9a\u6b0a\u8b49\u3002\u8981\u66f4\u65b0\uff0c\u8acb\u7de8\u8f2f config.yaml \u4e2d\u7684 providers \u5340\u6bb5\uff0c\u6216\u57f7\u884c hermes auth\u3002',
providers_oauth_not_configured_hint: '\u5c1a\u672a\u9a57\u8b49\u3002\u8acb\u5728\u7d42\u7aef\u6a5f\u57f7\u884c hermes auth \u4ee5\u8a2d\u5b9a\u6b64\u63d0\u4f9b\u8005\u3002',
providers_remove: '\u79fb\u9664',
providers_removing: '\u79fb\u9664\u4e2d\u2026',
providers_save: '\u5132\u5b58',
providers_saving: '\u5132\u5b58\u4e2d\u2026',
providers_section_meta: '管理 AI 提供者的 API 金鑰。變更會立即生效。',
providers_section_title: '供應商',
providers_status_api_key: 'API 金鑰',
providers_status_configured: 'API \u91d1\u9470\u5df2\u8a2d\u5b9a',
providers_status_not_configured: '\u7121 API \u91d1\u9470',
providers_status_not_configured_label: '\u672a\u8a2d\u5b9a',
providers_status_oauth: 'OAuth',
providers_tab_title: '供應商',
status_agent_running: 'Agent 執行中',
status_profile: '個人資料',
status_hermes_home: 'Hermes 主目錄',
status_started: '開始時間',
status_tokens: 'Token',
status_no_tokens: '未使用 Token',
status_unknown: '未知',
status_completed: '\u5df2\u5b8c\u6210',
status_failed: '\u5931\u6557',
status_heading: '\u6703\u8a71\u72c0\u614b',
status_load_failed: '\u8f09\u5165\u72c0\u614b\u5931\u6557\uff1a',
status_messages: '\u8a0a\u606f\u6578',
status_model: '\u6a21\u578b',
status_no: '\u5426',
status_personality: '\u4eba\u8a2d',
status_session_id: '\u6703\u8a71 ID',
status_title: '\u6a19\u984c',
status_workspace: '\u5de5\u4f5c\u5340',
status_yes: '\u662f',
usage_default_model: '\u9810\u8a2d',
usage_estimated_cost: '\u9810\u4f30\u8cbb\u7528',
usage_heading: 'Token \u7528\u91cf',
usage_input_tokens: '\u8f38\u5165 Token',
usage_load_failed: '\u8f09\u5165\u7528\u91cf\u5931\u6557\uff1a',
usage_output_tokens: '\u8f38\u51fa Token',
usage_personality_none: '\u7121',
usage_settings_tip: '\u6ce8\u610f\uff1a\u8cbb\u7528\u70ba\u9810\u4f30\u503c\u3002',
usage_total: '\u7e3d Token \u6578',
usage_unknown: '\u672a\u77e5',
cmd_yolo: 'YOLO 模式切換',
yolo_no_session: '無活動工作階段',
yolo_enabled: '⚡ YOLO 模式已開啟 — 將跳過所有審批',
yolo_disabled: 'YOLO 模式已關閉',
cmd_branch:'Fork this conversation into a new session',
cmd_branch_usage:'/branch [name] — fork conversation (optionally with a name)',
branch_forked:'Forked into new session',
branch_failed:'Fork failed: ',
fork_from_here:'Fork from here',
forked_from:'Forked from',
yolo_pill_label: 'YOLO',
yolo_pill_title_active: 'YOLO 模式激活 — 點擊關閉',
approval_skip_all: '⚡ 本次工作階段全部跳過',
approval_skip_all_title: '跳過本次工作階段的所有審批提示',
// composer action tooltips
composer_send: '\u50b3\u9001\u8a0a\u606f',
composer_queue: '\u8a0a\u606f\u52a0\u5165\u4f47\u5217',
composer_interrupt: '\u4e2d\u65b7\u4e26\u50b3\u9001',
composer_steer: '\u5f15\u5c0e\u76ee\u524d\u56de\u61c9',
composer_stop: '\u505c\u6b62\u7522\u751f',
composer_disabled_clarify: '\u8acb\u56de\u8986\u4e0a\u65b9\u7684\u6f84\u6e05\u8981\u6c42',
composer_disabled_compression: '\u7b49\u5f85\u58d3\u7e2e\u5b8c\u6210',
composer_disabled_empty: '\u8acb\u8f38\u5165\u8a0a\u606f\u5f8c\u50b3\u9001',
composer_mobile_workspace: '工作區',
composer_mobile_model: '模型',
composer_mobile_reasoning: '推理',
composer_mobile_context: '上下文',
// Queued messages
queued_label: '回應後發送',
queued_count: (n) => n === 1 ? '1 已排隊' : `${n} 已排隊`,
queued_cancel: '取消排隊訊息',
// Skills
skill_deleted: '技能已刪除',
skill_delete_confirm: '確定要刪除此技能嗎?',
skills_empty_title: '尚無技能',
skills_empty_sub: '安裝技能以擴展代理的能力',
skills_edit: '編輯',
skills_delete: '刪除',
skills_back_to: '返回技能列表',
// Tasks
tasks_empty_title: '無任務',
tasks_empty_sub: '管理排程與背景任務',
// Workspaces
workspaces_empty_title: '尚無工作區',
workspaces_empty_sub: '設定工作區以組織您的專案',
// Profiles
profiles_empty_title: '尚無設定檔',
profiles_empty_sub: '建立設定檔以快速切換環境',
// Skill editor
skill_name: '名稱',
skill_category: '類別',
skill_category_placeholder: '例如: devops',
skill_content: '內容',
skill_content_placeholder: '輸入技能內容...',
skill_rename_not_supported: '此技能不支援重新命名',
skill_metadata: '中繼資料',
// Cron labels
cron_name_label: '任務名稱',
cron_schedule_label: '排程',
cron_schedule_hint: '例如: 0 9 * * *, every 2h, 30m',
cron_prompt_label: '提示',
cron_deliver_label: '發送至',
cron_deliver_local: '僅本地儲存',
cron_skills_label: '技能',
cron_skills_placeholder: '選用技能(逗號分隔)',
cron_skills_edit_hint: '定義要載入的技能',
// Workspace labels
workspace_name_label: '名稱',
workspace_name_placeholder: '例如: main-project',
workspace_path_label: '路徑',
workspace_path_required: '工作區路徑為必填',
workspace_path_readonly: '路徑由環境設定檔決定,無法變更',
workspace_new_title: '新增工作區',
// Profile labels
profile_name_label: '名稱',
profile_base_url_label: 'Base URL',
profile_api_key_label: 'API 金鑰',
media_audio_label: '音訊',
media_svg_label: '圖表',
media_video_label: '影片',
csv_loading: '載入 CSV',
csv_too_large: 'CSV 檔案過大,無法內嵌渲染',
csv_no_data: 'CSV 檔案資料不足,無法渲染為表格',
csv_error: '載入 CSV 檔案失敗',
csv_header_note: '第一列顯示為表格標題',
excalidraw_loading: '載入圖表',
excalidraw_too_large: 'Excalidraw 檔案過大,無法內嵌渲染',
excalidraw_invalid: '無效的 Excalidraw 檔案格式',
excalidraw_error: '載入 Excalidraw 檔案失敗',
excalidraw_label: '圖表',
excalidraw_download: '下載',
excalidraw_empty: '空圖表',
excalidraw_render_error: '渲染圖表失敗',
excalidraw_simplified: '簡化 SVG 預覽 — 與 Excalidraw 畫布不完全相同',
pdf_loading: '正在載入 PDF {0}…',
pdf_too_large: 'PDF 檔案過大,無法內嵌預覽',
pdf_no_pages: '無法渲染 PDF 預覽',
pdf_error: 'PDF 載入失敗',
pdf_download: '下載 PDF',
html_loading: '正在載入 HTML 預覽…',
html_too_large: 'HTML 檔案過大,無法內嵌預覽',
html_error: 'HTML 預覽載入失敗',
html_open_full: '開啟完整頁面',
html_sandbox_label: 'HTML 預覽',
// TTS (#499)
tts_listen: '收聽',
tts_not_supported: '語音合成無法使用',
settings_label_tts: '回覆語音合成',
settings_desc_tts: '在助手訊息上顯示喇叭按鈕',
settings_label_tts_auto_read: '自動朗讀回覆',
settings_desc_tts_auto_read: '自動朗讀助手回覆',
// Composer voice-mode pref (#1488)
settings_label_voice_mode: 'Hands-free voice mode button', // TODO: translate
settings_desc_voice_mode: 'Show the voice-mode button (audio waveform) next to the dictation mic. Lets you speak naturally — Hermes auto-sends after a pause and reads replies aloud. Requires a browser that supports both speech recognition and TTS.', // TODO: translate
settings_label_tts_voice: '語音',
settings_desc_tts_voice: '選擇語音合成聲音',
settings_label_tts_rate: '語速',
settings_label_tts_pitch: '音調',
checkpoint_date: 'Date', // TODO: translate
checkpoint_diff_files_changed: (n) => `${n} file${n === 1 ? '' : 's'} changed`, // TODO: translate
checkpoint_diff_no_changes: 'No differences found between this checkpoint and the current workspace.', // TODO: translate
checkpoint_diff_title: 'Changes in checkpoint', // TODO: translate
checkpoint_empty: 'No checkpoints found for this workspace.', // TODO: translate
checkpoint_error: 'Failed to load checkpoints', // TODO: translate
checkpoint_files: 'Files', // TODO: translate
checkpoint_loading: 'Loading checkpoints…', // TODO: translate
checkpoint_message: 'Message', // TODO: translate
checkpoint_restore: 'Restore', // TODO: translate
checkpoint_restore_confirm_message: (ckpt) => `Restore workspace to checkpoint "${ckpt}"? This will overwrite files with the saved versions. Files added after this checkpoint will not be deleted.`, // TODO: translate
checkpoint_restore_confirm_title: 'Restore checkpoint?', // TODO: translate
checkpoint_restored: 'Checkpoint restored', // TODO: translate
checkpoint_title: 'Checkpoints', // TODO: translate
checkpoint_view_diff: 'View diff', // TODO: translate
insights_activity_by_day: 'Activity by Day', // TODO: translate
insights_activity_by_hour: 'Activity by Hour', // TODO: translate
insights_cost: 'Estimated Cost', // TODO: translate
insights_footer: 'Showing data from the last {days} days', // TODO: translate
insights_input_tokens: 'Input', // TODO: translate
insights_messages: 'Messages', // TODO: translate
insights_models: 'Models', // TODO: translate
insights_no_cost: 'N/A', // TODO: translate
insights_output_tokens: 'Output', // TODO: translate
insights_peak_hour: 'Peak: {hour}', // TODO: translate
insights_sessions: 'Sessions', // TODO: translate
insights_title: 'Usage Analytics', // TODO: translate
insights_token_breakdown: 'Token Breakdown', // TODO: translate
insights_tokens: 'Tokens', // TODO: translate
insights_total: 'Total', // TODO: translate
settings_desc_api_redact: 'Self-hosted users can disable for transparency (not recommended for shared instances).', // TODO: translate
settings_label_api_redact: 'Redact sensitive data in API responses', // TODO: translate
voice_error: 'Voice not supported in this browser', // TODO: translate
voice_listening: 'Listening…', // TODO: translate
voice_mode_active: 'Voice mode on', // TODO: translate
voice_mode_off: 'Voice mode off', // TODO: translate
voice_speaking: 'Speaking…', // TODO: translate
voice_thinking: 'Thinking…', // TODO: translate
// Composer voice buttons (#1488)
voice_dictate: 'Dictate', // TODO: translate
voice_dictate_active: 'Stop dictation', // TODO: translate
voice_mode_toggle: 'Voice mode', // TODO: translate
voice_mode_toggle_active: 'Exit voice mode', // TODO: translate
subagent_children: 'Subagent sessions', // TODO: translate
},
pt: {
_lang: 'pt',
_label: 'Português',
_speech: 'pt-BR',
// boot.js
cancelling: 'Cancelando…',
cancel_failed: 'Falha ao cancelar: ',
mic_denied: 'Acesso ao microfone negado. Verifique as permissões do navegador.',
mic_no_speech: 'Nenhuma fala detectada. Tente novamente.',
mic_network: 'Reconhecimento de fala indisponível.',
mic_error: 'Erro no input de voz: ',
session_imported: 'Sessão importada',
import_failed: 'Falha na importação: ',
import_invalid_json: 'JSON inválido',
image_pasted: 'Imagem colada: ',
// messages.js
edit_message: 'Editar mensagem',
regenerate: 'Regenerar resposta',
copy: 'Copiar',
copied: 'Copiado!',
copy_failed: 'Falha ao copiar',
you: 'Você',
thinking: 'Pensando',
expand_all: 'Expandir tudo',
collapse_all: 'Recolher tudo',
edit_failed: 'Falha ao editar: ',
regen_failed: 'Falha ao regenerar: ',
reconnect_active: 'Uma resposta ainda está sendo gerada. Recarregar quando estiver pronto?',
reconnect_finished: 'Uma resposta estava em andamento quando você saiu. As mensagens podem ter atualizado.',
// approval card
approval_heading: 'Aprovação necessária',
approval_desc_prefix: 'Comando perigoso detectado',
approval_btn_once: 'Permitir uma vez',
approval_btn_once_title: 'Permitir este comando (Enter)',
approval_btn_session: 'Permitir sessão',
approval_btn_session_title: 'Permitir para esta sessão de conversa',
approval_btn_always: 'Sempre permitir',
approval_btn_always_title: 'Sempre permitir este padrão de comando',
approval_btn_deny: 'Negar',
approval_btn_deny_title: 'Negar — não executar este comando',
approval_responding: 'Respondendo…',
clarify_heading: 'Esclarecimento necessário',
clarify_hint: 'Escolha uma opção ou digite sua resposta abaixo.',
clarify_other: 'Outro',
clarify_send: 'Enviar',
clarify_input_placeholder: 'Digite sua resposta…',
clarify_responding: 'Respondendo…',
untitled: 'Sem título',
n_messages: (n) => `${n} mensagens`,
load_older_messages: '↑ Role para cima ou clique para carregar mensagens mais antigas',
queued_label: 'Envia após a resposta',
queued_count: (n) => n === 1 ? '1 na fila' : `${n} na fila`,
queued_cancel: 'Cancelar mensagem na fila',
model_unavailable: ' (indisponível)',
model_unavailable_title: 'Este modelo não está mais na sua lista de provedores',
provider_mismatch_warning: (m,p)=>`"${m}" pode não funcionar com seu provedor configurado (${p}). Enviar assim mesmo, ou execute \`hermes model\` no terminal para trocar.`,
provider_mismatch_label: 'Provedor incompatível',
model_not_found_label: 'Modelo não encontrado',
composer_mobile_workspace: 'Workspace',
composer_mobile_model: 'Modelo',
composer_mobile_reasoning: 'Raciocínio',
composer_mobile_context: 'Contexto',
model_custom_label: 'ID de modelo customizado',
model_custom_placeholder: 'ex: openai/gpt-5.4',
model_search_placeholder: 'Buscar modelos…',
session_toolsets: 'Session Toolsets', // TODO: translate
session_toolsets_desc: 'Restrict available tools for this session (blank = use global config)', // TODO: translate
session_toolsets_global: 'Global (default)', // TODO: translate
session_toolsets_custom: 'Custom', // TODO: translate
session_toolsets_placeholder: 'tool1, tool2, \u2026', // TODO: translate
session_toolsets_apply: 'Apply', // TODO: translate
session_toolsets_clear: 'Clear (use global)', // TODO: translate
session_toolsets_applied: 'Toolsets updated', // TODO: translate
session_toolsets_cleared: 'Toolsets cleared — using global config', // TODO: translate
session_toolsets_failed: 'Failed to update toolsets: ', // TODO: translate
model_search_no_results: 'Nenhum modelo encontrado',
model_group_configured: 'Configurados',
ws_search_placeholder: 'Buscar espaços de trabalho…',
ws_no_results: 'Nenhum espaço de trabalho encontrado',
// commands.js
cmd_clear: 'Limpar mensagens da conversa',
cmd_compress: 'Comprimir manualmente o contexto (uso: /compress [tópico])',
cmd_compact_alias: 'Alias legado para /compress',
cmd_model: 'Trocar modelo (ex: /model gpt-4o)',
cmd_workspace: 'Trocar workspace por nome',
cmd_new: 'Iniciar nova sessão de chat',
cmd_usage: 'Alternar exibição de uso de tokens',
cmd_theme: 'Trocar aparência (tema: system/dark/light, skin: default/ares/mono/slate/poseidon/sisyphus/charizard)',
cmd_personality: 'Trocar personalidade do agente',
cmd_skills: 'Listar skills disponíveis do Hermes',
available_commands: 'Comandos disponíveis:',
type_slash: 'Digite / para ver comandos',
conversation_cleared: 'Conversa limpa',
command_label: 'Comando',
context_compaction_label: 'Compactação de contexto',
preserved_task_list_label: 'Lista de tarefas preservada',
reference_only_label: 'Apenas referência',
model_usage: 'Uso: /model <nome>',
no_model_match: 'Nenhum modelo correspondendo "',
switched_to: 'Trocado para ',
workspace_usage: 'Uso: /workspace <nome>',
no_workspace_match: 'Nenhum workspace correspondendo "',
switched_workspace: 'Trocado para workspace: ',
workspace_switch_failed: 'Falha ao trocar workspace: ',
new_session: 'Nova sessão criada',
compressing: 'Solicitando compressão de contexto...',
compress_running_label: 'Comprimindo',
compress_complete_label: 'Compressão completa',
auto_compress_label: 'Compressão automática',
compress_failed_label: 'Falha na compressão',
focus_label: 'Foco',
token_usage_on: 'Uso de tokens ligado',
token_usage_off: 'Uso de tokens desligado',
theme_usage: 'Uso: /theme ',
theme_set: 'Tema: ',
no_active_session: 'Nenhuma sessão ativa',
cmd_queue: 'Enfileirar mensagem para o próximo turno',
cmd_interrupt: 'Cancelar turno atual e enviar nova mensagem',
cmd_steer: 'Injetar correção no meio do turno sem interromper',
cmd_queue_no_msg: 'Uso: /queue <mensagem>',
cmd_queue_not_busy: 'Nenhuma tarefa ativa — apenas envie normalmente',
cmd_queue_confirm: 'Mensagem enfileirada',
cmd_interrupt_no_msg: 'Uso: /interrupt <mensagem>',
cmd_interrupt_confirm: 'Interrompido — enviando nova mensagem',
cmd_steer_no_msg: 'Uso: /steer <mensagem>',
cmd_steer_fallback: 'Steer indisponível — enfileirado para próximo turno',
cmd_steer_delivered: 'Steer entregue — agente verá no próximo resultado',
steer_leftover_queued: 'Steer enfileirado para próximo turno',
busy_steer_fallback: 'Steer indisponível — enfileirado para próximo turno',
busy_interrupt_confirm: 'Interrompido — enviando nova mensagem',
settings_label_busy_input_mode: 'Modo de input ocupado',
settings_desc_busy_input_mode: 'Controla o que acontece ao enviar mensagem com agente rodando. Fila espera; Interromper cancela; Steer injeta correção.',
settings_busy_input_mode_queue: 'Enfileirar follow-up',
settings_busy_input_mode_interrupt: 'Interromper turno atual',
settings_busy_input_mode_steer: 'Steer (correção no meio do turno)',
slash_skill_badge: 'Skill',
slash_skill_desc: 'Invocar esta skill',
cmd_stop: 'Parar resposta atual',
cmd_title: 'Obter ou definir título da sessão',
cmd_retry: 'Reenviar última mensagem',
cmd_undo: 'Remover última troca',
cmd_btw: 'Fazer pergunta lateral (efêmera)',
cmd_btw_usage: '/btw <pergunta> — fazer pergunta lateral',
cmd_background: 'Rodar prompt em background',
cmd_background_usage: '/background <prompt> — rodar em paralelo',
btw_asking: 'Fazendo pergunta lateral...',
btw_label: 'Pergunta lateral — não no histórico',
btw_done: 'Pergunta lateral respondida',
btw_no_answer: 'Nenhuma resposta recebida.',
btw_failed: 'Pergunta lateral falhou: ',
cmd_branch:'Fork this conversation into a new session',
cmd_branch_usage:'/branch [name] — fork conversation (optionally with a name)',
branch_forked:'Forked into new session',
branch_failed:'Fork failed: ',
fork_from_here:'Fork from here',
forked_from:'Forked from',
bg_running: 'Rodando em background...',
bg_complete: 'Tarefa de background completa',
bg_label: 'Resultado de background:',
bg_no_answer: '(sem resposta)',
bg_failed: 'Tarefa de background falhou: ',
undo_exchange: 'Desfazer última troca',
cmd_status: 'Mostrar info da sessão',
cmd_voice: 'Alternar input de microfone',
stream_stopped: 'Resposta parada.',
no_active_task: 'Nenhuma tarefa ativa para parar.',
cancel_unavailable: 'Cancelar indisponível.',
retry_failed: 'Retry falhou: ',
undo_failed: 'Undo falhou: ',
undid_n_messages: 'Removido',
undid_messages_suffix: 'mensagem(s).',
status_heading: 'Status da Sessão',
status_session_id: 'ID da Sessão',
status_title: 'Título',
status_model: 'Modelo',
status_workspace: 'Workspace',
status_personality: 'Personalidade',
status_messages: 'Mensagens',
status_agent_running: 'Agente rodando',
status_profile: 'Perfil',
status_hermes_home: 'Diretório Hermes',
status_started: 'Iniciado',
status_tokens: 'Tokens',
status_no_tokens: 'Nenhum token usado',
status_unknown: 'Desconhecido',
status_yes: 'Sim',
status_no: 'Não',
status_load_failed: 'Falha ao carregar status: ',
title_current: 'Título atual',
title_change_hint: 'Use `/title <novo nome>` para renomear.',
title_set: 'Título definido como',
cmd_webui_only_session: 'Comando indisponível para sessões CLI.',
cmd_voice_use_mic: 'Clique no botão de mic no composer.',
usage_heading: 'Uso de Tokens',
usage_default_model: 'padrão',
usage_unknown: 'desconhecido',
usage_input_tokens: 'Tokens de input',
usage_output_tokens: 'Tokens de output',
usage_total: 'Total de tokens',
usage_estimated_cost: 'Custo estimado',
usage_settings_tip: 'Nota: estimativas são aproximadas.',
usage_load_failed: 'Falha ao carregar uso: ',
usage_personality_none: 'nenhuma',
no_personalities: 'Nenhuma personalidade encontrada (adicione em ~/.hermes/personalities/)',
available_personalities: 'Personalidades disponíveis:',
personality_switch_hint: '\n\nUse `/personality <nome>` para trocar, ou `/personality none` para limpar.',
personalities_load_failed: 'Falha ao carregar personalidades',
personality_cleared: 'Personalidade limpa',
personality_set: 'Personalidade: ',
failed_colon: 'Falhou: ',
// ui.js
no_workspace: 'Nenhum workspace',
workspace_empty_no_path: 'Nenhum workspace selecionado. Configure em Configurações → Workspace.',
workspace_empty_dir: 'Este workspace está vazio.',
dialog_confirm_title: 'Confirmar ação',
dialog_prompt_title: 'Digite um valor',
dialog_confirm_btn: 'Confirmar',
// workspace.js
unsaved_confirm: 'Você tem mudanças não salvas. Descartar e navegar?',
discard: 'Descartar',
save: 'Salvar',
edit: 'Editar',
clear: 'Limpar',
create: 'Criar',
remove: 'Remover',
save_title: 'Salvar mudanças',
edit_title: 'Editar este arquivo',
saved: 'Salvo',
save_failed: 'Falha ao salvar: ',
image_load_failed: 'Não foi possível carregar imagem',
file_open_failed: 'Não foi possível abrir arquivo',
downloading: (name) => `Baixando ${name}`,
double_click_rename: 'Duplo clique para renomear',
renamed_to: 'Renomeado para ',
rename_failed: 'Falha ao renomear: ',
delete_title: 'Excluir',
delete_confirm: (name) => `Excluir ${name}?`,
deleted: 'Excluído ',
delete_failed: 'Falha ao excluir: ',
reveal_in_finder: 'Mostrar no gerenciador de arquivos',
reveal_failed: 'Falha ao mostrar: ',
new_file_prompt: 'Nome do novo arquivo (ex: notes.md):',
project_name_prompt: 'Nome do projeto:',
created: 'Criado ',
create_failed: 'Falha ao criar: ',
new_folder_prompt: 'Nome da nova pasta:',
folder_created: 'Pasta criada ',
folder_create_failed: 'Falha ao criar pasta: ',
workspace_auto_create_folder: 'Criar pasta se não existir',
folder_add_as_space_btn: 'Adicionar como Space',
folder_add_as_space_msg: 'Adicionar esta pasta como novo space?',
folder_add_as_space_title: 'Adicionar como Space?',
remove_title: 'Remover',
empty_dir: '(vazio)',
upload_failed: 'Falha ao upload: ',
all_uploads_failed: (n) => `Todos ${n} upload(s) falharam`,
session_pin: 'Fixar conversa',
session_unpin: 'Desfixar conversa',
session_pin_desc: 'Manter esta conversa no topo',
session_unpin_desc: 'Remover dos fixados',
session_pin_failed: 'Falha ao fixar: ',
session_move_project: 'Mover para projeto',
session_move_project_desc_has: 'Mudar projeto desta conversa',
session_move_project_desc_none: 'Atribuir projeto a esta conversa',
session_archive: 'Arquivar conversa',
session_restore: 'Restaurar conversa',
session_archive_desc: 'Esconder conversa até mostrar arquivados',
session_restore_desc: 'Trazer conversa de volta à lista principal',
session_archived: 'Sessão arquivada',
session_restored: 'Sessão restaurada',
session_archive_failed: 'Falha ao arquivar: ',
session_duplicate: 'Duplicar conversa',
session_duplicate_desc: 'Criar cópia com mesmo workspace e modelo',
session_duplicated: 'Sessão duplicada',
session_duplicate_failed: 'Falha ao duplicar: ',
session_stop_response: 'Stop response',
session_stop_response_desc: 'Cancel the running response for this conversation',
session_delete: 'Excluir conversa',
session_delete_desc: 'Remover permanentemente esta conversa',
// settings panel
settings_heading_title: 'Control Center',
settings_heading_subtitle: 'Preferências, ferramentas de conversa e controles do sistema.',
settings_section_conversation_title: 'Conversa',
settings_section_appearance_title: 'Aparência',
settings_section_appearance_meta: 'Tema, cores de destaque e estilo visual.',
settings_section_preferences_title: 'Preferências',
settings_section_preferences_meta: 'Padrões e comportamento UI do Hermes Web UI.',
settings_section_system_title: 'Sistema',
settings_section_system_meta: 'Versão da instância e controles de acesso.',
settings_check_now: 'Verificar agora',
settings_checking: 'Verificando…',
settings_up_to_date: 'Atualizado ✓',
settings_updates_available: '{count} atualização(ões) disponível(is)',
settings_updates_disabled: 'Verificação de updates desativada',
settings_update_check_failed: 'Falha ao verificar updates',
settings_label_workspace_panel_open: 'Manter painel workspace aberto por padrão',
settings_desc_workspace_panel_open: 'Quando ativo, o painel workspace abre automaticamente com cada nova sessão.',
open_in_browser: 'Abrir no navegador',
settings_dropdown_conversation: 'Conversa',
settings_dropdown_appearance: 'Aparência',
settings_dropdown_preferences: 'Preferências',
settings_dropdown_providers: 'Provedores',
settings_dropdown_system: 'Sistema',
settings_tab_conversation: 'Conversa',
settings_tab_appearance: 'Aparência',
settings_tab_preferences: 'Preferências',
settings_tab_system: 'Sistema',
settings_title: 'Configurações',
settings_save_btn: 'Salvar Configurações',
settings_label_model: 'Modelo Padrão',
settings_label_send_key: 'Tecla de Envio',
settings_label_theme: 'Tema',
settings_label_skin: 'Skin',
settings_label_font_size: 'Tamanho da fonte',
font_size_small: 'Pequeno',
font_size_default: 'Padrão',
font_size_large: 'Grande',
settings_autosave_saving: 'Salvando…',
settings_autosave_saved: 'Salvo',
settings_autosave_failed: 'Falha ao salvar',
settings_autosave_retry: 'Tentar novamente',
settings_label_language: 'Idioma',
settings_label_token_usage: 'Mostrar uso de tokens',
settings_label_sidebar_density: 'Densidade da sidebar',
cmd_reasoning: 'Alternar visibilidade do pensamento (mostrar/ocultar)',
settings_label_external_sessions: 'Mostrar sessões externas',
settings_label_sync_insights: 'Sincronizar para insights',
settings_label_check_updates: 'Verificar atualizações',
settings_label_bot_name: 'Nome do Assistente',
settings_label_password: 'Senha de Acesso',
settings_saved: 'Configurações salvas',
settings_save_failed: 'Falha ao salvar: ',
settings_load_failed: 'Falha ao carregar configurações: ',
settings_saved_pw: 'Configurações salvas — senha ativada e navegador permanece logado',
settings_saved_pw_updated: 'Configurações salvas — senha atualizada',
// login page
login_title: 'Entrar',
login_subtitle: 'Digite sua senha para continuar',
login_placeholder: 'Senha',
login_btn: 'Entrar',
login_invalid_pw: 'Senha inválida',
login_conn_failed: 'Falha na conexão',
// Sidebar & Tabs
tab_chat: 'Chat',
tab_tasks: 'Tarefas',
tab_skills: 'Skills',
tab_memory: 'Memória',
tab_workspaces: 'Spaces',
tab_profiles: 'Perfis',
tab_kanban: 'Kanban',
kanban_board: 'Board',
kanban_visible_tasks: '{0} visible tasks',
kanban_search_tasks: 'Search tasks',
kanban_all_assignees: 'All assignees',
kanban_all_tenants: 'All tenants',
kanban_include_archived: 'Include archived',
kanban_no_matching_tasks: 'No matching tasks',
kanban_no_data: 'No Kanban data',
kanban_unavailable: 'Kanban unavailable',
kanban_read_only: 'Read-only view',
kanban_empty: 'Empty',
kanban_task: 'Task',
kanban_no_description: 'No description',
kanban_refresh: 'Refresh',
kanban_status_triage: 'Triage',
kanban_status_todo: 'Todo',
kanban_status_ready: 'Ready',
kanban_status_running: 'Running',
kanban_status_blocked: 'Blocked',
kanban_status_done: 'Done',
kanban_comments_count: 'Comments ({0})',
kanban_events_count: 'Events ({0})',
kanban_links: 'Links',
kanban_parents: 'Parents',
kanban_children: 'Children',
kanban_runs_count: 'Runs ({0})',
kanban_no_comments: 'No comments',
kanban_no_events: 'No events',
kanban_no_runs: 'No runs',
kanban_new_task: 'New task',
kanban_add_comment: 'Add comment',
kanban_only_mine: 'Only mine',
kanban_bulk_action: 'Bulk action',
kanban_nudge_dispatcher: 'Nudge dispatcher',
kanban_stats: 'Stats',
kanban_worker_log: 'Worker log',
kanban_block: 'Block',
kanban_unblock: 'Unblock',
kanban_back_to_board: 'Back to board',
kanban_lanes_by_profile: 'Lanes by profile',
kanban_new_board: 'New board…',
kanban_rename_board: 'Rename current board…',
kanban_archive_board: 'Archive current board…',
kanban_archive_board_confirm: 'Archive board "{name}"? Tasks remain on disk and the board can be restored from kanban/boards/_archived/.',
kanban_board_archived: 'Board archived',
kanban_board_name: 'Name',
kanban_board_slug: 'Slug (lowercase, hyphens)',
kanban_board_description: 'Description (optional)',
kanban_board_icon: 'Icon (emoji, optional)',
kanban_board_color: 'Color (optional)',
kanban_board_name_required: 'Name is required',
kanban_board_slug_required: 'Slug is required',
kanban_card_start: 'start',
kanban_card_complete: 'complete',
kanban_card_archive: 'archive',
kanban_unassigned: 'unassigned',
kanban_status_archived: 'Archived',
tab_todos: 'Todos',
tab_insights: 'Estatísticas',
tab_settings: 'Configurações',
new_conversation: 'Nova conversa',
filter_conversations: 'Filtrar conversas...',
session_time_unknown: 'Desconhecido',
session_time_minutes_ago: (n) => `${n}m`,
session_time_hours_ago: (n) => `${n}h`,
session_time_days_ago: (n) => `${n}d`,
session_time_last_week: '1s',
session_time_bucket_today: 'Hoje',
session_time_bucket_yesterday: 'Ontem',
session_time_bucket_this_week: 'Esta semana',
session_time_bucket_last_week: 'Semana passada',
session_time_bucket_older: 'Antigo',
scheduled_jobs: 'Tarefas agendadas',
new_job: 'Nova tarefa',
loading: 'Carregando...',
search_skills: 'Buscar skills...',
new_skill: 'Nova skill',
personal_memory: 'Memória pessoal',
current_task_list: 'Lista de tarefas atual',
workspace_desc: 'Adicionar e trocar workspaces para suas sessões.',
session_meta_messages: (n) => `${n} msg${n === 1 ? '' : 's'}`,
session_meta_children: (n) => `${n} child${n === 1 ? '' : 'ren'}`,
new_profile: 'Novo perfil',
transcript: 'Transcrição',
download_transcript: 'Baixar como Markdown',
import: 'Importar',
// Settings detail
settings_label_sound: 'Som de notificação',
settings_desc_sound: 'Tocar som quando assistente finalizar resposta.',
settings_label_notifications: 'Notificações do navegador',
settings_desc_notifications: 'Mostrar notificação quando resposta completar com app em background.',
settings_desc_token_usage: 'Exibe contagem de tokens abaixo de cada resposta. Também com /usage.',
settings_sidebar_density_compact: 'Compacto',
settings_sidebar_density_detailed: 'Detalhado',
settings_desc_sidebar_density: 'Controla quanto metadado a lista de sessões mostra na sidebar.',
settings_label_auto_title_refresh: 'Atualização adaptativa de título',
settings_auto_title_refresh_off: 'Desligado',
settings_auto_title_refresh_5: 'A cada 5 trocas',
settings_auto_title_refresh_10: 'A cada 10 trocas',
settings_auto_title_refresh_20: 'A cada 20 trocas',
settings_desc_auto_title_refresh: 'Re-gera título da sessão baseado na última troca.',
settings_desc_external_sessions: 'Mostrar conversas de CLI, Telegram, Discord, Slack e outros canais na lista de sessões. Clique para importar e continuar.',
settings_desc_sync_insights: 'Espelha uso de tokens para state.db.',
settings_desc_check_updates: 'Mostrar banner quando versões mais novas estiverem disponíveis.',
settings_desc_bot_name: 'Nome de exibição do assistente. Padrão: Hermes.',
settings_desc_password: 'Digite nova senha para definir ou trocar. Deixe em branco para manter.',
password_placeholder: 'Digite nova senha…',
password_env_var_locked: 'A variável de ambiente HERMES_WEBUI_PASSWORD está definida e tem prioridade. Remova-a e reinicie o servidor para gerenciar a senha aqui.',
password_env_var_locked_placeholder: 'Bloqueado: variável HERMES_WEBUI_PASSWORD está definida',
disable_auth: 'Desativar Auth',
sign_out: 'Sair',
// Providers panel
providers_tab_title: 'Provedores',
providers_section_title: 'Provedores',
providers_section_meta: 'Gerenciar API keys. Mudanças fazem efeito imediatamente.',
providers_status_configured: 'API key configurada',
providers_status_not_configured: 'Sem API key',
providers_status_oauth: 'OAuth',
providers_status_api_key: 'API key',
providers_status_not_configured_label: 'Não configurado',
providers_oauth_hint: 'Autenticado via OAuth. Sem API key necessária.',
providers_oauth_config_yaml_hint: 'Token configurado via config.yaml. Para atualizar, edite config.yaml ou rode hermes auth.',
providers_oauth_not_configured_hint: 'Não autenticado. Rode hermes auth no terminal.',
providers_save: 'Salvar',
providers_remove: 'Remover',
providers_saving: 'Salvando…',
providers_removing: 'Removendo…',
providers_enter_key: 'Por favor digite uma API key',
providers_empty: 'Nenhum provedor configurável encontrado.',
providers_key_updated: 'API key salva',
providers_key_removed: 'API key removida',
providers_key_placeholder_new: 'sk-...',
providers_key_placeholder_replace: 'Digite nova key para substituir…',
cancel: 'Cancelar',
create_job: 'Criar tarefa',
save_skill: 'Salvar skill',
editing: 'Editando',
// Empty state
empty_title: 'Como posso ajudar?',
empty_subtitle: 'Pergunte qualquer coisa, rode comandos, explore arquivos ou gerencie tarefas.',
suggest_files: 'Quais arquivos estão neste workspace?',
suggest_schedule: 'O que tenho na agenda hoje?',
suggest_plan: 'Me ajude a planejar um pequeno projeto.',
// onboarding
onboarding_badge: 'PRIMEIRO ACESSO',
onboarding_title: 'Bem-vindo ao Hermes Web UI',
onboarding_lead: 'Uma configuração rápida vai verificar Hermes, salvar provedor, escolher workspace e modelo, e opcionalmente proteger com senha.',
onboarding_back: 'Voltar',
onboarding_continue: 'Continuar',
onboarding_skip: 'Pular configuração',
onboarding_skipped: 'Configuração pulada — usando config existente.',
onboarding_open: 'Abrir Hermes',
onboarding_step_system_title: 'Verificação do sistema',
onboarding_step_system_desc: 'Verificar Hermes Agent e visibilidade da config.',
onboarding_step_setup_title: 'Configuração do provedor',
onboarding_step_setup_desc: 'Salvar config mínima do provedor Hermes.',
onboarding_step_workspace_title: 'Workspace + modelo',
onboarding_step_workspace_desc: 'Escolher padrões para novas sessões e chat.',
onboarding_step_password_title: 'Senha opcional',
onboarding_step_password_desc: 'Proteger Web UI antes de compartilhar.',
onboarding_step_finish_title: 'Finalizar',
onboarding_step_finish_desc: 'Revisar e entrar no app.',
onboarding_notice_system_ready: 'Hermes Agent parece acessível pela Web UI.',
onboarding_notice_system_unavailable: 'Hermes Agent não está totalmente disponível. Bootstrap pode instalar, mas setup do provedor pode requerer terminal.',
onboarding_check_agent: 'Hermes Agent',
onboarding_check_agent_ready: 'Detectado e importável',
onboarding_check_agent_missing: 'Ausente ou parcialmente importável',
onboarding_check_password: 'Senha',
onboarding_check_password_enabled: 'Já ativada',
onboarding_check_password_disabled: 'Não ativada ainda',
onboarding_check_provider: 'Config do provedor',
onboarding_check_provider_ready: 'Pronto para conversar',
onboarding_check_provider_partial: 'Salvo mas incompleto',
onboarding_check_provider_pending: 'Precisa verificação',
onboarding_config_file: 'Arquivo de config:',
onboarding_env_file: 'Arquivo .env:',
onboarding_unknown: 'Desconhecido',
onboarding_current_provider: 'Config atual:',
onboarding_missing_imports: 'Imports ausentes:',
onboarding_notice_setup_required: 'Escolha caminho simples de provedor aqui. OAuth avançado ainda pertence ao Hermes CLI.',
onboarding_notice_setup_already_ready: 'Setup de provedor Hermes já detectado. Pode manter ou substituir.',
onboarding_oauth_provider_ready_title: 'Provedor já autenticado',
onboarding_oauth_provider_ready_body: 'Esta instância usa provedor OAuth (<strong>{provider}</strong>) configurado via CLI. Sem API key necessária.',
onboarding_oauth_provider_not_ready_title: 'Provedor OAuth não autenticado',
onboarding_oauth_provider_not_ready_body: 'Esta instância usa <strong>{provider}</strong> com OAuth. Rode `hermes auth` no terminal.',
onboarding_oauth_switch_hint: 'Ou escolha provedor diferente abaixo para trocar para API-key:',
onboarding_notice_workspace: 'Estes valores reusam as mesmas APIs de settings do app normal.',
onboarding_workspace_label: 'Workspace',
onboarding_workspace_or_path: 'Ou digite path do workspace',
onboarding_workspace_placeholder: '/home/voce/workspace',
onboarding_provider_label: 'Modo de setup',
onboarding_quick_setup_badge: 'setup rápido',
provider_category_easy_start: 'Início fácil',
provider_category_self_hosted: 'Open / self-hosted',
provider_category_specialized: 'Especializado',
onboarding_api_key_label: 'API key',
oauth_login_codex: 'Login with Codex (ChatGPT)', // TODO: translate
oauth_codex_step1: 'Step 1: Visit this URL and enter the code', // TODO: translate
oauth_codex_step2: 'Step 2: Enter this code on the page', // TODO: translate
oauth_codex_polling: 'Waiting for authorization...', // TODO: translate
oauth_codex_success: 'Codex OAuth login successful!', // TODO: translate
oauth_codex_error: 'OAuth login failed', // TODO: translate
oauth_codex_expired: 'Code expired, please try again', // TODO: translate
onboarding_api_key_placeholder: 'Deixe em branco para manter key existente',
onboarding_api_key_label_optional: 'API key (optional)', // TODO: translate
onboarding_api_key_placeholder_optional: 'Leave blank for keyless servers', // TODO: translate
onboarding_api_key_help_keyless: 'Most LM Studio / Ollama / vLLM installs run keyless — leave this blank if your server doesn\'t require authentication. Use the Test connection button to verify.', // TODO: translate
onboarding_api_key_help_prefix: 'Salvo como segredo no .env do Hermes usando',
onboarding_base_url_label: 'Base URL',
onboarding_base_url_placeholder: 'https://seu-endpoint.exemplo/v1',
onboarding_base_url_help: 'Use para endpoints OpenAI-compatible, self-hosted, LiteLLM, Ollama, LM Studio, vLLM.',
onboarding_model_label: 'Modelo padrão',
onboarding_workspace_help: 'Escolha modelo que Hermes deve usar para novos chats.',
onboarding_custom_model_placeholder: 'nome-do-seu-modelo',
onboarding_custom_model_help: 'Para endpoints customizados, digite ID exato que seu servidor espera.',
onboarding_notice_password_enabled: 'Senha já configurada. Digite nova apenas se quiser substituir.',
onboarding_notice_password_recommended: 'Opcional mas recomendado se expor UI além de localhost.',
onboarding_password_label: 'Senha (opcional)',
onboarding_password_placeholder: 'Deixe em branco para pular',
onboarding_password_help: 'Senhas são salvas via settings API e hasheadas no servidor.',
onboarding_notice_finish: 'Pode reabrir Configurações depois para mudar qualquer coisa.',
onboarding_not_set: 'Não definido',
onboarding_password_will_enable: 'Será ativada',
onboarding_password_will_replace: 'Será substituída',
onboarding_password_keep_existing: 'Manter senha atual',
onboarding_password_remains_disabled: 'Permanecerá desativada',
onboarding_password_skipped: 'Pulado por enquanto',
onboarding_finish_help: 'Finalizar guarda <code>onboarding_completed</code> em settings e leva ao app normal.',
onboarding_error_choose_workspace: 'Escolha workspace antes de continuar.',
onboarding_error_choose_model: 'Escolha modelo antes de continuar.',
onboarding_error_provider_required: 'Escolha modo de setup antes de continuar.',
onboarding_error_base_url_required: 'Base URL é necessária para endpoints customizados.',
onboarding_probe_test_button: 'Test connection', // TODO: translate
onboarding_probe_probing: 'Testing connection…', // TODO: translate
onboarding_probe_ok: 'Connected. {n} model(s) available.', // TODO: translate
onboarding_probe_error_generic: 'Could not reach the configured base URL.', // TODO: translate
onboarding_probe_error_invalid_url: 'Base URL must start with http:// or https://.', // TODO: translate
onboarding_probe_error_dns: 'Could not resolve the host. Check the URL or use the host\'s IP address.', // TODO: translate
onboarding_probe_error_connect_refused: 'Connection refused — the server may not be running on that address. From inside Docker, try the host IP instead of localhost.', // TODO: translate
onboarding_probe_error_timeout: 'The endpoint did not respond in time. Check that the server is running and the URL is correct.', // TODO: translate
onboarding_probe_error_http_4xx: 'The endpoint returned a client error. Check authentication and the URL path (typically ends in /v1).', // TODO: translate
onboarding_probe_error_http_5xx: 'The endpoint returned a server error. Check the LM Studio / Ollama server logs.', // TODO: translate
onboarding_probe_error_parse: 'The endpoint did not return a model list in the expected shape. Verify the URL points to the OpenAI-compatible API root.', // TODO: translate
onboarding_probe_error_unreachable: 'Could not reach the configured base URL.', // TODO: translate
onboarding_error_probe_failed: 'Could not validate the configured base URL.', // TODO: translate
onboarding_error_workspace_required: 'Workspace é necessário.',
onboarding_error_model_required: 'Modelo é necessário.',
onboarding_complete: 'Configuração completa',
// panel/runtime i18n
error_prefix: 'Erro: ',
not_available: 'N/D',
never: 'nunca',
add: 'Adicionar',
add_failed: 'Falha ao adicionar: ',
remove_failed: 'Falha ao remover: ',
switch_failed: 'Falha ao trocar: ',
name_required: 'Nome é necessário',
content_required: 'Conteúdo é necessário',
view: 'Ver',
dismiss: 'Dispensar',
disable: 'Desativar',
cron_no_jobs: 'Nenhuma tarefa agendada encontrada.',
cron_status_off: 'desligado',
cron_status_paused: 'pausado',
cron_status_error: 'erro',
cron_status_active: 'ativo',
cron_status_running: 'rodando…',
cron_status_needs_attention: 'precisa atenção',
cron_attention_desc: 'Esta tarefa não tem próxima execução. Scheduler pode não ter calculado.',
cron_attention_croniter_hint: 'Gateway pode não ter pacote croniter. Reinicie com cron support.',
cron_attention_resume: 'Retomar e recalcular',
cron_jobs_project: 'Tarefas Agendadas',
cron_attention_run_once: 'Rodar uma vez agora',
cron_attention_copy_diagnostics: 'Copiar diagnóstico',
cron_diagnostics_copied: 'Diagnóstico copiado',
cron_next: 'Próxima',
cron_last: 'Última',
cron_run_now: 'Rodar agora',
cron_pause: 'Pausar',
cron_resume: 'Retomar',
cron_job_name_placeholder: 'Nome da tarefa',
cron_schedule_placeholder: 'Agendamento',
cron_prompt_placeholder: 'Prompt',
cron_last_output: 'Último output',
cron_all_runs: 'Todas execuções',
cron_hide_runs: 'Esconder execuções',
cron_no_runs_yet: '(sem execuções ainda)',
cron_schedule_required_example: 'Agendamento necessário (ex: "0 9 * * *" ou "every 1h")',
cron_schedule_required: 'Agendamento é necessário',
cron_prompt_required: 'Prompt é necessário',
cron_job_created: 'Tarefa criada',
cron_job_triggered: 'Tarefa acionada',
cron_job_paused: 'Tarefa pausada',
cron_job_resumed: 'Tarefa retomada',
cron_job_updated: 'Tarefa atualizada',
cron_delete_confirm_title: 'Excluir tarefa cron',
cron_delete_confirm_message: 'Isso não pode ser desfeito.',
cron_job_deleted: 'Tarefa excluída',
cron_completion_status: (name, status) => `Cron "${name}" ${status}`,
status_failed: 'falhou',
status_completed: 'completou',
todos_no_active: 'Nenhuma lista de tarefas ativa nesta sessão.',
clear_conversation_title: 'Limpar conversa',
clear_conversation_message: 'Limpar todas mensagens? Isso não pode ser desfeito.',
clear_failed: 'Falha ao limpar: ',
skills_no_match: 'Nenhuma skill corresponde.',
linked_files: 'Arquivos vinculados',
skill_load_failed: 'Não foi possível carregar skill: ',
skill_file_load_failed: 'Não foi possível carregar arquivo: ',
skills_empty_title: 'Selecione uma skill',
skills_empty_sub: 'Escolha skill da sidebar para ver conteúdo, ou crie nova.',
skills_edit: 'Editar',
skills_delete: 'Excluir',
skills_back_to: 'Voltar para {0}',
tasks_empty_title: 'Selecione tarefa agendada',
tasks_empty_sub: 'Escolha tarefa da sidebar para ver detalhes e execuções.',
workspaces_empty_title: 'Selecione um space',
workspaces_empty_sub: 'Escolha space da sidebar para ver arquivos e settings.',
profiles_empty_title: 'Selecione um perfil',
profiles_empty_sub: 'Escolha perfil da sidebar para ver e editar settings.',
memory_notes_label: 'memória (notas)',
memory_saved: 'Memória salva',
my_notes: 'Minhas Notas',
user_profile: 'Perfil do Usuário',
no_notes_yet: 'Nenhuma nota ainda.',
no_profile_yet: 'Nenhum perfil definido.',
// skill form
skill_name: 'Nome',
skill_category: 'Categoria',
skill_category_placeholder: 'Opcional, ex: devops',
skill_content: 'Conteúdo SKILL.md',
skill_content_placeholder: 'YAML frontmatter + markdown body',
skill_rename_not_supported: 'Renomear skill não suportado. Crie nova e exclua antiga.',
skill_metadata: 'Metadados',
// cron form
cron_name_label: 'Nome',
cron_name_placeholder: 'Opcional',
cron_schedule_label: 'Agendamento',
cron_schedule_hint: "Expressão Cron ou shorthand como 'every 1h'.",
cron_prompt_label: 'Prompt',
cron_deliver_label: 'Entregar output para',
cron_deliver_local: 'Local (salvar output apenas)',
cron_deliver_origin: 'Origem (mesmo chat)',
cron_deliver_telegram: 'Telegram',
cron_deliver_discord: 'Discord',
cron_skills_label: 'Skills',
cron_skills_placeholder: 'Adicionar skills (opcional)…',
cron_skills_edit_hint: 'Lista de skills não editável após criação.',
// workspace form
workspace_name_label: 'Nome',
workspace_name_placeholder: 'Nome amigável opcional',
workspace_path_label: 'Path',
workspace_path_required: 'Path é necessário',
workspace_path_readonly: 'Path não pode mudar. Apenas renomear.',
workspace_new_title: 'Novo space',
workspace_rename_title: 'Renomear space',
// profile form
profile_name_label: 'Nome',
profile_name_required: 'Nome é necessário',
profile_name_placeholder: 'ex: Trabalho, Pessoal',
profile_provider_label: 'Provedor',
profile_model_label: 'Modelo',
profile_model_required: 'Modelo é necessário',
profile_base_url_label: 'Base URL',
profile_base_url_placeholder: 'Opcional, ex: http://localhost:11434',
profile_api_key_label: 'API key',
profile_api_key_placeholder: 'Opcional',
manage_profiles: 'Gerenciar perfis',
profiles_load_failed: 'Falha ao carregar perfis',
profiles_busy_switch: 'Não pode trocar perfis com agente rodando',
profile_switched_new_conversation: (name) => `Trocado para perfil: ${name} — nova conversa iniciada`,
profile_switched: (name) => `Trocado para perfil: ${name}`,
profile_delete_confirm: (name) => `Excluir perfil "${name}"?`,
profile_deleted: 'Perfil excluído',
profile_delete_failed: 'Falha ao excluir perfil: ',
profile_create_failed: 'Falha ao criar perfil: ',
profile_update_failed: 'Falha ao atualizar perfil: ',
profile_already_exists: 'Perfil já existe',
// workspace switch dialog
workspace_switch_prompt_title: 'Trocar workspace',
workspace_switch_prompt_message: 'Digite path absoluto do workspace para adicionar e trocar.',
workspace_switch_prompt_confirm: 'Trocar',
workspace_switch_prompt_placeholder: '/Users/voce/projeto',
workspace_not_added: 'Workspace não adicionado',
workspace_already_saved: 'Workspace já salvo — escolha da lista',
workspace_busy_switch: 'Não pode trocar workspace com agente rodando',
discard_file_edits_title: 'Descartar edições de arquivo?',
discard_file_edits_message: 'Trocar workspace descarta edições não salvas no preview.',
workspace_switched_to: (name) => `Trocado para ${name}`,
workspace_use: 'Usar',
workspace_use_title: 'Usar nesta conversa',
workspace_add_title: 'Adicionar workspace',
// Approval card
approval_skip: 'Pular',
approval_skip_title: 'Pular este prompt de aprovação',
approval_skip_all: 'Pular todos',
approval_skip_all_title: 'Pular todos prompts de aprovação nesta sessão',
// TTS (#499)
tts_listen: 'Ouvir',
tts_not_supported: 'Síntese de voz não disponível',
settings_label_tts: 'Texto para voz nas respostas',
settings_desc_tts: 'Mostrar botão de alto-falante nas mensagens do assistente',
settings_label_tts_auto_read: 'Ler respostas automaticamente',
settings_desc_tts_auto_read: 'Ler automaticamente as respostas do assistente',
// Composer voice-mode pref (#1488)
settings_label_voice_mode: 'Hands-free voice mode button', // TODO: translate
settings_desc_voice_mode: 'Show the voice-mode button (audio waveform) next to the dictation mic. Lets you speak naturally — Hermes auto-sends after a pause and reads replies aloud. Requires a browser that supports both speech recognition and TTS.', // TODO: translate
settings_label_tts_voice: 'Voz',
settings_desc_tts_voice: 'Selecionar voz para síntese de voz',
settings_label_tts_rate: 'Velocidade da fala',
settings_label_tts_pitch: 'Tom da fala',
checkpoint_date: 'Date', // TODO: translate
checkpoint_diff_files_changed: (n) => `${n} file${n === 1 ? '' : 's'} changed`, // TODO: translate
checkpoint_diff_no_changes: 'No differences found between this checkpoint and the current workspace.', // TODO: translate
checkpoint_diff_title: 'Changes in checkpoint', // TODO: translate
checkpoint_empty: 'No checkpoints found for this workspace.', // TODO: translate
checkpoint_error: 'Failed to load checkpoints', // TODO: translate
checkpoint_files: 'Files', // TODO: translate
checkpoint_loading: 'Loading checkpoints…', // TODO: translate
checkpoint_message: 'Message', // TODO: translate
checkpoint_restore: 'Restore', // TODO: translate
checkpoint_restore_confirm_message: (ckpt) => `Restore workspace to checkpoint "${ckpt}"? This will overwrite files with the saved versions. Files added after this checkpoint will not be deleted.`, // TODO: translate
checkpoint_restore_confirm_title: 'Restore checkpoint?', // TODO: translate
checkpoint_restored: 'Checkpoint restored', // TODO: translate
checkpoint_title: 'Checkpoints', // TODO: translate
checkpoint_view_diff: 'View diff', // TODO: translate
insights_activity_by_day: 'Activity by Day', // TODO: translate
insights_activity_by_hour: 'Activity by Hour', // TODO: translate
insights_cost: 'Estimated Cost', // TODO: translate
insights_footer: 'Showing data from the last {days} days', // TODO: translate
insights_input_tokens: 'Input', // TODO: translate
insights_messages: 'Messages', // TODO: translate
insights_models: 'Models', // TODO: translate
insights_no_cost: 'N/A', // TODO: translate
insights_output_tokens: 'Output', // TODO: translate
insights_peak_hour: 'Peak: {hour}', // TODO: translate
insights_sessions: 'Sessions', // TODO: translate
insights_title: 'Usage Analytics', // TODO: translate
insights_token_breakdown: 'Token Breakdown', // TODO: translate
insights_tokens: 'Tokens', // TODO: translate
insights_total: 'Total', // TODO: translate
settings_desc_api_redact: 'Self-hosted users can disable for transparency (not recommended for shared instances).', // TODO: translate
settings_label_api_redact: 'Redact sensitive data in API responses', // TODO: translate
voice_error: 'Voice not supported in this browser', // TODO: translate
voice_listening: 'Listening…', // TODO: translate
voice_mode_active: 'Voice mode on', // TODO: translate
voice_mode_off: 'Voice mode off', // TODO: translate
voice_speaking: 'Speaking…', // TODO: translate
voice_thinking: 'Thinking…', // TODO: translate
// Composer voice buttons (#1488)
voice_dictate: 'Dictate', // TODO: translate
voice_dictate_active: 'Stop dictation', // TODO: translate
voice_mode_toggle: 'Voice mode', // TODO: translate
voice_mode_toggle_active: 'Exit voice mode', // TODO: translate
subagent_children: 'Subagent sessions', // TODO: translate
// login-flow keys (issue #1442)
sign_out_failed: 'Falha ao sair: ',
auth_disabled: 'Autenticação desativada — proteção por senha removida',
disable_auth_confirm_title: 'Desativar proteção por senha',
},
ko: {
_lang: 'ko',
_label: '한국어',
_speech: 'ko-KR',
// boot.js
cancelling: '취소 중\u2026',
cancel_failed: '취소 실패: ',
mic_denied: '마이크 접근이 거부되었습니다. 브라우저 권한을 확인하세요.',
mic_no_speech: '음성이 감지되지 않았습니다. 다시 시도하세요.',
mic_network: '음성 인식을 사용할 수 없습니다.',
mic_error: '음성 입력 오류: ',
session_imported: '세션을 가져왔습니다',
import_failed: '가져오기 실패: ',
import_invalid_json: '잘못된 JSON입니다',
image_pasted: '붙여넣은 이미지: ',
// messages.js
edit_message: '메시지 편집',
regenerate: '응답 다시 생성',
copy: '복사',
copied: '복사됨!',
copy_failed: '복사 실패',
diff_loading: 'diff 불러오는 중',
diff_error: '패치 파일을 로드할 수 없습니다',
diff_too_large: '패치 파일이 너무 커서 인라인으로 표시할 수 없습니다',
tree_view: 'Tree',
raw_view: 'Raw',
parse_failed_note: 'parse failed',
you: '나',
mcp_servers_title: 'MCP Servers',
mcp_servers_desc: 'Manage Model Context Protocol servers configured in config.yaml.',
mcp_no_servers: 'No MCP servers configured.',
mcp_add_server: '+ Add Server',
mcp_field_name: 'Server Name',
mcp_transport_label: 'Transport Type',
mcp_field_command: 'Command',
mcp_field_args: 'Arguments (comma-separated)',
mcp_field_url: 'URL',
mcp_field_timeout: 'Timeout (seconds)',
mcp_save: 'Save',
mcp_cancel: 'Cancel',
mcp_name_required: 'Server name is required.',
mcp_url_required: 'URL is required for HTTP transport.',
mcp_command_required: 'Command is required for stdio transport.',
mcp_saved: 'MCP server saved.',
mcp_save_failed: 'Failed to save MCP server.',
mcp_delete_confirm_title: 'Delete MCP Server',
mcp_delete_confirm_message: 'Delete MCP server "{0}"? This cannot be undone.',
mcp_deleted: 'MCP server deleted.',
mcp_delete_failed: 'Failed to delete MCP server.',
mcp_load_failed: 'Failed to load MCP servers.',
thinking: '생각 중',
expand_all: '모두 펼치기',
collapse_all: '모두 접기',
edit_failed: 'Edit failed: ',
regen_failed: 'Regenerate failed: ',
reconnect_active: 'A response is still being generated. Reload when ready?',
reconnect_finished: 'A response was in progress when you last left. Messages may have updated.',
// approval card
approval_heading: '승인 필요',
approval_desc_prefix: '위험한 명령이 감지되었습니다',
approval_btn_once: '한 번 허용',
approval_btn_once_title: '이 명령만 허용(Enter)',
approval_btn_session: '세션 허용',
approval_btn_session_title: '이 대화 세션 동안 허용',
approval_btn_always: '항상 허용',
approval_btn_always_title: '이 명령 패턴을 항상 허용',
approval_btn_deny: '거부',
approval_btn_deny_title: '거부 — 이 명령을 실행하지 않음',
approval_responding: '응답 중\u2026',
clarify_heading: '확인 필요',
clarify_hint: '선택지를 고르거나 아래에 직접 입력하세요.',
clarify_other: '기타',
clarify_send: '보내기',
clarify_input_placeholder: '응답을 입력하세요…',
clarify_responding: '응답 중\u2026',
untitled: '제목 없음',
n_messages: (n) => `${n}개 메시지`,
load_older_messages: '↑ 위로 스크롤하거나 클릭하여 이전 메시지 불러오기',
queued_label: 'Sends after response',
queued_count: (n) => n === 1 ? '1 queued' : `${n} queued`,
queued_cancel: 'Cancel queued message',
model_unavailable: ' (unavailable)',
model_unavailable_title: 'This model is no longer in your current provider list',
provider_mismatch_warning: (m,p)=>`"${m}" may not work with your configured provider (${p}). Send anyway, or run \`hermes model\` in your terminal to switch.`,
provider_mismatch_label: 'Provider mismatch',
model_not_found_label: 'Model not found',
model_custom_label: 'Custom model ID',
model_custom_placeholder: 'e.g. openai/gpt-5.4',
model_search_placeholder: 'Search models…',
session_toolsets: 'Session Toolsets', // TODO: translate
session_toolsets_desc: 'Restrict available tools for this session (blank = use global config)', // TODO: translate
session_toolsets_global: 'Global (default)', // TODO: translate
session_toolsets_custom: 'Custom', // TODO: translate
session_toolsets_placeholder: 'tool1, tool2, \u2026', // TODO: translate
session_toolsets_apply: 'Apply', // TODO: translate
session_toolsets_clear: 'Clear (use global)', // TODO: translate
session_toolsets_applied: 'Toolsets updated', // TODO: translate
session_toolsets_cleared: 'Toolsets cleared — using global config', // TODO: translate
session_toolsets_failed: 'Failed to update toolsets: ', // TODO: translate
model_search_no_results: 'No models found',
model_group_configured: '구성됨',
ws_search_placeholder: '워크스페이스 검색…',
ws_no_results: '워크스페이스를 찾을 수 없습니다',
model_scope_advisory: '다음 메시지부터 이 대화에 적용됩니다.',
model_scope_toast: '다음 메시지부터 이 대화에 적용됩니다.',
// commands.js
cmd_clear: '대화 메시지 지우기',
cmd_compress: 'Manually compress conversation context (usage: /compress [focus topic])',
ctx_compress_hint: '\ucee8\ud14d\uc2a4\ud2b8 \uc555\ucd95\ud558\uba70 \uacf5\uac04 \ud655\ubcf4 →',
ctx_compress_action: '\u26a0 \uc9c0\uae08 \uc555\ucd95\ud558\uba70 \ucee8\ud14d\uc2a4\ud2b8 \ud655\ubcf4',
cmd_compact_alias: 'Legacy alias for /compress',
cmd_model: '모델 전환(예: /model gpt-4o)',
cmd_workspace: '이름으로 워크스페이스 전환',
cmd_terminal: '워크스페이스 터미널 열기',
cmd_new: '새 채팅 세션 시작',
cmd_usage: '토큰 사용량 표시 켜기/끄기',
cmd_theme: 'Switch appearance (theme: system/dark/light, skin: default/ares/mono/slate/poseidon/sisyphus/charizard)',
cmd_personality: 'Switch agent personality',
cmd_skills: 'List available Hermes skills',
available_commands: '사용 가능한 명령:',
type_slash: '/ 를 입력해 명령 보기',
conversation_cleared: '대화를 지웠습니다',
command_label: '명령',
context_compaction_label: 'Context compaction',
preserved_task_list_label: '보존된 작업 목록',
reference_only_label: 'Reference only',
model_usage: 'Usage: /model <name>',
no_model_match: 'No model matching "',
switched_to: 'Switched to ',
workspace_usage: 'Usage: /workspace <name>',
no_workspace_match: 'No workspace matching "',
switched_workspace: 'Switched to workspace: ',
workspace_switch_failed: 'Workspace switch failed: ',
new_session: '새 세션을 만들었습니다',
compressing: 'Requesting context compression...',
compress_running_label: 'Compressing',
compress_complete_label: 'Compression complete',
auto_compress_label: '자동 압축',
compress_failed_label: 'Compression failed',
focus_label: 'Focus',
token_usage_on: 'Token usage on',
token_usage_off: 'Token usage off',
theme_usage: 'Usage: /theme ',
theme_set: 'Theme: ',
no_active_session: '활성 세션 없음',
cmd_queue: 'Queue a message for the next turn',
cmd_interrupt: 'Cancel current turn and send a new message',
cmd_steer: 'Inject a mid-turn correction without interrupting the agent',
cmd_queue_no_msg: 'Usage: /queue <message>',
cmd_queue_not_busy: 'No active task — just send normally',
cmd_queue_confirm: 'Message queued',
cmd_interrupt_no_msg: 'Usage: /interrupt <message>',
cmd_interrupt_confirm: 'Interrupted — sending new message',
cmd_steer_no_msg: 'Usage: /steer <message>',
cmd_steer_fallback: 'Steer unavailable — queued for next turn instead',
cmd_steer_delivered: 'Steer delivered — agent will see it on its next tool result',
steer_leftover_queued: 'Steer queued for next turn',
busy_steer_fallback: 'Steer unavailable — queued for next turn',
busy_interrupt_confirm: 'Interrupted — sending new message',
settings_label_busy_input_mode: '작업 중 입력 방식',
settings_desc_busy_input_mode: '에이전트가 실행 중일 때 메시지를 보내면 어떻게 처리할지 제어합니다. 대기는 다음 차례까지 기다리고, 중단은 현재 작업을 취소하고 새로 시작하며, 조정은 현재 작업을 중단하지 않고 중간 수정 사항을 전달합니다(에이전트 또는 스트림을 사용할 수 없으면 대기로 전환).',
settings_busy_input_mode_queue: '후속 메시지 대기',
settings_busy_input_mode_interrupt: '현재 작업 중단',
settings_busy_input_mode_steer: '조정(중간 수정)',
slash_skill_badge: '스킬',
slash_skill_desc: '이 스킬 실행',
cmd_stop: '현재 응답 중지',
cmd_title: '세션 제목 보기 또는 설정',
cmd_retry: '마지막 메시지 다시 보내기',
cmd_undo: '마지막 교환 제거',
cmd_btw: '곁질문하기(임시)',
cmd_btw_usage: '/btw <질문> — 세션 맥락을 사용해 곁질문하기',
cmd_background: '백그라운드에서 프롬프트 실행',
cmd_background_usage: '/background <프롬프트> — 차단하지 않고 병렬 실행',
btw_asking: '곁질문 중...',
btw_label: '곁질문 — 기록에 저장되지 않음',
btw_done: '곁질문 답변 완료',
btw_no_answer: '답변을 받지 못했습니다.',
btw_failed: '곁질문 실패: ',
bg_running: '백그라운드에서 실행 중...',
bg_complete: '백그라운드 작업 완료',
bg_label: '백그라운드 결과:',
bg_no_answer: '(답변 없음)',
bg_failed: '백그라운드 작업 실패: ',
undo_exchange: '마지막 교환 실행 취소',
cmd_status: '세션 정보 표시',
cmd_voice: '마이크 입력 전환',
stream_stopped: '응답이 중지되었습니다.',
no_active_task: '중지할 활성 작업이 없습니다.',
cancel_unavailable: '취소를 사용할 수 없습니다.',
retry_failed: '재시도 실패: ',
undo_failed: '실행 취소 실패: ',
undid_n_messages: '제거됨',
undid_messages_suffix: '개 메시지.',
status_heading: '세션 상태',
status_session_id: '세션 ID',
status_title: '제목',
status_model: '모델',
status_workspace: '워크스페이스',
status_personality: '페르소나',
status_messages: '메시지',
status_agent_running: '에이전트 실행 중',
status_profile: '프로필',
status_hermes_home: 'Hermes 홈',
status_started: '시작 시간',
status_tokens: '토큰',
status_no_tokens: '사용된 토큰 없음',
status_unknown: '알 수 없음',
status_yes: '예',
status_no: '아니요',
status_load_failed: '상태를 불러오지 못했습니다: ',
title_current: '현재 제목',
title_change_hint: '`/title <새 이름>`으로 이름을 변경하세요.',
title_set: '제목 설정됨:',
cmd_webui_only_session: '이 명령은 CLI에서 가져온 세션에서 사용할 수 없습니다.',
cmd_voice_use_mic: '작성창의 마이크 버튼을 클릭하세요.',
usage_heading: '토큰 사용량',
usage_default_model: '기본값',
usage_unknown: '알 수 없음',
usage_input_tokens: '입력 토큰',
usage_output_tokens: '출력 토큰',
usage_total: '총 토큰',
usage_estimated_cost: '예상 비용',
usage_settings_tip: '참고: 비용 추정치는 대략적인 값입니다.',
usage_load_failed: '사용량을 불러오지 못했습니다: ',
usage_personality_none: '없음',
no_personalities: 'No personalities found (add them to ~/.hermes/personalities/)',
available_personalities: 'Available personalities:',
personality_switch_hint: '\n\nUse `/personality <name>` to switch, or `/personality none` to clear.',
personalities_load_failed: 'Failed to load personalities',
personality_cleared: 'Personality cleared',
personality_set: 'Personality: ',
failed_colon: 'Failed: ',
// ui.js
no_workspace: 'No workspace',
terminal_open_title: '워크스페이스 터미널 열기',
terminal_no_workspace_title: '터미널을 열 워크스페이스를 선택하세요',
terminal_title: '터미널',
terminal_clear: '지우기',
terminal_copy_output: '출력 복사',
terminal_restart: '다시 시작',
terminal_collapse: '접기',
terminal_expand: '펼치기',
terminal_close: '닫기',
terminal_input_placeholder: '명령 입력...',
terminal_start_failed: '터미널 시작 실패: ',
terminal_input_failed: '터미널 입력 실패: ',
terminal_copy_failed: '복사 실패: ',
terminal_error: '터미널 오류',
workspace_empty_no_path: 'No workspace selected. Set a workspace in Settings \u2192 Workspace to browse files.',
workspace_empty_dir: 'This workspace is empty.',
dialog_confirm_title: 'Confirm action',
dialog_prompt_title: 'Enter a value',
dialog_confirm_btn: 'Confirm',
// workspace.js
unsaved_confirm: 'You have unsaved changes in the preview. Discard and navigate?',
discard: '버리기',
save: '저장',
edit: '편집',
clear: '지우기',
create: '만들기',
remove: '제거',
save_title: 'Save changes',
edit_title: 'Edit this file',
saved: '저장됨',
save_failed: '저장 실패: ',
image_load_failed: 'Could not load image',
file_open_failed: 'Could not open file',
downloading: (name) => `Downloading ${name}\u2026`,
double_click_rename: 'Double-click to rename',
renamed_to: 'Renamed to ',
rename_failed: 'Rename failed: ',
delete_title: '삭제',
delete_confirm: (name) => `${name}을(를) 삭제할까요?`,
delete_dir_confirm: (name) => `"${name}" 폴더와 모든 내용을 삭제할까요?`,
rename_title: '이름 바꾸기',
rename_prompt: '새 이름:',
deleted: '삭제됨: ',
delete_failed: '삭제 실패: ',
reveal_in_finder: '파일 관리자에서 열기',
reveal_failed: '표시 실패: ',
new_file_prompt: 'New file name (e.g. notes.md):',
project_name_prompt: 'Project name:',
created: '생성됨: ',
create_failed: '생성 실패: ',
new_folder_prompt: 'New folder name:',
folder_created: 'Created folder ',
folder_create_failed: 'Create folder failed: ',
workspace_auto_create_folder: '폴더가 없으면 생성',
folder_add_as_space_btn: '스페이스로 추가',
folder_add_as_space_msg: '이 폴더를 워크스페이스 목록의 새 스페이스로 추가할까요?',
archive_extracted: (n, c) => `${c}개 압축 파일에서 ${n}개 파일 압축 해제됨`,
folder_add_as_space_title: '스페이스로 추가할까요?',
remove_title: 'Remove',
empty_dir: '(비어 있음)',
upload_failed: 'Upload failed: ',
all_uploads_failed: (n) => `All ${n} upload(s) failed`,
session_pin: 'Pin conversation',
session_unpin: 'Unpin conversation',
session_pin_desc: 'Keep this conversation at the top',
session_unpin_desc: 'Remove from pinned',
session_pin_failed: 'Pin failed: ',
session_move_project: 'Move to project',
session_move_project_desc_has: 'Change the project for this conversation',
session_move_project_desc_none: 'Assign a project to this conversation',
session_archive: 'Archive conversation',
session_restore: 'Restore conversation',
session_archive_desc: 'Hide this conversation until archived is shown',
session_restore_desc: 'Bring this conversation back into the main list',
session_archived: 'Session archived',
session_restored: 'Session restored',
session_archive_failed: 'Archive failed: ',
session_duplicate: 'Duplicate conversation',
session_duplicate_desc: 'Create a copy with the same workspace and model',
session_duplicated: 'Session duplicated',
session_duplicate_failed: 'Duplicate failed: ',
session_stop_response: 'Stop response',
session_stop_response_desc: 'Cancel the running response for this conversation',
session_delete: 'Delete conversation',
session_delete_desc: 'Permanently remove this conversation',
session_select_mode: '선택',
session_select_mode_desc: '일괄 관리할 대화를 선택하세요',
session_select_all: '전체 선택',
session_deselect_all: '전체 해제',
session_selected_count: '{0}개 선택됨',
session_batch_archive: '보관',
session_batch_delete: '삭제',
session_batch_move: '프로젝트로 이동',
session_batch_delete_confirm: '{0}개의 대화를 삭제하시겠습니까?',
session_batch_archive_confirm: '{0}개의 대화를 보관하시겠습니까?',
session_no_selection: '선택된 대화가 없습니다',
// settings panel
settings_heading_title: '제어 센터',
settings_heading_subtitle: '환경설정, 대화 도구, 시스템 제어.',
settings_section_conversation_title: '대화',
settings_section_appearance_title: '외형',
settings_section_appearance_meta: '테마, 강조 색상, 시각 스타일.',
settings_section_preferences_title: '환경설정',
settings_section_preferences_meta: 'Hermes Web UI의 기본값과 UI 동작.',
settings_section_system_title: '시스템',
settings_section_system_meta: '인스턴스 버전과 접근 제어.',
settings_check_now: '지금 확인',
settings_checking: '확인 중\u2026',
settings_up_to_date: '최신 상태 \u2713',
settings_updates_available: '{count} update(s) available',
settings_updates_disabled: 'Update checks disabled',
settings_update_check_failed: 'Update check failed',
settings_label_workspace_panel_open: '기본으로 워크스페이스 패널 열기',
settings_desc_workspace_panel_open: '활성화하면 새 세션마다 워크스페이스/파일 브라우저 패널이 자동으로 열립니다. 언제든지 수동으로 닫을 수 있습니다.',
open_in_browser: '브라우저에서 열기',
settings_dropdown_conversation: '대화',
settings_dropdown_appearance: '외형',
settings_dropdown_preferences: '환경설정',
settings_dropdown_providers: 'Providers',
settings_dropdown_system: '시스템',
settings_tab_conversation: '대화',
settings_tab_appearance: '외형',
settings_tab_preferences: '환경설정',
settings_tab_system: '시스템',
settings_title: '설정',
settings_save_btn: '설정 저장',
settings_label_model: '기본 모델',
settings_desc_model: '새 대화에 사용됩니다. 기존 대화는 선택된 모델을 유지합니다.',
settings_label_send_key: '전송 키',
settings_label_theme: '테마',
settings_label_skin: '스킨',
settings_label_font_size: '글꼴 크기',
font_size_small: '작게',
font_size_default: '기본',
font_size_large: '크게',
settings_autosave_saving: '저장 중…',
settings_autosave_saved: '저장됨',
settings_autosave_failed: '저장 실패',
settings_autosave_retry: '다시 시도',
settings_label_language: '언어',
settings_label_token_usage: '토큰 사용량 표시',
settings_label_sidebar_density: '사이드바 밀도',
cmd_reasoning: 'Toggle thinking visibility (show/hide), set effort level, or check current status',
settings_label_external_sessions: '외부 세션 표시',
settings_label_sync_insights: 'Insights에 동기화',
settings_label_check_updates: '업데이트 확인',
settings_label_bot_name: 'Assistant 이름',
settings_label_password: '접근 비밀번호',
settings_saved: '설정 저장됨',
settings_save_failed: '설정 저장 실패: ',
settings_load_failed: '설정 로드 실패: ',
settings_saved_pw: '설정이 저장되었습니다 — 비밀번호 보호가 활성화되었으며 이 브라우저는 로그인 상태로 유지됩니다',
settings_saved_pw_updated: '설정이 저장되었습니다 — 비밀번호가 업데이트되었습니다',
// login page (used server-side via /api/i18n/login endpoint)
login_title: '로그인',
login_subtitle: '계속하려면 비밀번호를 입력하세요.',
login_placeholder: '비밀번호',
login_btn: '로그인',
login_invalid_pw: '비밀번호가 올바르지 않습니다',
login_conn_failed: '연결 실패',
// Sidebar & Tabs
tab_chat: '채팅',
tab_tasks: '작업',
tab_skills: '스킬',
tab_memory: '메모리',
tab_workspaces: '공간',
tab_profiles: 'Agent 프로필',
tab_kanban: 'Kanban',
kanban_board: 'Board',
kanban_visible_tasks: '{0} visible tasks',
kanban_search_tasks: 'Search tasks',
kanban_all_assignees: 'All assignees',
kanban_all_tenants: 'All tenants',
kanban_include_archived: 'Include archived',
kanban_no_matching_tasks: 'No matching tasks',
kanban_no_data: 'No Kanban data',
kanban_unavailable: 'Kanban unavailable',
kanban_read_only: 'Read-only view',
kanban_empty: 'Empty',
kanban_task: 'Task',
kanban_no_description: 'No description',
kanban_refresh: 'Refresh',
kanban_status_triage: 'Triage',
kanban_status_todo: 'Todo',
kanban_status_ready: 'Ready',
kanban_status_running: 'Running',
kanban_status_blocked: 'Blocked',
kanban_status_done: 'Done',
kanban_comments_count: 'Comments ({0})',
kanban_events_count: 'Events ({0})',
kanban_links: 'Links',
kanban_parents: 'Parents',
kanban_children: 'Children',
kanban_runs_count: 'Runs ({0})',
kanban_no_comments: 'No comments',
kanban_no_events: 'No events',
kanban_no_runs: 'No runs',
kanban_new_task: 'New task',
kanban_add_comment: 'Add comment',
kanban_only_mine: 'Only mine',
kanban_bulk_action: 'Bulk action',
kanban_nudge_dispatcher: 'Nudge dispatcher',
kanban_stats: 'Stats',
kanban_worker_log: 'Worker log',
kanban_block: 'Block',
kanban_unblock: 'Unblock',
kanban_back_to_board: 'Back to board',
kanban_lanes_by_profile: 'Lanes by profile',
kanban_new_board: 'New board…',
kanban_rename_board: 'Rename current board…',
kanban_archive_board: 'Archive current board…',
kanban_archive_board_confirm: 'Archive board "{name}"? Tasks remain on disk and the board can be restored from kanban/boards/_archived/.',
kanban_board_archived: 'Board archived',
kanban_board_name: 'Name',
kanban_board_slug: 'Slug (lowercase, hyphens)',
kanban_board_description: 'Description (optional)',
kanban_board_icon: 'Icon (emoji, optional)',
kanban_board_color: 'Color (optional)',
kanban_board_name_required: 'Name is required',
kanban_board_slug_required: 'Slug is required',
kanban_card_start: 'start',
kanban_card_complete: 'complete',
kanban_card_archive: 'archive',
kanban_unassigned: 'unassigned',
kanban_status_archived: 'Archived',
tab_todos: 'Todos',
tab_insights: '통계',
tab_settings: '설정',
new_conversation: '새 대화',
filter_conversations: '대화 필터…',
session_time_unknown: 'Unknown',
session_time_minutes_ago: (n) => `${n}m`,
session_time_hours_ago: (n) => `${n}h`,
session_time_days_ago: (n) => `${n}d`,
session_time_last_week: '1w',
session_time_bucket_today: 'Today',
session_time_bucket_yesterday: 'Yesterday',
session_time_bucket_this_week: 'This week',
session_time_bucket_last_week: 'Last week',
session_time_bucket_older: 'Older',
scheduled_jobs: '예약 작업',
new_job: '새 작업',
loading: '로딩 중...',
search_skills: 'Search skills...',
new_skill: 'New skill',
personal_memory: '개인 메모리',
current_task_list: '현재 작업 목록',
workspace_desc: '세션용 워크스페이스를 추가하고 전환합니다.',
session_meta_messages: (n) => `${n} msg${n === 1 ? '' : 's'}`,
session_meta_children: (n) => `${n} child${n === 1 ? '' : 'ren'}`,
new_profile: 'New profile',
transcript: '대화 기록',
download_transcript: 'Download as Markdown',
import: '가져오기',
// Settings detail
settings_label_sound: '알림음',
settings_desc_sound: 'Assistant 응답이 끝나면 소리를 재생합니다.',
settings_label_notifications: '브라우저 알림',
settings_desc_notifications: '앱이 백그라운드에 있을 때 응답이 완료되면 시스템 알림을 표시합니다.',
settings_desc_token_usage: '각 Assistant 응답 아래에 입력/출력 토큰 수를 표시합니다. /usage로도 전환할 수 있습니다.',
settings_sidebar_density_compact: '간결',
settings_sidebar_density_detailed: '자세히',
settings_desc_sidebar_density: '왼쪽 사이드바의 세션 목록에 표시할 메타데이터 양을 제어합니다.',
settings_label_auto_title_refresh: '적응형 제목 새로고침',
settings_auto_title_refresh_off: '꺼짐',
settings_auto_title_refresh_5: 'Every 5 exchanges',
settings_auto_title_refresh_10: 'Every 10 exchanges',
settings_auto_title_refresh_20: 'Every 20 exchanges',
settings_desc_auto_title_refresh: '최신 대화를 바탕으로 세션 제목을 자동으로 다시 생성해 대화가 진행되어도 제목을 관련 있게 유지합니다. LLM 제목 생성 모델 설정이 필요합니다.',
settings_desc_external_sessions: 'CLI, Telegram, Discord, Slack 및 기타 채널의 대화를 세션 목록에 표시합니다. 클릭하여 가져오고 계속하세요.',
settings_desc_sync_insights: 'WebUI 토큰 사용량을 state.db에 반영하여 hermes /insights에 브라우저 세션 데이터가 포함되도록 합니다. 기본값은 꺼짐입니다.',
settings_desc_check_updates: 'WebUI 또는 Agent의 새 버전이 있으면 배너를 표시합니다. 백그라운드에서 주기적으로 git fetch를 실행합니다.',
settings_desc_bot_name: 'UI 전체에 표시되는 Assistant 이름입니다. 기본값은 Hermes입니다.',
settings_desc_password: '새 비밀번호를 설정하거나 변경하려면 입력하세요. 현재 설정을 유지하려면 비워 두세요.',
password_placeholder: '새 비밀번호 입력…',
password_env_var_locked: '현재 HERMES_WEBUI_PASSWORD 환경 변수가 설정되어 있어 우선 적용됩니다. 변수를 해제하고 서버를 재시작해야 여기에서 비밀번호를 관리할 수 있습니다.',
password_env_var_locked_placeholder: '잠금: HERMES_WEBUI_PASSWORD 환경 변수가 설정되어 있습니다',
disable_auth: '인증 비활성화',
sign_out: '로그아웃',
// Providers panel
providers_tab_title: 'Providers',
providers_section_title: 'Providers',
providers_section_meta: 'Manage API keys for AI providers. Changes take effect immediately.',
providers_status_configured: 'API key configured',
providers_status_not_configured: 'No API key',
providers_status_oauth: 'OAuth',
providers_status_api_key: 'API key',
providers_status_not_configured_label: 'Not configured',
providers_oauth_hint: 'Authenticated via OAuth. No API key needed.',
providers_oauth_config_yaml_hint: 'Token configured via config.yaml. To update, edit the providers section in your config.yaml or run hermes auth.',
providers_oauth_not_configured_hint: 'Not authenticated. Run hermes auth in the terminal to configure this provider.',
providers_save: 'Save',
providers_remove: 'Remove',
providers_saving: 'Saving…',
providers_removing: 'Removing…',
providers_enter_key: 'Please enter an API key',
providers_empty: 'No configurable providers found.',
providers_key_updated: 'API key saved',
providers_key_removed: 'API key removed',
providers_key_placeholder_new: 'sk-...',
providers_key_placeholder_replace: 'Enter new key to replace…',
cancel: '취소',
create_job: 'Create job',
save_skill: 'Save skill',
editing: 'Editing',
// Empty state
empty_title: '무엇을 도와드릴까요?',
empty_subtitle: '질문하고, 명령을 실행하고, 파일을 탐색하거나 예약 작업을 관리하세요.',
suggest_files: '이 워크스페이스에는 어떤 파일이 있나요?',
suggest_schedule: '오늘 일정에는 무엇이 있나요?',
suggest_plan: '작은 프로젝트 계획을 도와주세요.',
// onboarding
onboarding_badge: '첫 실행',
onboarding_title: 'Hermes Web UI에 오신 것을 환영합니다',
onboarding_lead: '간단한 안내 설정으로 Hermes 설치를 확인하고, 워크스페이스와 모델을 선택하며, 필요하면 비밀번호로 앱을 보호합니다.',
onboarding_back: '뒤로',
onboarding_continue: '계속',
onboarding_skip: '설정 건너뛰기',
onboarding_skipped: 'Setup skipped — using existing config.',
onboarding_open: 'Open Hermes',
onboarding_step_system_title: 'System check',
onboarding_step_system_desc: 'Verify Hermes Agent and config visibility.',
onboarding_step_setup_title: 'Provider setup',
onboarding_step_setup_desc: 'Save the minimum Hermes provider config.',
onboarding_step_workspace_title: 'Workspace + model',
onboarding_step_workspace_desc: 'Pick defaults for new sessions and chat.',
onboarding_step_password_title: 'Optional password',
onboarding_step_password_desc: 'Protect the Web UI before sharing it.',
onboarding_step_finish_title: 'Finish',
onboarding_step_finish_desc: 'Review and enter the app.',
onboarding_notice_system_ready: 'Hermes Agent looks reachable from the Web UI.',
onboarding_notice_system_unavailable: 'Hermes Agent is not fully available yet. Bootstrap can install it, but provider setup may still require a terminal.',
onboarding_check_agent: 'Hermes Agent',
onboarding_check_agent_ready: 'Detected and importable',
onboarding_check_agent_missing: 'Missing or partially importable',
onboarding_check_password: 'Password',
onboarding_check_password_enabled: 'Already enabled',
onboarding_check_password_disabled: 'Not enabled yet',
onboarding_check_provider: 'Provider config',
onboarding_check_provider_ready: 'Ready to chat',
onboarding_check_provider_partial: 'Saved but incomplete',
onboarding_check_provider_pending: 'Needs verification',
onboarding_config_file: 'Config file:',
onboarding_env_file: '.env file:',
onboarding_unknown: 'Unknown',
onboarding_current_provider: 'Current setup:',
onboarding_missing_imports: 'Missing imports:',
onboarding_notice_setup_required: 'Choose a simple provider path here. Advanced OAuth flows still belong in the Hermes CLI for now.',
onboarding_notice_setup_already_ready: 'A working Hermes provider setup is already detected. You can keep it or replace it here.',
onboarding_oauth_provider_ready_title: 'Provider already authenticated',
onboarding_oauth_provider_ready_body: 'This instance is configured to use an OAuth provider (<strong>{provider}</strong>) that was set up via the Hermes CLI. No API key is needed here — click Continue to finish setup.',
onboarding_oauth_provider_not_ready_title: 'OAuth provider not yet authenticated',
onboarding_oauth_provider_not_ready_body: 'This instance is configured to use <strong>{provider}</strong>, which uses OAuth rather than an API key. Run <code>hermes auth</code> or <code>hermes model</code> in a terminal to authenticate, then reload the Web UI.',
onboarding_oauth_switch_hint: 'Or choose a different provider below to switch to an API-key setup:',
onboarding_notice_workspace: 'These values reuse the same settings APIs as the normal app.',
onboarding_workspace_label: 'Workspace',
onboarding_workspace_or_path: 'Or enter a workspace path',
onboarding_workspace_placeholder: '/home/you/workspace',
onboarding_provider_label: 'Setup mode',
onboarding_quick_setup_badge: 'quick setup',
provider_category_easy_start: 'Easy start',
provider_category_self_hosted: 'Open / self-hosted',
provider_category_specialized: 'Specialized',
onboarding_api_key_label: 'API key',
oauth_login_codex: 'Login with Codex (ChatGPT)', // TODO: translate
oauth_codex_step1: 'Step 1: Visit this URL and enter the code', // TODO: translate
oauth_codex_step2: 'Step 2: Enter this code on the page', // TODO: translate
oauth_codex_polling: 'Waiting for authorization...', // TODO: translate
oauth_codex_success: 'Codex OAuth login successful!', // TODO: translate
oauth_codex_error: 'OAuth login failed', // TODO: translate
oauth_codex_expired: 'Code expired, please try again', // TODO: translate
onboarding_api_key_placeholder: 'Leave blank to keep an existing saved key',
onboarding_api_key_label_optional: 'API key (optional)', // TODO: translate
onboarding_api_key_placeholder_optional: 'Leave blank for keyless servers', // TODO: translate
onboarding_api_key_help_keyless: 'Most LM Studio / Ollama / vLLM installs run keyless — leave this blank if your server doesn\'t require authentication. Use the Test connection button to verify.', // TODO: translate
onboarding_api_key_help_prefix: 'Saved as a secret in your Hermes .env file using',
onboarding_base_url_label: 'Base URL',
onboarding_base_url_placeholder: 'https://your-endpoint.example/v1',
onboarding_base_url_help: 'Use this for OpenAI-compatible routers, self-hosted servers, LiteLLM, Ollama, LM Studio, vLLM, or similar endpoints.',
onboarding_model_label: 'Default model',
onboarding_workspace_help: 'Pick the model Hermes should use for new chats after setup completes.',
onboarding_custom_model_placeholder: 'your-model-name',
onboarding_custom_model_help: 'For custom endpoints, enter the exact model ID your server expects.',
onboarding_notice_password_enabled: 'A password is already configured. Enter a new one only if you want to replace it.',
onboarding_notice_password_recommended: 'Optional but recommended if you will expose the UI beyond localhost.',
onboarding_password_label: 'Password (optional)',
onboarding_password_placeholder: 'Leave blank to skip',
onboarding_password_help: 'Passwords are stored through the existing settings API and hashed server-side.',
onboarding_notice_finish: 'You can reopen Settings later to change any of this.',
onboarding_not_set: 'Not set',
onboarding_password_will_enable: 'Will be enabled',
onboarding_password_will_replace: 'Will be replaced',
onboarding_password_keep_existing: 'Keep current password',
onboarding_password_remains_disabled: 'Will remain disabled',
onboarding_password_skipped: 'Skipped for now',
onboarding_finish_help: 'Finishing stores <code>onboarding_completed</code> in settings and drops you into the normal app.',
onboarding_error_choose_workspace: 'Choose a workspace before continuing.',
onboarding_error_choose_model: 'Choose a model before continuing.',
onboarding_error_provider_required: 'Choose a setup mode before continuing.',
onboarding_error_base_url_required: 'Base URL is required for custom endpoints.',
onboarding_probe_test_button: 'Test connection', // TODO: translate
onboarding_probe_probing: 'Testing connection…', // TODO: translate
onboarding_probe_ok: 'Connected. {n} model(s) available.', // TODO: translate
onboarding_probe_error_generic: 'Could not reach the configured base URL.', // TODO: translate
onboarding_probe_error_invalid_url: 'Base URL must start with http:// or https://.', // TODO: translate
onboarding_probe_error_dns: 'Could not resolve the host. Check the URL or use the host\'s IP address.', // TODO: translate
onboarding_probe_error_connect_refused: 'Connection refused — the server may not be running on that address. From inside Docker, try the host IP instead of localhost.', // TODO: translate
onboarding_probe_error_timeout: 'The endpoint did not respond in time. Check that the server is running and the URL is correct.', // TODO: translate
onboarding_probe_error_http_4xx: 'The endpoint returned a client error. Check authentication and the URL path (typically ends in /v1).', // TODO: translate
onboarding_probe_error_http_5xx: 'The endpoint returned a server error. Check the LM Studio / Ollama server logs.', // TODO: translate
onboarding_probe_error_parse: 'The endpoint did not return a model list in the expected shape. Verify the URL points to the OpenAI-compatible API root.', // TODO: translate
onboarding_probe_error_unreachable: 'Could not reach the configured base URL.', // TODO: translate
onboarding_error_probe_failed: 'Could not validate the configured base URL.', // TODO: translate
onboarding_error_workspace_required: 'Workspace is required.',
onboarding_error_model_required: 'Model is required.',
onboarding_complete: '설정 완료',
// panel/runtime i18n
error_prefix: 'Error: ',
not_available: 'N/A',
never: 'never',
add: 'Add',
add_failed: 'Add failed: ',
remove_failed: 'Remove failed: ',
switch_failed: 'Switch failed: ',
name_required: 'Name is required',
content_required: 'Content is required',
view: 'View',
dismiss: 'Dismiss',
disable: 'Disable',
cron_no_jobs: 'No scheduled jobs found.',
cron_status_off: 'off',
cron_status_paused: 'paused',
cron_status_error: 'error',
cron_status_active: 'active',
cron_status_running: '\uc2e4\ud589 \uc911\u2026',
cron_status_needs_attention: '주의 필요',
cron_attention_desc: '이 반복 작업에 다음 실행 시간이 없습니다. 스케줄러가 다음 실행을 계산하지 못했을 수 있습니다.',
cron_attention_croniter_hint: 'Gateway 런타임에 croniter 패키지가 없을 수 있습니다. cron 지원이 포함된 환경으로 Gateway를 재시작한 후 이 작업을 재개하세요.',
cron_attention_resume: '재개 및 재계산',
cron_jobs_project: '예약 작업',
cron_attention_run_once: '지금 한 번 실행',
cron_attention_copy_diagnostics: '진단 정보 복사',
cron_diagnostics_copied: '크론 진단 정보가 복사되었습니다',
cron_next: 'Next',
cron_last: 'Last',
cron_run_now: 'Run now',
cron_pause: 'Pause',
cron_resume: 'Resume',
cron_job_name_placeholder: 'Job name',
cron_schedule_placeholder: 'Schedule',
cron_prompt_placeholder: 'Prompt',
cron_last_output: 'Last output',
cron_all_runs: 'All runs',
cron_hide_runs: 'Hide runs',
cron_no_runs_yet: '(no runs yet)',
cron_schedule_required_example: 'Schedule is required (e.g. "0 9 * * *" or "every 1h")',
cron_schedule_required: 'Schedule is required',
cron_prompt_required: 'Prompt is required',
cron_job_created: 'Job created',
cron_duplicate: 'Duplicate',
cron_duplicated: 'Job duplicated (paused)',
cron_job_triggered: 'Job triggered',
cron_job_paused: 'Job paused',
cron_job_resumed: 'Job resumed',
cron_job_updated: 'Job updated',
cron_delete_confirm_title: 'Delete cron job',
cron_delete_confirm_message: 'This cannot be undone.',
cron_job_deleted: 'Job deleted',
cron_completion_status: (name, status) => `Cron "${name}" ${status}`,
status_failed: 'failed',
status_completed: 'completed',
todos_no_active: 'No active task list in this session.',
clear_conversation_title: 'Clear conversation',
clear_conversation_message: 'Clear all messages? This cannot be undone.',
clear_failed: 'Clear failed: ',
skills_no_match: 'No skills match.',
linked_files: 'Linked Files',
skill_load_failed: 'Could not load skill: ',
skill_file_load_failed: 'Could not load file: ',
skill_name_required: 'Skill name is required',
skill_updated: 'Skill updated',
skill_created: 'Skill created',
skill_deleted: 'Skill deleted',
skill_delete_confirm: 'Delete skill "{0}"?',
skills_empty_title: 'Select a skill',
skills_empty_sub: 'Pick a skill from the sidebar to view its contents, or create a new one.',
skills_edit: 'Edit',
skills_delete: 'Delete',
skills_back_to: 'Back to {0}',
tasks_empty_title: 'Select a scheduled job',
tasks_empty_sub: 'Pick a job from the sidebar to view its details and runs, or create a new one.',
workspaces_empty_title: 'Select a space',
workspaces_empty_sub: 'Pick a space from the sidebar to view its files and settings, or add a new one.',
profiles_empty_title: 'Select a profile',
profiles_empty_sub: 'Pick an agent profile from the sidebar to view and edit its settings, or create a new one.',
memory_notes_label: 'memory (notes)',
memory_saved: 'Memory saved',
my_notes: 'My Notes',
user_profile: 'User Profile',
no_notes_yet: 'No notes yet.',
no_profile_yet: 'No profile yet.',
workspace_choose_path: 'Choose workspace path',
workspace_choose_path_meta: 'Add a validated path and switch this conversation',
workspace_manage: 'Manage workspaces',
workspace_manage_meta: 'Open the Spaces panel',
workspace_use_title: 'Use in current session',
workspace_use: 'Use',
workspace_add_path_placeholder: 'Add workspace path (e.g. /home/user/my-project)',
workspace_paths_validated_hint: 'Paths are validated as existing directories before saving.',
workspace_drag_hint: '드래그하여 순서 변경',
workspace_reorder_failed: '순서 변경 실패',
workspace_added: 'Workspace added',
workspace_renamed: 'Workspace renamed',
workspace_remove_confirm_title: 'Remove workspace',
workspace_remove_confirm_message: (path) => `Remove "${path}"?`,
workspace_removed: 'Workspace removed',
workspace_switch_prompt_title: 'Switch workspace',
workspace_switch_prompt_message: 'Enter an absolute workspace path to add and switch this conversation to.',
workspace_switch_prompt_confirm: 'Switch',
workspace_switch_prompt_placeholder: '/Users/you/project',
workspace_not_added: 'Workspace was not added',
workspace_already_saved: 'Workspace already saved — choose it from the list',
workspace_busy_switch: 'Cannot switch workspace while agent is running',
discard_file_edits_title: 'Discard file edits?',
discard_file_edits_message: 'Switching workspaces will discard unsaved file edits in the preview.',
workspace_switched_to: (name) => `Switched to ${name}`,
profiles_no_profiles: 'No profiles found.',
profile_api_keys_configured: 'API keys configured',
profile_gateway_running: 'Gateway running',
profile_gateway_stopped: 'Gateway stopped',
profile_active: 'ACTIVE',
profile_no_configuration: 'No configuration',
profile_skill_count: (count) => `${count} skill${count === 1 ? '' : 's'}`,
profile_use: 'Use',
profile_switch_title: 'Switch to this profile',
profile_delete_title: 'Delete this profile',
profile_default_label: '(default)',
profile_name_placeholder: 'Profile name (lowercase, a-z 0-9 hyphens)',
profile_clone_label: 'Clone config from active profile',
profile_base_url_placeholder: 'Base URL (optional, e.g. http://localhost:11434)',
profile_api_key_placeholder: 'API key (optional)',
manage_profiles: 'Manage profiles',
profiles_load_failed: 'Failed to load profiles',
profiles_busy_switch: 'Cannot switch profiles while agent is running',
profile_switched_new_conversation: (name) => `Switched to profile: ${name} — new conversation started`,
profile_switched: (name) => `Switched to profile: ${name}`,
profile_name_rule: 'Lowercase letters, numbers, hyphens, underscores only',
profile_base_url_rule: 'Base URL must start with http:// or https://',
profile_created: (name) => `Profile created: ${name}`,
profile_delete_confirm_title: (name) => `Delete profile "${name}"?`,
profile_delete_confirm_message: 'All sessions, config, skills, and memory for this profile will be permanently deleted. This cannot be undone.',
profile_deleted: (name) => `Profile deleted: ${name}`,
active_conversation_none: 'No active conversation selected.',
active_conversation_meta: (title, count) => `${title} · ${count} message${count === 1 ? '' : 's'}`,
settings_unsaved_changes: 'You have unsaved changes.',
sign_out_failed: '로그아웃 실패: ',
disable_auth_confirm_title: '비밀번호 보호 비활성화',
disable_auth_confirm_message: 'Anyone will be able to access this instance.',
auth_disabled: '인증 비활성화 — 비밀번호 보호가 제거되었습니다',
disable_auth_failed: 'Failed to disable auth: ',
bg_error_single: (title) => `"${title}" has encountered an error`,
bg_error_multi: (count) => `${count} sessions have encountered an error`,
// skill form
skill_name: 'Name',
skill_category: 'Category',
skill_category_placeholder: 'Optional, e.g. devops',
skill_content: 'SKILL.md content',
skill_content_placeholder: 'YAML frontmatter + markdown body',
skill_rename_not_supported: 'Renaming a skill is not supported. Create a new skill and delete the old one to rename.',
skill_metadata: 'Metadata',
// cron form
cron_name_label: 'Name',
cron_name_placeholder: 'Optional',
cron_schedule_label: 'Schedule',
cron_schedule_hint: "Cron expression or shorthand like 'every 1h'.",
cron_prompt_label: 'Prompt',
cron_deliver_label: 'Deliver output to',
cron_deliver_local: 'Local (save output only)',
cron_skills_label: 'Skills',
cron_skills_placeholder: 'Add skills (optional)…',
cron_skills_edit_hint: 'Skill list is not editable after creation.',
// workspace form
workspace_name_label: 'Name',
workspace_name_placeholder: 'Optional friendly name',
workspace_path_label: 'Path',
workspace_path_required: 'Path is required',
workspace_path_readonly: 'Path cannot be changed. Rename only.',
workspace_new_title: 'New space',
// profile form
profile_name_label: 'Name',
profile_base_url_label: 'Base URL',
profile_api_key_label: 'API key',
cmd_yolo: 'YOLO 모드 전환',
cmd_branch: 'Fork this conversation into a new session',
cmd_branch_usage: '/branch [name] — fork conversation (optionally with a name)',
branch_forked: 'Forked into new session',
branch_failed: 'Fork failed: ',
fork_from_here: 'Fork from here',
forked_from: 'Forked from',
yolo_no_session: '활성 세션 없음',
yolo_enabled: '⚡ YOLO 모드 켜짐 — 이 세션에서 승인 건너뜀',
yolo_disabled: 'YOLO 모드 꺼짐',
yolo_pill_label: 'YOLO',
yolo_pill_title_active: 'YOLO 모드 활성 — 클릭하여 비활성화',
approval_skip_all: '⚡ 이 세션에서 모두 건너뛰기',
approval_skip_all_title: '이 세션의 모든 승인 요청 건너뛰기',
// composer action tooltips
composer_send: '메시지 보내기',
composer_queue: '메시지 대기열에 추가',
composer_interrupt: '중단하고 전송',
composer_steer: '현재 응답 유도',
composer_stop: '생성 중지',
composer_disabled_clarify: '위의 명확화 요청에 응답하세요',
composer_disabled_compression: '압축 완료 대기 중',
composer_disabled_empty: '메시지를 입력하세요',
composer_mobile_workspace: '워크스페이스',
composer_mobile_model: '모델',
composer_mobile_reasoning: '추론',
composer_mobile_context: '컨텍스트',
pdf_loading: 'PDF {0} 로드 중…',
pdf_too_large: 'PDF가 인라인 미리보기에 너무 큼',
pdf_no_pages: 'PDF 미리보기를 렌더링할 수 없음',
pdf_error: 'PDF 로드 실패',
pdf_download: 'PDF 다운로드',
html_loading: 'HTML 미리보기 로드 중…',
html_too_large: 'HTML이 인라인 미리보기에 너무 큼',
html_error: 'HTML 미리보기 로드 실패',
html_open_full: '전체 페이지 열기',
html_sandbox_label: 'HTML 미리보기',
media_audio_label: '오디오',
media_svg_label: '다이어그램',
media_video_label: '비디오',
csv_loading: 'CSV 로딩 중',
csv_too_large: 'CSV 파일이 너무 커서 인라인 렌더링할 수 없습니다',
csv_no_data: 'CSV 파일에 표시할 데이터가 부족합니다',
csv_error: 'CSV 파일을 로드하지 못했습니다',
csv_header_note: '첫 번째 행이 테이블 헤더로 표시됩니다',
excalidraw_loading: '다이어그램 로딩 중',
excalidraw_too_large: 'Excalidraw 파일이 너무 커서 인라인 렌더링할 수 없습니다',
excalidraw_invalid: '잘못된 Excalidraw 파일 형식',
excalidraw_error: 'Excalidraw 파일을 로드하지 못했습니다',
excalidraw_label: '다이어그램',
excalidraw_download: '다운로드',
excalidraw_empty: '빈 다이어그램',
excalidraw_render_error: '다이어그램 렌더링 실패',
excalidraw_simplified: '단순화된 SVG 미리보기 — Excalidraw 캔버스와 픽셀 동일하지 않음',
// TTS (#499)
tts_listen: '듣기',
tts_not_supported: '음성 합성을 사용할 수 없습니다',
settings_label_tts: '답변 음성 합성',
settings_desc_tts: '도움말 메시지에 스피커 버튼 표시',
settings_label_tts_auto_read: '답변 자동 읽기',
settings_desc_tts_auto_read: '도움말 답변을 자동으로 읽어줌',
// Composer voice-mode pref (#1488)
settings_label_voice_mode: 'Hands-free voice mode button', // TODO: translate
settings_desc_voice_mode: 'Show the voice-mode button (audio waveform) next to the dictation mic. Lets you speak naturally — Hermes auto-sends after a pause and reads replies aloud. Requires a browser that supports both speech recognition and TTS.', // TODO: translate
settings_label_tts_voice: '음성',
settings_desc_tts_voice: '음성 합성 음성 선택',
settings_label_tts_rate: '말 속도',
settings_label_tts_pitch: '말 톤',
checkpoint_date: 'Date', // TODO: translate
checkpoint_diff_files_changed: (n) => `${n} file${n === 1 ? '' : 's'} changed`, // TODO: translate
checkpoint_diff_no_changes: 'No differences found between this checkpoint and the current workspace.', // TODO: translate
checkpoint_diff_title: 'Changes in checkpoint', // TODO: translate
checkpoint_empty: 'No checkpoints found for this workspace.', // TODO: translate
checkpoint_error: 'Failed to load checkpoints', // TODO: translate
checkpoint_files: 'Files', // TODO: translate
checkpoint_loading: 'Loading checkpoints…', // TODO: translate
checkpoint_message: 'Message', // TODO: translate
checkpoint_restore: 'Restore', // TODO: translate
checkpoint_restore_confirm_message: (ckpt) => `Restore workspace to checkpoint "${ckpt}"? This will overwrite files with the saved versions. Files added after this checkpoint will not be deleted.`, // TODO: translate
checkpoint_restore_confirm_title: 'Restore checkpoint?', // TODO: translate
checkpoint_restored: 'Checkpoint restored', // TODO: translate
checkpoint_title: 'Checkpoints', // TODO: translate
checkpoint_view_diff: 'View diff', // TODO: translate
insights_activity_by_day: 'Activity by Day', // TODO: translate
insights_activity_by_hour: 'Activity by Hour', // TODO: translate
insights_cost: 'Estimated Cost', // TODO: translate
insights_footer: 'Showing data from the last {days} days', // TODO: translate
insights_input_tokens: 'Input', // TODO: translate
insights_messages: 'Messages', // TODO: translate
insights_models: 'Models', // TODO: translate
insights_no_cost: 'N/A', // TODO: translate
insights_output_tokens: 'Output', // TODO: translate
insights_peak_hour: 'Peak: {hour}', // TODO: translate
insights_sessions: 'Sessions', // TODO: translate
insights_title: 'Usage Analytics', // TODO: translate
insights_token_breakdown: 'Token Breakdown', // TODO: translate
insights_tokens: 'Tokens', // TODO: translate
insights_total: 'Total', // TODO: translate
settings_desc_api_redact: 'Self-hosted users can disable for transparency (not recommended for shared instances).', // TODO: translate
settings_label_api_redact: 'Redact sensitive data in API responses', // TODO: translate
voice_error: 'Voice not supported in this browser', // TODO: translate
voice_listening: 'Listening…', // TODO: translate
voice_mode_active: 'Voice mode on', // TODO: translate
voice_mode_off: 'Voice mode off', // TODO: translate
voice_speaking: 'Speaking…', // TODO: translate
voice_thinking: 'Thinking…', // TODO: translate
// Composer voice buttons (#1488)
voice_dictate: 'Dictate', // TODO: translate
voice_dictate_active: 'Stop dictation', // TODO: translate
voice_mode_toggle: 'Voice mode', // TODO: translate
voice_mode_toggle_active: 'Exit voice mode', // TODO: translate
subagent_children: 'Subagent sessions', // TODO: translate
},
};
// Active locale — defaults to English; overridden by loadLocale() at boot.
let _locale = LOCALES.en;
/**
* Resolve an incoming locale tag to a known LOCALES key.
* Supports exact keys, case-insensitive matches, and a few common aliases
* (e.g. zh-CN -> zh, zh-TW -> zh-Hant). Returns null when unresolved.
* @param {string} lang
* @returns {string|null}
*/
function resolveLocale(lang) {
if (typeof lang !== 'string') return null;
const raw = lang.trim();
if (!raw) return null;
if (LOCALES[raw]) return raw;
const lower = raw.toLowerCase().replace(/_/g, '-');
// Case-insensitive direct match first.
const direct = Object.keys(LOCALES).find((k) => k.toLowerCase() === lower);
if (direct) return direct;
// Common Chinese variants.
if (lower === 'zh' || lower.startsWith('zh-cn') || lower.startsWith('zh-sg') || lower.startsWith('zh-hans')) {
return LOCALES.zh ? 'zh' : null;
}
if (lower.startsWith('zh-tw') || lower.startsWith('zh-hk') || lower.startsWith('zh-mo') || lower.startsWith('zh-hant')) {
return LOCALES['zh-Hant'] ? 'zh-Hant' : null;
}
// Fallback to base language subtag (e.g. en-US -> en).
const base = lower.split('-')[0];
const baseMatch = Object.keys(LOCALES).find((k) => k.toLowerCase() === base);
return baseMatch || null;
}
/**
* Resolve locale with precedence:
* 1) primary (typically server setting)
* 2) fallback (typically localStorage)
* 3) English
* @param {string} primary
* @param {string} fallback
* @returns {string}
*/
function resolvePreferredLocale(primary, fallback) {
return resolveLocale(primary) || resolveLocale(fallback) || 'en';
}
/**
* Translate a key. Falls back to English if the key is missing in the active locale.
* Supports function values (for interpolated strings): call t('key', arg).
* @param {string} key
* @param {...*} args - forwarded to function-valued translations
* @returns {string}
*/
function t(key, ...args) {
const val = _locale[key] ?? LOCALES.en[key];
if (val === undefined) return key; // final fallback: return key itself
if (typeof val === 'function') return val(...args);
if (args.length) {
// Locale strings can use numbered placeholders like {0} and {1}.
return String(val).replace(/\{(\d+)\}/g, (match, idx) => (
Object.prototype.hasOwnProperty.call(args, idx) ? String(args[idx]) : match
));
}
return val;
}
/**
* Switch locale by language code (e.g. 'en', 'zh').
* Persists to localStorage and updates the <html lang> attribute.
* @param {string} lang
*/
function setLocale(lang) {
const resolved = resolveLocale(lang) || 'en';
_locale = LOCALES[resolved];
localStorage.setItem('hermes-lang', resolved);
document.documentElement.lang = _locale._speech || resolved;
}
/**
* Load locale from localStorage (called once at boot, before DOMContentLoaded).
* Server-persisted preference is applied later in loadSettingsPanel().
*/
function loadLocale() {
setLocale(resolvePreferredLocale(null, localStorage.getItem('hermes-lang')));
}
/**
* Re-stamp all [data-i18n] elements in the DOM with the current locale.
* Safe to call at any time — missing keys fall back to English.
* Call after setLocale() to make static HTML text update without a reload.
*/
function applyLocaleToDOM() {
document.querySelectorAll('[data-i18n]').forEach(el => {
const key = el.getAttribute('data-i18n');
const val = t(key);
if (val && val !== key) el.textContent = val;
});
document.querySelectorAll('[data-i18n-title]').forEach(el => {
const key = el.getAttribute('data-i18n-title');
const val = t(key);
if (val && val !== key) el.title = val;
});
document.querySelectorAll('[data-i18n-placeholder]').forEach(el => {
const key = el.getAttribute('data-i18n-placeholder');
const val = t(key);
if (val && val !== key) el.placeholder = val;
});
if (typeof syncAppTitlebar === 'function') syncAppTitlebar();
}
// Apply saved locale immediately so there's no flash of English on reload.
loadLocale();