Files
hermes-webui/static/i18n.js
T
bergeouss 85547612fe fix(logs): clipboard fallback + severity filter for Logs panel (#2081)
- replace navigator.clipboard.writeText with _copyText (has textarea fallback)
- add severity filter dropdown (All / Errors / Warnings+)
- add _severityForLine and _filteredLogsLines helpers
- add logsSeverityFilter HTML element + CSS class hooks
- add 5 new i18n keys across all 8 locales
- update test_logs_ui_static.py to match new implementation

Closes #2081
2026-05-11 15:40:49 +00:00

9558 lines
558 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: {
offline_title: 'Connection lost',
offline_browser_detail: 'Your browser reports that this device is offline.',
offline_network_detail: 'Hermes is unreachable from this browser right now.',
offline_autorefresh: 'I will refresh this page automatically when Hermes is reachable again.',
offline_check_now: 'Check now',
offline_checking: 'Checking…',
offline_stream_waiting: 'Connection lost. Waiting to refresh…',
_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: 'View 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.',
mcp_restart_hint: 'Server changes are read-only here for now. Edit config.yaml and restart Hermes for changes to take effect.',
mcp_toggle_followup: 'Enable/disable controls are intentionally deferred until MCP reload semantics are explicit.',
mcp_status_active: 'Active',
mcp_status_configured: 'Configured',
mcp_status_disabled: 'Disabled',
mcp_status_invalid_config: 'Invalid config',
mcp_status_unknown: 'Unknown',
mcp_tool_count: '{0} tools',
mcp_enabled_yes: 'Enabled',
mcp_enabled_no: 'Disabled',
mcp_tools_title: 'MCP Tools',
mcp_tools_desc: 'Search known tools across active MCP servers.',
mcp_tools_search_placeholder: 'Search tools by name, server, or description…',
mcp_tools_no_tools: 'No MCP tools are available from the active runtime inventory.',
mcp_tools_no_matches: 'No MCP tools match your search.',
mcp_tools_load_failed: 'Failed to load MCP tools.',
mcp_tools_schema_empty: 'No schema parameters.',
mcp_tools_runtime_note: 'Tool inventory only uses already-known active MCP runtime data; the WebUI does not start or probe 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',
session_jump_start: 'Start',
session_jump_start_label: 'Jump to beginning of session',
session_jump_end: 'End',
session_jump_end_label: 'Jump to end of session',
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',
workspace_new_worktree_conversation: 'New conversation in worktree',
workspace_new_worktree_conversation_meta: 'Create an isolated git worktree for this workspace.',
workspace_worktree_created: 'Worktree conversation created',
workspace_worktree_failed: 'Worktree creation failed: ',
session_worktree_badge: 'Worktree',
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_goal: 'Set or inspect a persistent goal',
goal_evaluating_progress: 'Evaluating goal progress…',
goal_working_toward: 'Working toward goal…',
goal_continuing_toast: 'Continuing toward goal…',
goal_status_none: 'No active goal. Set one with /goal <text>.',
goal_status_active: (turns, max_turns, goal) => `⊙ Goal (active, ${turns}/${max_turns} turns): ${goal}`,
goal_status_paused: (turns, max_turns, reason, goal) => `⏸ Goal (paused, ${turns}/${max_turns}${reason ? `, ${reason}` : ''}): ${goal}`,
goal_status_done: (turns, max_turns, goal) => `✓ Goal done (${turns}/${max_turns}): ${goal}`,
goal_set: (turns, goal) => `⊙ Goal set (${turns}-turn budget): ${goal}`,
goal_paused: (goal) => `⏸ Goal paused: ${goal}`,
goal_resumed: (goal) => `▶ Goal resumed: ${goal}`,
goal_cleared: 'Goal cleared.',
goal_no_goal: 'No active goal.',
goal_achieved: (reason) => `✓ Goal achieved: ${reason}`,
goal_paused_budget_exhausted: (turns, max_turns) => `⏸ Goal paused — ${turns}/${max_turns} turns used. Use /goal resume to keep going, or /goal clear to stop.`,
goal_continuing: (turns, max_turns, reason) => `↻ Continuing toward goal (${turns}/${max_turns}): ${reason}`,
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_provider:'Provider',
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_updated: 'Updated',
status_tokens: 'Tokens',
status_ephemeral: 'Ephemeral snapshot — not saved to transcript history.',
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.',
workspace_show_hidden_files: 'Show hidden files',
workspace_show_hidden_files_desc: 'Include .DS_Store, .git, node_modules, and other hidden / system files in the file tree.',
workspace_hidden_files_visible: 'hidden visible',
workspace_hidden_files_visible_title: 'Hidden files are visible — click for options',
workspace_options: 'Workspace options',
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: ',
copy_file_path: 'Copy file path',
path_copied: 'File path copied to clipboard',
path_copy_failed: 'Failed to copy path: ',
session_rename: 'Rename conversation',
session_rename_desc: 'Edit the title of this conversation',
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: ',
upload_too_large: (maxMb, fileMb) => `File is too large (${fileMb} MB). Maximum upload size is ${maxMb} MB.`,
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.',
settings_label_session_jump_buttons: 'Show session jump buttons',
settings_desc_session_jump_buttons: 'Show floating Start and End buttons while reading long session histories.',
settings_label_session_endless_scroll: 'Load older messages while scrolling up',
settings_desc_session_endless_scroll: 'When enabled, older messages load automatically as you scroll upward. When disabled, use the older-messages button.',
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_work_queue_hint: 'This is the Hermes Agent work queue. Create or triage a task, assign it, move it to Ready, then let the dispatcher claim it.',
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_title: 'Title',
kanban_description: 'Description',
kanban_description_placeholder: 'Optional — what needs to happen, acceptance criteria, links',
kanban_status: 'Status',
kanban_assignee: 'Assignee',
kanban_assignee_placeholder: 'Optional — leave blank for any worker',
kanban_tenant: 'Tenant',
kanban_tenant_placeholder: 'Optional — project or team slug',
kanban_priority: 'Priority',
kanban_priority_hint: 'Higher numbers run first. Default 0.',
kanban_title_required: 'Title is required.',
kanban_new_task: 'New task',
kanban_edit_task: 'Edit task',
kanban_status_original_hint: 'Actual status: {0}. This dialog only supports Triage/Todo/Ready edits.',
kanban_run_dispatcher: 'Run dispatcher',
kanban_run_dispatcher_confirm: 'This will claim Ready tasks on this board and spawn worker subprocesses (one per task, up to 8 per click). Continue?',
kanban_assignee_profiles_label: 'Hermes profiles',
kanban_assignee_other_label: 'Other (CLI lanes / removed profiles)',
kanban_assignee_unassigned: '— Unassigned (won\u2019t auto-run) —',
kanban_ready_needs_assignee: 'You picked Unassigned + Ready. The dispatcher will skip this task. Submit again to confirm, or pick a profile.',
kanban_dispatch_preview_prefix: 'Preview:',
kanban_dispatch_run_prefix: 'Dispatched:',
kanban_dispatch_spawned: 'spawned',
kanban_dispatch_promoted: 'promoted',
kanban_dispatch_reclaimed: 'reclaimed',
kanban_dispatch_skipped_unassigned: 'skipped (no assignee)',
kanban_dispatch_skipped_nonspawnable: 'skipped (unknown profile)',
kanban_dispatch_auto_blocked: 'auto-blocked',
kanban_dispatch_timed_out: 'timed out',
kanban_dispatch_crashed: 'crashed',
kanban_add_comment: 'Add comment',
kanban_only_mine: 'Only mine',
kanban_bulk_action: 'Bulk action',
kanban_nudge_dispatcher: 'Preview 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_complete: 'complete',
kanban_card_archive: 'archive',
kanban_unassigned: 'unassigned',
kanban_status_archived: 'Archived',
tab_todos: 'Todos',
tab_insights: 'Insights',
tab_dashboard: 'Hermes Dashboard',
dashboard_loopback_warning: 'Dashboard is loopback-only on the server. Either browse from the server itself or restart it with --host 0.0.0.0 (insecure).',
tab_logs: 'Logs',
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',
// Logs
logs_title: 'Logs',
logs_file: 'File',
logs_tail: 'Tail',
logs_auto_refresh: 'Auto-refresh (5s)',
logs_wrap: 'Wrap lines',
logs_copy_all: 'Copy all',
logs_empty: 'No log lines yet.',
logs_loading: 'Loading logs…',
logs_load_failed: 'Logs failed to load',
logs_status_idle: 'Choose a log file to view recent lines.',
logs_no_mtime: 'not written yet',
logs_truncated_hint: 'Showing the tail of a large log file; older bytes were skipped to keep memory bounded.',
logs_copied: 'Logs copied',
logs_severity: 'Severity',
logs_severity_all: 'All',
logs_severity_errors: 'Errors',
logs_severity_warnings: 'Warnings+',
logs_filter_active: 'shown (filter active)',
// 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_daily_tokens: 'Daily Tokens',
insights_model_name: 'Model',
insights_model_sessions: 'Sessions',
insights_model_tokens: 'Tokens',
insights_model_cost: 'Cost',
insights_model_share: 'Share',
insights_no_usage_data: 'No usage data yet',
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'}`,
session_meta_segments: (n) => `${n} segment${n === 1 ? '' : 's'}`,
session_lineage_segment_untitled: 'Untitled segment',
session_lineage_segment_open: 'Open lineage segment',
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',
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: "Use 'every 1h' or a cron expression for recurring jobs. Bare durations like '30m' run once.",
cron_schedule_once_warning: "Duration forms like '30m' run once and are removed after running. Use 'every 30m' to keep a recurring job.",
cron_prompt_label: 'Prompt',
cron_deliver_label: 'Deliver output to',
cron_deliver_local: 'Local (save output only)',
cron_profile_label: 'Profile',
cron_profile_server_default: 'server default',
cron_profile_server_default_hint: 'Uses the WebUI server default profile at run time. Existing jobs without a profile keep this legacy behavior.',
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: {
offline_title: '接続が切断されました',
offline_browser_detail: 'ブラウザはこのデバイスがオフラインだと報告しています。',
offline_network_detail: '現在、このブラウザからHermesに到達できません。',
offline_autorefresh: 'Hermesに再接続できたら、このページを自動的に更新します。',
offline_check_now: '今すぐ確認',
offline_checking: '確認中…',
offline_stream_waiting: '接続が切断されました。更新を待っています…',
_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サーバーの読み込みに失敗しました。',
mcp_restart_hint: 'ここでのサーバー変更は現状読み取り専用です。反映するには config.yaml を編集して Hermes を再起動してください。',
mcp_toggle_followup: '有効/無効の切り替えは、MCP のリロード仕様が明確になるまで意図的に保留しています。',
mcp_status_active: 'アクティブ',
mcp_status_configured: '設定済み',
mcp_status_disabled: '無効',
mcp_status_invalid_config: '不正な設定',
mcp_status_unknown: '不明',
mcp_tool_count: '{0} 個のツール',
mcp_enabled_yes: '有効',
mcp_enabled_no: '無効',
mcp_tools_title: 'MCP ツール',
mcp_tools_desc: 'アクティブな MCP サーバー全体から既知のツールを検索します。',
mcp_tools_search_placeholder: '名前、サーバー、説明でツールを検索…',
mcp_tools_no_tools: 'アクティブなランタイムに利用可能な MCP ツールがありません。',
mcp_tools_no_matches: '一致する MCP ツールはありません。',
mcp_tools_load_failed: 'MCP ツールの読み込みに失敗しました。',
mcp_tools_schema_empty: 'スキーマパラメータはありません。',
mcp_tools_runtime_note: 'ツール一覧は既知の MCP ランタイム情報のみを使用します。WebUI はサーバーの起動や探索を行いません。',
// 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: '↑ 上にスクロール、またはクリックして過去のメッセージを読み込む',
session_jump_start: '開始',
session_jump_start_label: 'セッションの先頭へ移動',
session_jump_end: '末尾',
session_jump_end_label: 'セッションの末尾へ移動',
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: 'ワークスペースが見つかりません',
workspace_new_worktree_conversation: 'worktree で新しい会話',
workspace_new_worktree_conversation_meta: 'このワークスペース用に隔離された git worktree を作成します。',
workspace_worktree_created: 'worktree 会話を作成しました',
workspace_worktree_failed: 'worktree の作成に失敗しました: ',
session_worktree_badge: 'Worktree',
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_goal: '永続ゴールを設定または確認',
goal_evaluating_progress: 'Evaluating goal progress…',
goal_working_toward: 'Working toward goal…',
goal_continuing_toast: 'Continuing toward goal…',
goal_status_none: 'No active goal. Set one with /goal <text>.',
goal_status_active: (turns, max_turns, goal) => `⊙ Goal (active, ${turns}/${max_turns} turns): ${goal}`,
goal_status_paused: (turns, max_turns, reason, goal) => `⏸ Goal (paused, ${turns}/${max_turns}${reason ? `, ${reason}` : ''}): ${goal}`,
goal_status_done: (turns, max_turns, goal) => `✓ Goal done (${turns}/${max_turns}): ${goal}`,
goal_set: (turns, goal) => `⊙ Goal set (${turns}-turn budget): ${goal}`,
goal_paused: (goal) => `⏸ Goal paused: ${goal}`,
goal_resumed: (goal) => `▶ Goal resumed: ${goal}`,
goal_cleared: 'Goal cleared.',
goal_no_goal: 'No active goal.',
goal_achieved: (reason) => `✓ Goal achieved: ${reason}`,
goal_paused_budget_exhausted: (turns, max_turns) => `⏸ Goal paused — ${turns}/${max_turns} turns used. Use /goal resume to keep going, or /goal clear to stop.`,
goal_continuing: (turns, max_turns, reason) => `↻ Continuing toward goal (${turns}/${max_turns}): ${reason}`,
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_provider:'プロバイダー',
status_workspace:'ワークスペース',
status_personality:'パーソナリティ',
status_messages:'メッセージ',
status_agent_running:'エージェント実行中',
status_profile: 'プロファイル',
status_hermes_home: 'Hermes ホーム',
status_started: '開始',
status_tokens: 'トークン',
status_updated: '更新',
status_ephemeral: '一時的なスナップショット — 履歴には保存されません。',
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: 'このワークスペースは空です。',
workspace_show_hidden_files: '隠しファイルを表示',
workspace_show_hidden_files_desc: 'Include .DS_Store, .git, node_modules, and other hidden / system files in the file tree.',
workspace_hidden_files_visible: 'hidden visible',
workspace_hidden_files_visible_title: 'Hidden files are visible — click for options',
workspace_options: 'Workspace options',
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: '表示に失敗しました: ',
copy_file_path: 'ファイルパスをコピー',
path_copied: 'ファイルパスをクリップボードにコピーしました',
path_copy_failed: 'パスのコピーに失敗しました: ',
session_rename: '会話の名前を変更',
session_rename_desc: 'この会話のタイトルを編集',
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: 'アップロード失敗: ',
upload_too_large: (maxMb, fileMb) => `ファイルが大きすぎます (${fileMb} MB)。最大アップロードサイズは ${maxMb} MB です。`,
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: '応答を停止',
session_stop_response_desc: 'この会話の実行中の応答をキャンセルします',
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: '有効にすると、新しいセッションごとにワークスペース/ファイルブラウザパネルが自動で開きます。手動でいつでも閉じられます。',
settings_label_session_jump_buttons: 'セッションジャンプボタンを表示',
settings_desc_session_jump_buttons: '長いセッション履歴を読むときに、浮動表示の「開始」と「末尾」ボタンを表示します。',
settings_label_session_endless_scroll: '上スクロールで古いメッセージを読み込む',
settings_desc_session_endless_scroll: '有効にすると、上にスクロールしたとき古いメッセージを自動で読み込みます。無効の場合は古いメッセージボタンを使います。',
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_board: 'ボード',
kanban_visible_tasks: '表示中のタスク: {0}',
kanban_search_tasks: 'タスクを検索',
kanban_all_assignees: '担当者: すべて',
kanban_all_tenants: 'テナント: すべて',
kanban_include_archived: 'アーカイブを含める',
kanban_no_matching_tasks: '一致するタスクがありません',
kanban_no_data: 'カンバンデータがありません',
kanban_work_queue_hint: 'これは Hermes Agent のワークキューです。タスクを作成またはトリアージし、担当者を割り当て、Ready に移動すると、ディスパッチャーがそれをクレームします。',
kanban_unavailable: 'カンバンを利用できません',
kanban_read_only: '読み取り専用',
kanban_empty: '空',
kanban_task: 'タスク',
kanban_no_description: '説明なし',
kanban_refresh: '更新',
kanban_status_triage: 'トリアージ',
kanban_status_todo: 'ToDo',
kanban_status_ready: '準備完了',
kanban_status_running: '実行中',
kanban_status_blocked: 'ブロック中',
kanban_status_done: '完了',
kanban_status_original_hint: 'Actual status: {0}. This dialog only supports Triage/Todo/Ready edits.',
kanban_comments_count: 'コメント ({0})',
kanban_events_count: 'イベント ({0})',
kanban_links: 'リンク',
kanban_parents: '親',
kanban_children: '子',
kanban_runs_count: '実行 ({0})',
kanban_no_comments: 'コメントなし',
kanban_no_events: 'イベントなし',
kanban_no_runs: '実行なし',
kanban_title: 'タイトル',
kanban_description: '説明',
kanban_description_placeholder: '任意 — 何をすべきか、受け入れ基準、リンク',
kanban_status: 'ステータス',
kanban_assignee: '担当者',
kanban_assignee_placeholder: '任意 — 空欄で任意のワーカーに',
kanban_tenant: 'テナント',
kanban_tenant_placeholder: '任意 — プロジェクトまたはチームのスラッグ',
kanban_priority: '優先度',
kanban_priority_hint: '値が大きいほど優先されます。既定値は 0。',
kanban_title_required: 'タイトルは必須です。',
kanban_edit_task: 'タスクを編集',
kanban_run_dispatcher: 'ディスパッチャーを実行',
kanban_run_dispatcher_confirm: 'このボードの「Ready」タスクを取得し、ワーカーサブプロセスを起動します(クリック1回につき最大8件)。続行しますか?',
kanban_assignee_profiles_label: 'Hermes プロファイル',
kanban_assignee_other_label: 'その他 (CLI レーン / 削除されたプロファイル)',
kanban_assignee_unassigned: '— 未割当 (自動実行されません) —',
kanban_ready_needs_assignee: '担当者「未割当」+「Ready」を選択しました。ディスパッチャーはこのタスクをスキップします。続行するにはもう一度送信するか、プロファイルを選んでください。',
kanban_dispatch_preview_prefix: 'プレビュー:',
kanban_dispatch_run_prefix: '実行:',
kanban_dispatch_spawned: '起動',
kanban_dispatch_promoted: '昇格',
kanban_dispatch_reclaimed: '再取得',
kanban_dispatch_skipped_unassigned: 'スキップ (担当者なし)',
kanban_dispatch_skipped_nonspawnable: 'スキップ (不明なプロファイル)',
kanban_dispatch_auto_blocked: '自動ブロック',
kanban_dispatch_timed_out: 'タイムアウト',
kanban_dispatch_crashed: 'クラッシュ',
kanban_new_task: '新規タスク',
kanban_add_comment: 'コメント追加',
kanban_only_mine: '自分のみ',
kanban_bulk_action: '一括操作',
kanban_nudge_dispatcher: 'ディスパッチャープレビュー',
kanban_stats: '統計',
kanban_worker_log: 'ワーカーログ',
kanban_block: 'ブロック',
kanban_unblock: 'ブロック解除',
kanban_back_to_board: 'ボードに戻る',
kanban_lanes_by_profile: 'プロファイル別レーン',
kanban_new_board: '新規ボード…',
kanban_rename_board: '現在のボード名を変更…',
kanban_archive_board: '現在のボードをアーカイブ…',
kanban_archive_board_confirm: 'ボード "{name}" をアーカイブしますか? タスクはディスク上に残り、kanban/boards/_archived/ から復元できます。',
kanban_board_archived: 'ボードをアーカイブしました',
kanban_board_name: '名前',
kanban_board_slug: 'スラッグ (小文字・ハイフン)',
kanban_board_description: '説明 (任意)',
kanban_board_icon: 'アイコン (絵文字、任意)',
kanban_board_color: '色 (任意)',
kanban_board_name_required: '名前は必須です',
kanban_board_slug_required: 'スラッグは必須です',
kanban_card_complete: '完了',
kanban_card_archive: 'アーカイブ',
kanban_unassigned: '未割り当て',
kanban_status_archived: 'アーカイブ済み',
tab_todos: 'ToDo',
tab_insights: 'インサイト',
tab_dashboard: 'Hermes ダッシュボード',
dashboard_loopback_warning: 'ダッシュボードはサーバー上のループバック専用です。サーバー上で閲覧するか、--host 0.0.0.0(安全ではありません)で再起動してください。',
tab_logs: 'ログ',
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: '現在のタスクリスト',
// Logs
logs_title: 'ログ',
logs_file: 'ファイル',
logs_tail: '末尾',
logs_auto_refresh: '自動更新 (5秒)',
logs_wrap: '行を折り返す',
logs_copy_all: 'すべてコピー',
logs_empty: 'ログはまだありません。',
logs_loading: 'ログを読み込み中…',
logs_load_failed: 'ログの読み込みに失敗しました',
logs_status_idle: 'ログファイルを選択すると最近の行を表示します。',
logs_no_mtime: '未書き込み',
logs_truncated_hint: '大きなログファイルの末尾を表示しています。メモリ使用量を抑えるため、古いデータは省略されました。',
logs_copied: 'ログをコピーしました',
logs_severity: 'Severity', // TODO: translate
logs_severity_all: 'All', // TODO: translate
logs_severity_errors: 'Errors', // TODO: translate
logs_severity_warnings: 'Warnings+', // TODO: translate
logs_filter_active: 'shown (filter active)', // TODO: translate
// 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_daily_tokens: '日別トークン',
insights_model_name: 'モデル',
insights_model_sessions: 'セッション',
insights_model_tokens: 'トークン',
insights_model_cost: 'コスト',
insights_model_share: 'シェア',
insights_no_usage_data: '使用データはまだありません',
insights_footer: '直近 {days} 日間のデータを表示',
workspace_desc: 'セッション用のワークスペースを追加・切り替えします。',
session_meta_messages: (n) => `${n}`,
session_meta_children: (n) => `${n}`,
session_meta_segments: (n) => `${n} セグメント`,
session_lineage_segment_untitled: '無題のセグメント',
session_lineage_segment_open: '系譜セグメントを開く',
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キー (任意)',
onboarding_api_key_placeholder_optional: 'キー不要のサーバーの場合は空欄にしてください',
onboarding_api_key_help_keyless: 'LM Studio / Ollama / vLLM の多くはキーなしで動作します。認証が不要なサーバーの場合は空欄にしてください。『接続テスト』で確認できます。',
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: '接続テスト',
onboarding_probe_probing: '接続をテスト中…',
onboarding_probe_ok: '接続成功。{n} 個のモデルが利用可能です。',
onboarding_probe_error_generic: '設定されたベース URL に到達できません。',
onboarding_probe_error_invalid_url: 'ベース URL は http:// または https:// で始まる必要があります。',
onboarding_probe_error_dns: 'ホストを名前解決できませんでした。URL を確認するか、ホストの IP アドレスを使用してください。',
onboarding_probe_error_connect_refused: '接続が拒否されました。サーバーが起動していない可能性があります。Docker 内からは localhost ではなくホスト IP を試してください。',
onboarding_probe_error_timeout: '時間内に応答がありません。サーバーが起動しているか、URL が正しいか確認してください。',
onboarding_probe_error_http_4xx: 'クライアントエラーが返されました。認証設定と URL パス (通常は /v1) を確認してください。',
onboarding_probe_error_http_5xx: 'サーバーエラーが返されました。LM Studio / Ollama のログを確認してください。',
onboarding_probe_error_parse: 'モデル一覧が期待する形式で返されませんでした。URL が OpenAI 互換 API のルートを指しているか確認してください。',
onboarding_probe_error_unreachable: '設定されたベース URL に到達できません。',
onboarding_error_probe_failed: 'ベース URL を検証できませんでした。',
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: 'プロファイルの読み込みに失敗しました',
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: "繰り返し実行には 'every 1h' または Cron 式を使います。'30m' のような期間だけの指定は 1 回だけ実行されます。",
cron_schedule_once_warning: "'30m' のような期間指定は 1 回だけ実行され、実行後に削除されます。繰り返すには 'every 30m' を使ってください。",
cron_prompt_label: 'プロンプト',
cron_deliver_label: '出力先',
cron_deliver_local: 'ローカル (出力を保存のみ)',
cron_profile_label: 'プロフィール',
cron_profile_server_default: 'サーバーデフォルト',
cron_profile_server_default_hint: '実行時に WebUI サーバーのデフォルトプロフィールを使用します。プロフィールのない既存ジョブはこの従来の動作を維持します。',
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: {
offline_title: 'Соединение потеряно',
offline_browser_detail: 'Браузер сообщает, что это устройство офлайн.',
offline_network_detail: 'Hermes сейчас недоступен из этого браузера.',
offline_autorefresh: 'Я автоматически обновлю страницу, когда Hermes снова станет доступен.',
offline_check_now: 'Проверить сейчас',
offline_checking: 'Проверка…',
offline_stream_waiting: 'Соединение потеряно. Ожидаю обновления…',
_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 伺服器失敗。',
mcp_restart_hint: 'Server changes are read-only here for now. Edit config.yaml and restart Hermes for changes to take effect.',
mcp_toggle_followup: 'Enable/disable controls are intentionally deferred until MCP reload semantics are explicit.',
mcp_status_active: 'Active',
mcp_status_configured: 'Configured',
mcp_status_disabled: 'Disabled',
mcp_status_invalid_config: 'Invalid config',
mcp_status_unknown: 'Unknown',
mcp_tool_count: '{0} tools',
mcp_enabled_yes: 'Enabled',
mcp_enabled_no: 'Disabled',
mcp_tools_title: 'MCP Tools',
mcp_tools_desc: 'Search known tools across active MCP servers.',
mcp_tools_search_placeholder: 'Search tools by name, server, or description…',
mcp_tools_no_tools: 'No MCP tools are available from the active runtime inventory.',
mcp_tools_no_matches: 'No MCP tools match your search.',
mcp_tools_load_failed: 'Failed to load MCP tools.',
mcp_tools_schema_empty: 'No schema parameters.',
mcp_tools_runtime_note: 'Tool inventory only uses already-known active MCP runtime data; the WebUI does not start or probe servers.',
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: '↑ Прокрутите вверх или нажмите, чтобы загрузить ранние сообщения',
session_jump_start: 'Начало',
session_jump_start_label: 'Перейти к началу сессии',
session_jump_end: 'Конец',
session_jump_end_label: 'Перейти к концу сессии',
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_goal: 'Задать или проверить постоянную цель',
goal_evaluating_progress: 'Evaluating goal progress…',
goal_working_toward: 'Working toward goal…',
goal_continuing_toast: 'Continuing toward goal…',
goal_status_none: 'No active goal. Set one with /goal <text>.',
goal_status_active: (turns, max_turns, goal) => `⊙ Goal (active, ${turns}/${max_turns} turns): ${goal}`,
goal_status_paused: (turns, max_turns, reason, goal) => `⏸ Goal (paused, ${turns}/${max_turns}${reason ? `, ${reason}` : ''}): ${goal}`,
goal_status_done: (turns, max_turns, goal) => `✓ Goal done (${turns}/${max_turns}): ${goal}`,
goal_set: (turns, goal) => `⊙ Goal set (${turns}-turn budget): ${goal}`,
goal_paused: (goal) => `⏸ Goal paused: ${goal}`,
goal_resumed: (goal) => `▶ Goal resumed: ${goal}`,
goal_cleared: 'Goal cleared.',
goal_no_goal: 'No active goal.',
goal_achieved: (reason) => `✓ Goal achieved: ${reason}`,
goal_paused_budget_exhausted: (turns, max_turns) => `⏸ Goal paused — ${turns}/${max_turns} turns used. Use /goal resume to keep going, or /goal clear to stop.`,
goal_continuing: (turns, max_turns, reason) => `↻ Continuing toward goal (${turns}/${max_turns}): ${reason}`,
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: 'Рабочие пространства не найдены',
workspace_new_worktree_conversation: 'Новый разговор в worktree',
workspace_new_worktree_conversation_meta: 'Создать изолированный git worktree для этого рабочего пространства.',
workspace_worktree_created: 'Разговор в worktree создан',
workspace_worktree_failed: 'Не удалось создать worktree: ',
session_worktree_badge: 'Worktree',
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_show_hidden_files: 'Показывать скрытые файлы',
workspace_show_hidden_files_desc: 'Include .DS_Store, .git, node_modules, and other hidden / system files in the file tree.',
workspace_hidden_files_visible: 'hidden visible',
workspace_hidden_files_visible_title: 'Hidden files are visible — click for options',
workspace_options: 'Workspace options',
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: 'Не удалось открыть: ',
copy_file_path: 'Копировать путь к файлу',
path_copied: 'Путь к файлу скопирован в буфер обмена',
path_copy_failed: 'Не удалось скопировать путь: ',
session_rename: 'Переименовать беседу',
session_rename_desc: 'Изменить название этой беседы',
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: 'Не удалось загрузить: ',
upload_too_large: (maxMb, fileMb) => `Файл слишком большой (${fileMb} МБ). Максимальный размер загрузки: ${maxMb} МБ.`,
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_work_queue_hint: 'This is the Hermes Agent work queue. Create or triage a task, assign it, move it to Ready, then let the dispatcher claim it.',
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_status_original_hint: 'Actual status: {0}. This dialog only supports Triage/Todo/Ready edits.',
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_title: 'Заголовок',
kanban_description: 'Описание',
kanban_description_placeholder: 'Необязательно — что нужно сделать, критерии приёмки, ссылки',
kanban_status: 'Статус',
kanban_assignee: 'Исполнитель',
kanban_assignee_placeholder: 'Необязательно — оставьте пустым для любого исполнителя',
kanban_tenant: 'Арендатор',
kanban_tenant_placeholder: 'Необязательно — слаг проекта или команды',
kanban_priority: 'Приоритет',
kanban_priority_hint: 'Большие числа выполняются первыми. По умолчанию 0.',
kanban_title_required: 'Заголовок обязателен.',
kanban_edit_task: 'Редактировать задачу',
kanban_run_dispatcher: 'Запустить диспетчер',
kanban_run_dispatcher_confirm: 'Это захватит задачи в состоянии Ready на этой доске и запустит подпроцессы-исполнители (по одному на задачу, до 8 за нажатие). Продолжить?',
kanban_assignee_profiles_label: 'Профили Hermes',
kanban_assignee_other_label: 'Другие (CLI каналы / удалённые профили)',
kanban_assignee_unassigned: '— Не назначено (не запустится автоматически) —',
kanban_ready_needs_assignee: 'Вы выбрали «Не назначено» + «Ready». Диспетчер пропустит эту задачу. Отправьте ещё раз для подтверждения или выберите профиль.',
kanban_dispatch_preview_prefix: 'Предпросмотр:',
kanban_dispatch_run_prefix: 'Отправлено:',
kanban_dispatch_spawned: 'запущено',
kanban_dispatch_promoted: 'повышено',
kanban_dispatch_reclaimed: 'возвращено',
kanban_dispatch_skipped_unassigned: 'пропущено (без исполнителя)',
kanban_dispatch_skipped_nonspawnable: 'пропущено (неизвестный профиль)',
kanban_dispatch_auto_blocked: 'автоблок',
kanban_dispatch_timed_out: 'таймаут',
kanban_dispatch_crashed: 'падение',
kanban_new_task: 'New task',
kanban_add_comment: 'Add comment',
kanban_only_mine: 'Only mine',
kanban_bulk_action: 'Bulk action',
kanban_nudge_dispatcher: 'Preview 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_complete: 'complete',
kanban_card_archive: 'archive',
kanban_unassigned: 'unassigned',
kanban_status_archived: 'Archived',
tab_todos: 'Список дел',
tab_insights: 'Аналитика',
tab_dashboard: 'Панель Hermes',
dashboard_loopback_warning: 'Панель доступна только через loopback на сервере. Откройте её с самого сервера или перезапустите с --host 0.0.0.0 (небезопасно).',
tab_logs: 'Logs',
tab_settings: 'Настройки',
logs_title: 'Logs', // TODO: translate
logs_file: 'File', // TODO: translate
logs_tail: 'Tail', // TODO: translate
logs_auto_refresh: 'Auto-refresh (5s)', // TODO: translate
logs_wrap: 'Wrap lines', // TODO: translate
logs_copy_all: 'Copy all', // TODO: translate
logs_empty: 'No log lines yet.', // TODO: translate
logs_loading: 'Loading logs…', // TODO: translate
logs_load_failed: 'Logs failed to load', // TODO: translate
logs_status_idle: 'Choose a log file to view recent lines.', // TODO: translate
logs_no_mtime: 'not written yet', // TODO: translate
logs_truncated_hint: 'Showing the tail of a large log file; older bytes were skipped to keep memory bounded.', // TODO: translate
logs_copied: 'Logs copied', // TODO: translate
logs_severity: 'Severity', // TODO: translate
logs_severity_all: 'All', // TODO: translate
logs_severity_errors: 'Errors', // TODO: translate
logs_severity_warnings: 'Warnings+', // TODO: translate
logs_filter_active: 'shown (filter active)', // TODO: translate
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 ? 'дочерн.' : 'дочерн.'}`,
session_meta_segments: (n) => `${n} сегм.`,
session_lineage_segment_untitled: 'Сегмент без названия',
session_lineage_segment_open: 'Открыть сегмент цепочки',
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: 'Не удалось загрузить профили',
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: "Для повторяющихся заданий используйте 'every 1h' или cron-выражение. Простые интервалы вроде '30m' выполняются один раз.",
cron_schedule_once_warning: "Интервалы вроде '30m' выполняются один раз и удаляются после запуска. Используйте 'every 30m' для повторяющегося задания.",
cron_prompt_label: 'Запрос',
cron_deliver_label: 'Доставлять вывод',
cron_deliver_local: 'Локально (только сохранение)',
cron_profile_label: 'Профиль',
cron_profile_server_default: 'по умолчанию сервера',
cron_profile_server_default_hint: 'Использует профиль WebUI-сервера по умолчанию во время запуска. Существующие задания без профиля сохраняют это поведение.',
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: 'При включении панель файлов будет открываться автоматически в каждой новой сессии.',
settings_label_session_jump_buttons: 'Показывать кнопки перехода по сессии',
settings_desc_session_jump_buttons: 'Показывать плавающие кнопки «Начало» и «Конец» при чтении длинных историй сессий.',
settings_label_session_endless_scroll: 'Загружать старые сообщения при прокрутке вверх',
settings_desc_session_endless_scroll: 'Если включено, старые сообщения загружаются автоматически при прокрутке вверх. Если выключено, используйте кнопку загрузки старых сообщений.',
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_updated: 'Updated',
status_ephemeral: 'Ephemeral snapshot — not saved to transcript history.',
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_daily_tokens: 'Daily Tokens',
insights_model_name: 'Model',
insights_model_sessions: 'Sessions',
insights_model_tokens: 'Tokens',
insights_model_cost: 'Cost',
insights_model_share: 'Share',
insights_no_usage_data: 'No usage data yet',
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: {
offline_title: 'Conexión perdida',
offline_browser_detail: 'Tu navegador indica que este dispositivo está sin conexión.',
offline_network_detail: 'Hermes no está disponible desde este navegador ahora mismo.',
offline_autorefresh: 'Actualizaré esta página automáticamente cuando Hermes vuelva a estar disponible.',
offline_check_now: 'Comprobar ahora',
offline_checking: 'Comprobando…',
offline_stream_waiting: 'Conexión perdida. Esperando para actualizar…',
_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 服务器失败。',
mcp_restart_hint: 'Server changes are read-only here for now. Edit config.yaml and restart Hermes for changes to take effect.',
mcp_toggle_followup: 'Enable/disable controls are intentionally deferred until MCP reload semantics are explicit.',
mcp_status_active: 'Active',
mcp_status_configured: 'Configured',
mcp_status_disabled: 'Disabled',
mcp_status_invalid_config: 'Invalid config',
mcp_status_unknown: 'Unknown',
mcp_tool_count: '{0} tools',
mcp_enabled_yes: 'Enabled',
mcp_enabled_no: 'Disabled',
mcp_tools_title: 'MCP Tools',
mcp_tools_desc: 'Search known tools across active MCP servers.',
mcp_tools_search_placeholder: 'Search tools by name, server, or description…',
mcp_tools_no_tools: 'No MCP tools are available from the active runtime inventory.',
mcp_tools_no_matches: 'No MCP tools match your search.',
mcp_tools_load_failed: 'Failed to load MCP tools.',
mcp_tools_schema_empty: 'No schema parameters.',
mcp_tools_runtime_note: 'Tool inventory only uses already-known active MCP runtime data; the WebUI does not start or probe servers.',
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',
session_jump_start: 'Inicio',
session_jump_start_label: 'Saltar al inicio de la sesión',
session_jump_end: 'Fin',
session_jump_end_label: 'Saltar al final de la sesión',
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',
workspace_new_worktree_conversation: 'Nueva conversación en worktree',
workspace_new_worktree_conversation_meta: 'Crear un git worktree aislado para este espacio de trabajo.',
workspace_worktree_created: 'Conversación en worktree creada',
workspace_worktree_failed: 'Error al crear worktree: ',
session_worktree_badge: 'Worktree',
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_goal: 'Definir o consultar un objetivo persistente',
goal_evaluating_progress: 'Evaluating goal progress…',
goal_working_toward: 'Working toward goal…',
goal_continuing_toast: 'Continuing toward goal…',
goal_status_none: 'No active goal. Set one with /goal <text>.',
goal_status_active: (turns, max_turns, goal) => `⊙ Goal (active, ${turns}/${max_turns} turns): ${goal}`,
goal_status_paused: (turns, max_turns, reason, goal) => `⏸ Goal (paused, ${turns}/${max_turns}${reason ? `, ${reason}` : ''}): ${goal}`,
goal_status_done: (turns, max_turns, goal) => `✓ Goal done (${turns}/${max_turns}): ${goal}`,
goal_set: (turns, goal) => `⊙ Goal set (${turns}-turn budget): ${goal}`,
goal_paused: (goal) => `⏸ Goal paused: ${goal}`,
goal_resumed: (goal) => `▶ Goal resumed: ${goal}`,
goal_cleared: 'Goal cleared.',
goal_no_goal: 'No active goal.',
goal_achieved: (reason) => `✓ Goal achieved: ${reason}`,
goal_paused_budget_exhausted: (turns, max_turns) => `⏸ Goal paused — ${turns}/${max_turns} turns used. Use /goal resume to keep going, or /goal clear to stop.`,
goal_continuing: (turns, max_turns, reason) => `↻ Continuing toward goal (${turns}/${max_turns}): ${reason}`,
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_show_hidden_files: 'Mostrar archivos ocultos',
workspace_show_hidden_files_desc: 'Include .DS_Store, .git, node_modules, and other hidden / system files in the file tree.',
workspace_hidden_files_visible: 'hidden visible',
workspace_hidden_files_visible_title: 'Hidden files are visible — click for options',
workspace_options: 'Workspace options',
// 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: ',
copy_file_path: 'Copiar ruta del archivo',
path_copied: 'Ruta del archivo copiada al portapapeles',
path_copy_failed: 'Error al copiar la ruta: ',
session_rename: 'Renombrar conversación',
session_rename_desc: 'Editar el título de esta conversación',
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: ',
upload_too_large: (maxMb, fileMb) => `El archivo es demasiado grande (${fileMb} MB). El tamaño máximo de subida es ${maxMb} MB.`,
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_work_queue_hint: 'This is the Hermes Agent work queue. Create or triage a task, assign it, move it to Ready, then let the dispatcher claim it.',
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_status_original_hint: 'Actual status: {0}. This dialog only supports Triage/Todo/Ready edits.',
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_title: 'Título',
kanban_description: 'Descripción',
kanban_description_placeholder: 'Opcional — qué hay que hacer, criterios de aceptación, enlaces',
kanban_status: 'Estado',
kanban_assignee: 'Responsable',
kanban_assignee_placeholder: 'Opcional — déjalo en blanco para cualquier trabajador',
kanban_tenant: 'Tenant',
kanban_tenant_placeholder: 'Opcional — slug del proyecto o equipo',
kanban_priority: 'Prioridad',
kanban_priority_hint: 'Los números más altos se ejecutan primero. Predeterminado: 0.',
kanban_title_required: 'El título es obligatorio.',
kanban_edit_task: 'Editar tarea',
kanban_run_dispatcher: 'Ejecutar despachador',
kanban_run_dispatcher_confirm: 'Esto reclamará tareas Ready en este tablero y generará subprocesos worker (uno por tarea, hasta 8 por clic). ¿Continuar?',
kanban_assignee_profiles_label: 'Perfiles Hermes',
kanban_assignee_other_label: 'Otros (carriles CLI / perfiles eliminados)',
kanban_assignee_unassigned: '— Sin asignar (no se ejecutará automáticamente) —',
kanban_ready_needs_assignee: 'Elegiste «Sin asignar» + «Ready». El despachador omitirá esta tarea. Envía de nuevo para confirmar o selecciona un perfil.',
kanban_dispatch_preview_prefix: 'Vista previa:',
kanban_dispatch_run_prefix: 'Despachado:',
kanban_dispatch_spawned: 'generadas',
kanban_dispatch_promoted: 'promovidas',
kanban_dispatch_reclaimed: 'recuperadas',
kanban_dispatch_skipped_unassigned: 'omitidas (sin asignar)',
kanban_dispatch_skipped_nonspawnable: 'omitidas (perfil desconocido)',
kanban_dispatch_auto_blocked: 'auto-bloqueadas',
kanban_dispatch_timed_out: 'expiradas',
kanban_dispatch_crashed: 'fallaron',
kanban_new_task: 'New task',
kanban_add_comment: 'Add comment',
kanban_only_mine: 'Only mine',
kanban_bulk_action: 'Bulk action',
kanban_nudge_dispatcher: 'Preview 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_complete: 'complete',
kanban_card_archive: 'archive',
kanban_unassigned: 'unassigned',
kanban_status_archived: 'Archived',
tab_todos: 'Todos',
tab_insights: 'Analíticas',
tab_dashboard: 'Panel de Hermes',
dashboard_loopback_warning: 'El panel solo usa loopback en el servidor. Navega desde el propio servidor o reinícialo con --host 0.0.0.0 (inseguro).',
tab_logs: 'Logs',
tab_settings: 'Ajustes',
logs_title: 'Logs', // TODO: translate
logs_file: 'File', // TODO: translate
logs_tail: 'Tail', // TODO: translate
logs_auto_refresh: 'Auto-refresh (5s)', // TODO: translate
logs_wrap: 'Wrap lines', // TODO: translate
logs_copy_all: 'Copy all', // TODO: translate
logs_empty: 'No log lines yet.', // TODO: translate
logs_loading: 'Loading logs…', // TODO: translate
logs_load_failed: 'Logs failed to load', // TODO: translate
logs_status_idle: 'Choose a log file to view recent lines.', // TODO: translate
logs_no_mtime: 'not written yet', // TODO: translate
logs_truncated_hint: 'Showing the tail of a large log file; older bytes were skipped to keep memory bounded.', // TODO: translate
logs_copied: 'Logs copied', // TODO: translate
logs_severity: 'Severity', // TODO: translate
logs_severity_all: 'All', // TODO: translate
logs_severity_errors: 'Errors', // TODO: translate
logs_severity_warnings: 'Warnings+', // TODO: translate
logs_filter_active: 'shown (filter active)', // TODO: translate
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'}`,
session_meta_segments: (n) => `${n} ${n === 1 ? 'segmento' : 'segmentos'}`,
session_lineage_segment_untitled: 'Segmento sin título',
session_lineage_segment_open: 'Abrir segmento de linaje',
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',
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: "Usa 'every 1h' o una expresión cron para trabajos recurrentes. Duraciones como '30m' se ejecutan una sola vez.",
cron_schedule_once_warning: "Las duraciones como '30m' se ejecutan una vez y se eliminan después de correr. Usa 'every 30m' para mantener un trabajo recurrente.",
cron_prompt_label: 'Prompt',
cron_deliver_label: 'Entregar salida a',
cron_deliver_local: 'Local (solo guardar salida)',
cron_profile_label: 'Perfil',
cron_profile_server_default: 'predeterminado del servidor',
cron_profile_server_default_hint: 'Usa el perfil predeterminado del servidor WebUI durante la ejecución. Los trabajos existentes sin perfil conservan este comportamiento heredado.',
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.',
settings_label_session_jump_buttons: 'Mostrar botones de salto de sesión',
settings_desc_session_jump_buttons: 'Muestra botones flotantes de Inicio y Fin al leer historiales de sesión largos.',
settings_label_session_endless_scroll: 'Cargar mensajes antiguos al desplazarse hacia arriba',
settings_desc_session_endless_scroll: 'Si está activado, los mensajes antiguos se cargan automáticamente al desplazarte hacia arriba. Si está desactivado, usa el botón de mensajes antiguos.',
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_updated: 'Updated',
status_ephemeral: 'Ephemeral snapshot — not saved to transcript history.',
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_daily_tokens: 'Daily Tokens',
insights_model_name: 'Model',
insights_model_sessions: 'Sessions',
insights_model_tokens: 'Tokens',
insights_model_cost: 'Cost',
insights_model_share: 'Share',
insights_no_usage_data: 'No usage data yet',
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: {
offline_title: 'Verbindung verloren',
offline_browser_detail: 'Dein Browser meldet, dass dieses Gerät offline ist.',
offline_network_detail: 'Hermes ist von diesem Browser aus gerade nicht erreichbar.',
offline_autorefresh: 'Ich aktualisiere diese Seite automatisch, sobald Hermes wieder erreichbar ist.',
offline_check_now: 'Jetzt prüfen',
offline_checking: 'Prüfe…',
offline_stream_waiting: 'Verbindung verloren. Warte auf Aktualisierung…',
_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.',
mcp_restart_hint: 'Server changes are read-only here for now. Edit config.yaml and restart Hermes for changes to take effect.',
mcp_toggle_followup: 'Enable/disable controls are intentionally deferred until MCP reload semantics are explicit.',
mcp_status_active: 'Active',
mcp_status_configured: 'Configured',
mcp_status_disabled: 'Disabled',
mcp_status_invalid_config: 'Invalid config',
mcp_status_unknown: 'Unknown',
mcp_tool_count: '{0} tools',
mcp_enabled_yes: 'Enabled',
mcp_enabled_no: 'Disabled',
mcp_tools_title: 'MCP Tools',
mcp_tools_desc: 'Search known tools across active MCP servers.',
mcp_tools_search_placeholder: 'Search tools by name, server, or description…',
mcp_tools_no_tools: 'No MCP tools are available from the active runtime inventory.',
mcp_tools_no_matches: 'No MCP tools match your search.',
mcp_tools_load_failed: 'Failed to load MCP tools.',
mcp_tools_schema_empty: 'No schema parameters.',
mcp_tools_runtime_note: 'Tool inventory only uses already-known active MCP runtime data; the WebUI does not start or probe servers.',
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',
session_jump_start: 'Anfang',
session_jump_start_label: 'Zum Anfang der Sitzung springen',
session_jump_end: 'Ende',
session_jump_end_label: 'Zum Ende der Sitzung springen',
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_goal: 'Ein dauerhaftes Ziel setzen oder prüfen',
goal_evaluating_progress: 'Evaluating goal progress…',
goal_working_toward: 'Working toward goal…',
goal_continuing_toast: 'Continuing toward goal…',
goal_status_none: 'No active goal. Set one with /goal <text>.',
goal_status_active: (turns, max_turns, goal) => `⊙ Goal (active, ${turns}/${max_turns} turns): ${goal}`,
goal_status_paused: (turns, max_turns, reason, goal) => `⏸ Goal (paused, ${turns}/${max_turns}${reason ? `, ${reason}` : ''}): ${goal}`,
goal_status_done: (turns, max_turns, goal) => `✓ Goal done (${turns}/${max_turns}): ${goal}`,
goal_set: (turns, goal) => `⊙ Goal set (${turns}-turn budget): ${goal}`,
goal_paused: (goal) => `⏸ Goal paused: ${goal}`,
goal_resumed: (goal) => `▶ Goal resumed: ${goal}`,
goal_cleared: 'Goal cleared.',
goal_no_goal: 'No active goal.',
goal_achieved: (reason) => `✓ Goal achieved: ${reason}`,
goal_paused_budget_exhausted: (turns, max_turns) => `⏸ Goal paused — ${turns}/${max_turns} turns used. Use /goal resume to keep going, or /goal clear to stop.`,
goal_continuing: (turns, max_turns, reason) => `↻ Continuing toward goal (${turns}/${max_turns}): ${reason}`,
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.',
workspace_show_hidden_files: 'Versteckte Dateien anzeigen',
workspace_show_hidden_files_desc: '.DS_Store, .git, node_modules und weitere versteckte / Systemdateien im Dateibaum anzeigen.',
workspace_hidden_files_visible: 'versteckt sichtbar',
workspace_hidden_files_visible_title: 'Versteckte Dateien sind sichtbar — Klicken für Optionen',
workspace_options: 'Arbeitsbereich-Optionen',
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: ',
copy_file_path: 'Dateipfad kopieren',
path_copied: 'Dateipfad in die Zwischenablage kopiert',
path_copy_failed: 'Pfad konnte nicht kopiert werden: ',
session_rename: 'Unterhaltung umbenennen',
session_rename_desc: 'Titel dieser Unterhaltung bearbeiten',
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: ',
upload_too_large: (maxMb, fileMb) => `Datei ist zu groß (${fileMb} MB). Die maximale Uploadgröße beträgt ${maxMb} MB.`,
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_work_queue_hint: 'This is the Hermes Agent work queue. Create or triage a task, assign it, move it to Ready, then let the dispatcher claim it.',
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_status_original_hint: 'Actual status: {0}. This dialog only supports Triage/Todo/Ready edits.',
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_title: 'Titel',
kanban_description: 'Beschreibung',
kanban_description_placeholder: 'Optional — was zu tun ist, Akzeptanzkriterien, Links',
kanban_status: 'Status',
kanban_assignee: 'Zugewiesen an',
kanban_assignee_placeholder: 'Optional — leer lassen für beliebigen Worker',
kanban_tenant: 'Mandant',
kanban_tenant_placeholder: 'Optional — Projekt- oder Team-Slug',
kanban_priority: 'Priorität',
kanban_priority_hint: 'Höhere Zahlen laufen zuerst. Standard: 0.',
kanban_title_required: 'Titel ist erforderlich.',
kanban_edit_task: 'Aufgabe bearbeiten',
kanban_run_dispatcher: 'Dispatcher ausführen',
kanban_run_dispatcher_confirm: 'Dies beansprucht Ready-Aufgaben auf diesem Board und startet Worker-Subprozesse (einen pro Aufgabe, bis zu 8 pro Klick). Fortfahren?',
kanban_assignee_profiles_label: 'Hermes-Profile',
kanban_assignee_other_label: 'Andere (CLI-Bahnen / entfernte Profile)',
kanban_assignee_unassigned: '— Nicht zugewiesen (läuft nicht automatisch) —',
kanban_ready_needs_assignee: 'Du hast „Nicht zugewiesen“ + „Ready“ gewählt. Der Dispatcher überspringt diese Aufgabe. Erneut senden zum Bestätigen oder ein Profil wählen.',
kanban_dispatch_preview_prefix: 'Vorschau:',
kanban_dispatch_run_prefix: 'Gestartet:',
kanban_dispatch_spawned: 'gestartet',
kanban_dispatch_promoted: 'befördert',
kanban_dispatch_reclaimed: 'zurückgenommen',
kanban_dispatch_skipped_unassigned: 'übersprungen (kein Bearbeiter)',
kanban_dispatch_skipped_nonspawnable: 'übersprungen (unbekanntes Profil)',
kanban_dispatch_auto_blocked: 'auto-blockiert',
kanban_dispatch_timed_out: 'Zeitüberschreitung',
kanban_dispatch_crashed: 'abgestürzt',
kanban_new_task: 'New task',
kanban_add_comment: 'Add comment',
kanban_only_mine: 'Only mine',
kanban_bulk_action: 'Bulk action',
kanban_nudge_dispatcher: 'Preview 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_complete: 'complete',
kanban_card_archive: 'archive',
kanban_unassigned: 'unassigned',
kanban_status_archived: 'Archived',
tab_todos: 'Todos',
tab_insights: 'Statistiken',
tab_dashboard: 'Hermes-Dashboard',
dashboard_loopback_warning: 'Das Dashboard ist auf dem Server nur per Loopback erreichbar. Öffne es direkt auf dem Server oder starte es mit --host 0.0.0.0 neu (unsicher).',
tab_logs: 'Logs',
tab_settings: 'Einstellungen',
logs_title: 'Logs', // TODO: translate
logs_file: 'File', // TODO: translate
logs_tail: 'Tail', // TODO: translate
logs_auto_refresh: 'Auto-refresh (5s)', // TODO: translate
logs_wrap: 'Wrap lines', // TODO: translate
logs_copy_all: 'Copy all', // TODO: translate
logs_empty: 'No log lines yet.', // TODO: translate
logs_loading: 'Loading logs…', // TODO: translate
logs_load_failed: 'Logs failed to load', // TODO: translate
logs_status_idle: 'Choose a log file to view recent lines.', // TODO: translate
logs_no_mtime: 'not written yet', // TODO: translate
logs_truncated_hint: 'Showing the tail of a large log file; older bytes were skipped to keep memory bounded.', // TODO: translate
logs_copied: 'Logs copied', // TODO: translate
logs_severity: 'Severity', // TODO: translate
logs_severity_all: 'All', // TODO: translate
logs_severity_errors: 'Errors', // TODO: translate
logs_severity_warnings: 'Warnings+', // TODO: translate
logs_filter_active: 'shown (filter active)', // TODO: translate
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'}`,
session_meta_segments: (n) => `${n} Segment${n === 1 ? '' : 'e'}`,
session_lineage_segment_untitled: 'Unbenanntes Segment',
session_lineage_segment_open: 'Liniensegment öffnen',
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: "Für wiederkehrende Aufgaben 'every 1h' oder einen Cron-Ausdruck verwenden. Reine Dauern wie '30m' laufen einmal.",
cron_schedule_once_warning: "Dauerangaben wie '30m' laufen einmal und werden nach der Ausführung entfernt. Verwende 'every 30m' für eine wiederkehrende Aufgabe.",
cron_prompt_label: 'Prompt',
cron_deliver_label: 'Ausgabe senden an',
cron_deliver_local: 'Lokal (nur speichern)',
cron_profile_label: 'Profil',
cron_profile_server_default: 'Serverstandard',
cron_profile_server_default_hint: 'Verwendet zur Laufzeit das Standardprofil des WebUI-Servers. Bestehende Jobs ohne Profil behalten dieses Legacy-Verhalten.',
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.',
settings_label_session_jump_buttons: 'Sitzungs-Sprungtasten anzeigen',
settings_desc_session_jump_buttons: 'Zeigt beim Lesen langer Sitzungsverläufe schwebende Anfang- und Ende-Tasten an.',
settings_label_session_endless_scroll: 'Ältere Nachrichten beim Hochscrollen laden',
settings_desc_session_endless_scroll: 'Wenn aktiviert, werden ältere Nachrichten beim Hochscrollen automatisch geladen. Wenn deaktiviert, nutzt du den Button für ältere Nachrichten.',
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_updated: 'Updated',
status_ephemeral: 'Ephemeral snapshot — not saved to transcript history.',
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',
workspace_new_worktree_conversation: 'Neue Unterhaltung in Worktree',
workspace_new_worktree_conversation_meta: 'Erstellt einen isolierten git worktree für diesen Arbeitsbereich.',
workspace_worktree_created: 'Worktree-Unterhaltung erstellt',
workspace_worktree_failed: 'Worktree-Erstellung fehlgeschlagen: ',
session_worktree_badge: 'Worktree',
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) => `${count} Fähigkeit${count === 1 ? '' : 'en'}`,
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.',
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_daily_tokens: 'Daily Tokens',
insights_model_name: 'Model',
insights_model_sessions: 'Sessions',
insights_model_tokens: 'Tokens',
insights_model_cost: 'Cost',
insights_model_share: 'Share',
insights_no_usage_data: 'No usage data yet',
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: {
offline_title: '连接已断开',
offline_browser_detail: '浏览器报告此设备当前离线。',
offline_network_detail: '此浏览器当前无法连接到 Hermes。',
offline_autorefresh: '当 Hermes 可访问时,我会自动刷新此页面。',
offline_check_now: '立即检查',
offline_checking: '正在检查…',
offline_stream_waiting: '连接已断开。正在等待刷新…',
_lang: 'zh',
_label: '\u7b80\u4f53\u4e2d\u6587',
_speech: 'zh-CN',
// boot.js
cancelling: '正在取消...',
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: '无法加载 patch 文件',
diff_too_large: 'Patch 文件过大,无法内联显示',
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 服务器加载失败。',
mcp_restart_hint: '服务器更改目前为只读。请编辑 config.yaml 并重启 Hermes。',
mcp_toggle_followup: '在 MCP 的重新加载规范明确之前,我们有意暂缓启用/禁用的切换。',
mcp_status_active: '运行中',
mcp_status_configured: '已配置',
mcp_status_disabled: '已禁用',
mcp_status_invalid_config: '配置无效',
mcp_status_unknown: '未知',
mcp_tool_count: '{0} 个工具',
mcp_enabled_yes: '已启用',
mcp_enabled_no: '已禁用',
mcp_tools_title: 'MCP 工具',
mcp_tools_desc: '搜索活跃 MCP 服务器中的已知工具。',
mcp_tools_search_placeholder: '按名称、服务器或描述搜索工具…',
mcp_tools_no_tools: '当前运行时清单中没有可用的 MCP 工具。',
mcp_tools_no_matches: '没有匹配的 MCP 工具。',
mcp_tools_load_failed: '加载 MCP 工具失败。',
mcp_tools_schema_empty: '无参数。',
mcp_tools_runtime_note: '工具清单仅使用已知的活跃 MCP 运行时数据;WebUI 不会启动或探测服务器。',
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: '允许执行此命令一次(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: '↑ 向上滚动或点击加载更早的消息',
session_jump_start: '开头',
session_jump_start_label: '跳转到会话开头',
session_jump_end: '结尾',
session_jump_end_label: '跳转到会话结尾',
queued_label: '响应后发送',
queued_count: (n) => n === 1 ? '1 条排队' : `${n} 条排队`,
queued_cancel: '取消排队消息',
model_unavailable: '(不可用)',
model_unavailable_title: '这个模型已经不在当前 provider 列表中',
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: '未找到工作区',
workspace_new_worktree_conversation: '在 worktree 中新建对话',
workspace_new_worktree_conversation_meta: '为此工作区创建隔离的 git worktree。',
workspace_worktree_created: '已创建 worktree 对话',
workspace_worktree_failed: 'Worktree 创建失败:',
session_worktree_badge: 'Worktree',
session_toolsets: 'Session 工具集',
session_toolsets_desc: '限制此会话可用工具(留空 = 使用全局配置)',
session_toolsets_global: '全局(默认)',
session_toolsets_custom: '自定义',
session_toolsets_placeholder: 'tool1, tool2, \u2026', // TODO: translate
session_toolsets_apply: '应用',
session_toolsets_clear: '清除(使用全局)',
session_toolsets_applied: '工具集已更新',
session_toolsets_cleared: '工具集已清除 — 使用全局配置',
session_toolsets_failed: '更新工具集失败:',
model_scope_advisory: '从下一条消息起应用于当前对话。',
model_scope_toast: '从下一条消息起应用于当前对话。',
// commands.js
cmd_help: '查看可用命令',
cmd_clear: '清空当前对话消息',
cmd_compress: '手动压缩对话上下文(用法:/compress [主题]',
ctx_compress_hint: '压缩上下文以释放空间 →',
ctx_compress_action: '⚠ 立即压缩以释放上下文',
cmd_compact_alias: '旧别名:/compress',
cmd_model: '切换模型(例如 /model gpt-4o',
cmd_workspace: '按名称切换工作区',
cmd_terminal: '打开工作区 Terminal',
cmd_new: '新建聊天会话',
cmd_usage: '切换 token 用量显示',
cmd_theme: '切换外观(主题:system/dark/light,皮肤:default/ares/mono/slate/poseidon/sisyphus/charizard',
cmd_personality: '切换 Agent 人设',
cmd_skills: '列出可用的 Hermes 技能',
available_commands: '可用命令:',
type_slash: '输入 / 可查看命令',
conversation_cleared: '对话已清空',
command_label: '命令',
context_compaction_label: '上下文压缩',
preserved_task_list_label: '保留的任务列表',
reference_only_label: '仅供参考',
model_usage: '用法:/model <name>',
no_model_match: '没有匹配“',
switched_to: '已切换到 ',
workspace_usage: '用法:/workspace <name>',
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: 'Token 用量显示已开启',
usage_personality_none: '无',
token_usage_off: 'Token 用量显示已关闭',
theme_usage: '用法:/theme ',
theme_set: '主题:',
no_active_session: '当前没有活动会话',
cmd_queue: '将消息加入下一轮的队列',
cmd_goal: '设置或查看持久目标',
goal_evaluating_progress: 'Evaluating goal progress…',
goal_working_toward: 'Working toward goal…',
goal_continuing_toast: 'Continuing toward goal…',
goal_status_none: 'No active goal. Set one with /goal <text>.',
goal_status_active: (turns, max_turns, goal) => `⊙ Goal (active, ${turns}/${max_turns} turns): ${goal}`,
goal_status_paused: (turns, max_turns, reason, goal) => `⏸ Goal (paused, ${turns}/${max_turns}${reason ? `, ${reason}` : ''}): ${goal}`,
goal_status_done: (turns, max_turns, goal) => `✓ Goal done (${turns}/${max_turns}): ${goal}`,
goal_set: (turns, goal) => `⊙ Goal set (${turns}-turn budget): ${goal}`,
goal_paused: (goal) => `⏸ Goal paused: ${goal}`,
goal_resumed: (goal) => `▶ Goal resumed: ${goal}`,
goal_cleared: 'Goal cleared.',
goal_no_goal: 'No active goal.',
goal_achieved: (reason) => `✓ Goal achieved: ${reason}`,
goal_paused_budget_exhausted: (turns, max_turns) => `⏸ Goal paused — ${turns}/${max_turns} turns used. Use /goal resume to keep going, or /goal clear to stop.`,
goal_continuing: (turns, max_turns, reason) => `↻ Continuing toward goal (${turns}/${max_turns}): ${reason}`,
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(中断 + 发送)',
workspace_empty_no_path: '未选择工作区。请在 设置 → 工作区 中设置工作区以浏览文件。',
workspace_empty_dir: '此工作区为空。',
workspace_show_hidden_files: '显示隐藏文件',
workspace_show_hidden_files_desc: '将 .DS_Store、.git、node_modules 以及其他隐藏文件/系统文件包含在文件树中。',
workspace_hidden_files_visible: '隐藏 显示',
workspace_hidden_files_visible_title: '隐藏文件已显示 — 点击查看选项',
workspace_options: '工作区选项',
no_personalities: '没有找到人设(可添加到 ~/.hermes/personalities/',
available_personalities: '可用人设:',
personality_switch_hint: '\n\n使用 `/personality <name>` 切换,或用 `/personality none` 清空。',
personalities_load_failed: '加载人设失败',
personality_cleared: '人设已清空',
personality_set: '当前人设:',
failed_colon: '失败:',
// ui.js
no_workspace: '未选择工作区',
terminal_open_title: '打开工作区 Terminal',
terminal_no_workspace_title: '请先选择工作区再打开 Terminal',
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: '确认',
// 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: '显示失败:',
copy_file_path: '\u590d\u5236\u6587\u4ef6\u8def\u5f84',
path_copied: '\u6587\u4ef6\u8def\u5f84\u5df2\u590d\u5236\u5230\u526a\u8d34\u677f',
path_copy_failed: '\u590d\u5236\u8def\u5f84\u5931\u8d25\uff1a',
session_rename: '\u91cd\u547d\u540d\u5bf9\u8bdd',
session_rename_desc: '\u7f16\u8f91\u6b64\u5bf9\u8bdd\u7684\u6807\u9898',
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: '上传失败:',
upload_too_large: (maxMb, fileMb) => `\u6587\u4ef6\u8fc7\u5927\uff08${fileMb} MB\uff09\u3002\u6700\u5927\u4e0a\u4f20\u5927\u5c0f\u4e3a ${maxMb} MB\u3002`,
all_uploads_failed: (n) => `${n} 个文件全部上传失败`,
// settings panel
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: '显示 token 用量',
settings_label_sidebar_density: '侧边栏密度',
cmd_reasoning: '切换思维可见性(显示/隐藏)、设置工作强度或查看当前状态',
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 page
login_title: '登录',
login_subtitle: '输入密码继续使用',
login_placeholder: '密码',
login_btn: '登录',
login_invalid_pw: '密码错误',
login_conn_failed: '连接失败',
// sidebar & navigation
tab_chat: '聊天',
tab_memory: '记忆',
tab_skills: '技能',
tab_tasks: '任务',
tab_kanban: '看板',
kanban_board: '看板',
kanban_visible_tasks: '{0} 个可见任务',
kanban_search_tasks: '搜索任务',
kanban_all_assignees: '所有负责人',
kanban_all_tenants: '所有租户',
kanban_include_archived: '包含已归档',
kanban_no_matching_tasks: '没有匹配的任务',
kanban_no_data: '无看板数据',
kanban_work_queue_hint: '这是 Hermes Agent 的工作队列。创建或分类任务,分配任务,将其移至“就绪”状态,然后让调度员认领任务。',
kanban_unavailable: '看板不可用',
kanban_read_only: '只读视图',
kanban_empty: '空',
kanban_task: '任务',
kanban_no_description: '无描述',
kanban_refresh: '刷新',
kanban_status_triage: '待分类',
kanban_status_todo: '待办',
kanban_status_ready: '就绪',
kanban_status_running: '进行中',
kanban_status_blocked: '阻塞',
kanban_status_done: '完成',
kanban_status_original_hint: '实际状态:{0}。此对话框仅支持编辑 Triage/Todo/Ready。',
kanban_comments_count: '评论 ({0})',
kanban_events_count: '事件 ({0})',
kanban_links: '链接',
kanban_parents: '父任务',
kanban_children: '子任务',
kanban_runs_count: '运行 ({0})',
kanban_no_comments: '无评论',
kanban_no_events: '无事件',
kanban_no_runs: '无运行记录',
kanban_title: '标题',
kanban_description: '描述',
kanban_description_placeholder: '可选 — 需要做什么、验收标准、链接',
kanban_status: '状态',
kanban_assignee: '负责人',
kanban_assignee_placeholder: '可选 — 留空表示任意工作器',
kanban_tenant: '租户',
kanban_tenant_placeholder: '可选 — 项目或团队标识',
kanban_priority: '优先级',
kanban_priority_hint: '数值越高越先执行,默认为 0。',
kanban_title_required: '标题为必填项。',
kanban_edit_task: '编辑任务',
kanban_run_dispatcher: '运行调度器',
kanban_run_dispatcher_confirm: '将认领此看板的 Ready 任务并生成工作子进程(每次点击最多 8 个)。是否继续?',
kanban_assignee_profiles_label: 'Hermes 配置',
kanban_assignee_other_label: '其他 (CLI 通道 / 已删除的配置)',
kanban_assignee_unassigned: '— 未分配 (不会自动运行) —',
kanban_ready_needs_assignee: '您选择了「未分配」+「Ready」。调度器将跳过此任务。再次提交以确认,或选择一个配置。',
kanban_dispatch_preview_prefix: '预览:',
kanban_dispatch_run_prefix: '已调度:',
kanban_dispatch_spawned: '已启动',
kanban_dispatch_promoted: '已提升',
kanban_dispatch_reclaimed: '已收回',
kanban_dispatch_skipped_unassigned: '跳过 (未分配)',
kanban_dispatch_skipped_nonspawnable: '跳过 (未知配置)',
kanban_dispatch_auto_blocked: '自动阻止',
kanban_dispatch_timed_out: '超时',
kanban_dispatch_crashed: '崩溃',
kanban_new_task: '新建任务',
kanban_add_comment: '添加评论',
kanban_only_mine: '仅我的',
kanban_bulk_action: '批量操作',
kanban_nudge_dispatcher: '提醒调度器',
kanban_stats: '统计',
kanban_worker_log: '工作日志',
kanban_block: '阻塞',
kanban_unblock: '解除阻塞',
kanban_back_to_board: '返回看板',
kanban_lanes_by_profile: '按配置文件分列',
kanban_new_board: '新建看板…',
kanban_rename_board: '重命名当前看板…',
kanban_archive_board: '归档当前看板…',
kanban_archive_board_confirm: '归档看板 "{name}"?任务仍保存在磁盘上,并且可以从 kanban/boards/_archived/ 恢复该看板。',
kanban_board_archived: '看板已归档',
kanban_board_name: '名称',
kanban_board_slug: '标识(小写,连字符)',
kanban_board_description: '描述(可选)',
kanban_board_icon: '图标(emoji,可选)',
kanban_board_color: '颜色(可选)',
kanban_board_name_required: '名称为必填',
kanban_board_slug_required: '标识为必填',
kanban_card_complete: '完成',
kanban_card_archive: '归档',
kanban_unassigned: '未分配',
kanban_status_archived: '已归档',
tab_todos: '待办',
tab_insights: '统计',
tab_dashboard: 'Hermes 仪表盘',
dashboard_loopback_warning: '仪表盘在服务器上仅限 loopback 访问。请从服务器本机浏览,或使用 --host 0.0.0.0 重启(不安全)。',
tab_workspaces: '工作区',
tab_profiles: '配置',
tab_logs: '日志',
tab_settings: '设置',
logs_title: '日志',
logs_file: '文件',
logs_tail: '末尾',
logs_auto_refresh: '自动刷新(5秒)',
logs_wrap: '自动换行',
logs_copy_all: '全部复制',
logs_empty: '暂无日志。',
logs_loading: '加载日志中…',
logs_load_failed: '日志加载失败',
logs_status_idle: '选择日志文件以查看最新内容。',
logs_no_mtime: '尚未写入',
logs_truncated_hint: '此处显示的是日志文件的末尾内容。为节省内存,已省略较早的数据。',
logs_copied: '日志已复制',
logs_severity: 'Severity', // TODO: translate
logs_severity_all: 'All', // TODO: translate
logs_severity_errors: 'Errors', // TODO: translate
logs_severity_warnings: 'Warnings+', // TODO: translate
logs_filter_active: 'shown (filter active)', // TODO: translate
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} 子会话`,
session_meta_segments: (n) => `${n}`,
session_lineage_segment_untitled: '未命名段',
session_lineage_segment_open: '打开脉络段',
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_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: '输入新密钥以替换…',
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: '自适应标题更新',
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 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 密钥(可选)',
onboarding_api_key_placeholder_optional: '留空用于无需密钥的服务器',
onboarding_api_key_help_keyless: '大多数 LM Studio / Ollama / vLLM 安装无需密钥即可运行。',
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_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: '测试连接',
onboarding_probe_probing: '正在测试连接…',
onboarding_probe_ok: '已连接。{n} 个模型可用。',
onboarding_probe_error_generic: '无法访问配置的基础 URL。',
onboarding_probe_error_invalid_url: '基础 URL 必须以 http:// 或 https:// 开头。',
onboarding_probe_error_dns: '无法解析主机名。请检查 URL,或在 Docker 中使用主机 IP 而非 localhost。',
onboarding_probe_error_connect_refused: '连接被拒绝 — 该地址上可能没有运行服务器。在 Docker 容器内,请使用主机 IP 而非 localhost。',
onboarding_probe_error_timeout: '端点未及时响应。请确认服务器正在运行且 URL 正确。',
onboarding_probe_error_http_4xx: '端点返回客户端错误。请检查认证信息和 URL 路径(通常以 /v1 结尾)。',
onboarding_probe_error_http_5xx: '端点返回服务器错误。请检查 LM Studio / Ollama 服务器日志。',
onboarding_probe_error_parse: '端点未返回预期的模型列表格式。请确认 URL 指向 OpenAI 兼容的 API 根路径。',
onboarding_probe_error_unreachable: '无法访问配置的基础 URL。',
onboarding_error_probe_failed: '无法验证配置的基础 URL。',
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: '加载配置档失败',
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: "循环任务请用 'every 1h' 或 Cron 表达式。像 '30m' 这样的裸时长只会运行一次。",
cron_schedule_once_warning: "像 '30m' 这样的时长写法只会运行一次,并在运行后移除。要保留循环任务,请使用 'every 30m'。",
cron_prompt_label: '提示词',
cron_deliver_label: '输出位置',
cron_deliver_local: '本地(仅保存输出)',
cron_profile_label: '配置档',
cron_profile_server_default: '服务器默认',
cron_profile_server_default_hint: '运行时使用 WebUI 服务器默认配置档。没有配置档的现有作业会保留此旧行为。',
cron_skills_label: '技能',
cron_skills_placeholder: '添加技能(可选)…',
cron_skills_edit_hint: '创建后无法再编辑技能列表。',
cron_duplicate: '复制',
cron_duplicated: '任务已复制(已暂停)',
// 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: '归档会话',
session_archive_desc: '隐藏此会话,直到显示归档',
session_archive_failed: '归档失败:',
session_archived: '会话已归档',
session_delete: '删除会话',
session_delete_desc: '永久删除此会话',
session_duplicate: '复制会话',
session_duplicate_desc: '用相同工作区和模型创建副本',
session_duplicate_failed: '复制失败:',
session_stop_response: '停止回复',
session_stop_response_desc: '取消此会话正在进行的回复',
session_duplicated: '会话已复制',
session_move_project: '移至项目',
session_move_project_desc_has: '更改此会话的项目',
session_move_project_desc_none: '为此会话分配项目',
session_pin: '置顶会话',
session_pin_desc: '将此会话保持在顶部',
session_pin_failed: '置顶失败:',
session_restore: '恢复会话',
session_restore_desc: '将会话恢复到主列表',
session_restored: '会话已恢复',
session_unpin: '取消置顶',
session_unpin_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_dropdown_appearance: '外观',
settings_dropdown_conversation: '对话',
settings_dropdown_preferences: '偏好',
settings_dropdown_providers: '提供商',
settings_dropdown_system: '系统',
settings_heading_subtitle: '偏好设置、对话工具和系统控制。',
settings_heading_title: '控制中心',
settings_section_appearance_meta: '主题、强调色和视觉风格。',
settings_section_appearance_title: '外观',
settings_section_conversation_title: '对话',
settings_section_preferences_meta: 'Hermes WebUI 的默认和 UI 行为。',
settings_section_preferences_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: '启用后,工作区/文件浏览器面板会在每次新会话时自动打开。您仍可随时手动关闭。',
settings_label_session_jump_buttons: '显示会话跳转按钮',
settings_desc_session_jump_buttons: '阅读较长会话历史时显示悬浮的开头和结尾按钮。',
settings_label_session_endless_scroll: '向上滚动时加载更早的消息',
settings_desc_session_endless_scroll: '启用后,向上滚动时会自动加载更早的消息。禁用时请使用加载更早消息按钮。',
open_in_browser: '在浏览器中打开',
settings_section_system_title: '系统',
settings_tab_appearance: '外观',
settings_tab_conversation: '对话',
settings_tab_preferences: '偏好',
settings_tab_system: '系统',
status_updated: '已更新',
status_ephemeral: '临时快照 — 不会保存到对话记录。',
status_no_tokens: '无令牌数据',
status_profile: '配置文件',
status_hermes_home: 'Hermes 主目录',
status_started: '开始时间',
status_tokens: '令牌',
status_unknown: '未知',
cmd_yolo: 'YOLO 模式切换',
yolo_no_session: '无活动会话',
yolo_enabled: '⚡ YOLO 模式已开启 — 将跳过所有审批',
cmd_branch: '将此对话分叉到新会话',
cmd_branch_usage:'/branch [名称] — 分叉会话(可选择添加名称)',
branch_forked: '已创建新分叉',
branch_failed: '分叉失败:',
fork_from_here: '从此处分叉',
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: '免提语音模式按钮',
settings_desc_voice_mode: '在听写麦克风旁显示语音模式按钮(音频波形)。让您自然说话 — Hermes 会在停顿后自动发送并朗读回复。需要支持语音识别和 TTS 的浏览器。',
settings_label_tts_voice: '语音',
settings_desc_tts_voice: '选择语音合成声音',
settings_label_tts_rate: '语速',
settings_label_tts_pitch: '音调',
checkpoint_date: '日期',
checkpoint_diff_files_changed: (n) => `${n} file${n === 1 ? '' : 's'} changed`, // TODO: translate
checkpoint_diff_no_changes: '此检查点与当前工作区之间无差异。',
checkpoint_diff_title: '检查点变更',
checkpoint_empty: '此工作区未找到检查点。',
checkpoint_error: '加载检查点失败',
checkpoint_files: '文件',
checkpoint_loading: '加载检查点中…',
checkpoint_message: '消息',
checkpoint_restore: '恢复',
checkpoint_restore_confirm_message: (ckpt) => `将工作区恢复到检查点 "${ckpt}"?此操作将用已保存版本覆盖文件。此检查点之后添加的文件不会被删除。`,
checkpoint_restore_confirm_title: '恢复检查点?',
checkpoint_restored: '检查点已恢复',
checkpoint_title: '检查点',
checkpoint_view_diff: '查看差异',
insights_activity_by_day: '按日活动',
insights_activity_by_hour: '按时活动',
insights_cost: '预估费用',
insights_daily_tokens: '每日令牌',
insights_model_name: '模型',
insights_model_sessions: '会话',
insights_model_tokens: '令牌',
insights_model_cost: '费用',
insights_model_share: '占比',
insights_no_usage_data: '暂无使用数据',
insights_footer: '显示最近 {days} 天的数据',
insights_input_tokens: '输入',
insights_messages: '消息',
insights_models: '模型',
insights_no_cost: 'N/A',
insights_output_tokens: '输出',
insights_peak_hour: '高峰:{hour}时',
insights_sessions: '会话',
insights_title: '使用分析',
insights_token_breakdown: '令牌分解',
insights_tokens: '令牌',
insights_total: '总计',
settings_desc_api_redact: '自托管用户可禁用以实现透明(不推荐用于共享实例)。',
settings_label_api_redact: '在 API 响应中隐藏敏感数据',
voice_error: '此浏览器不支持语音功能',
voice_listening: '正在聆听…',
voice_mode_active: '语音模式已开启',
voice_mode_off: '语音模式已关闭',
voice_speaking: '正在说话…',
voice_thinking: '思考中…',
// Composer voice buttons (#1488)
voice_dictate: '听写',
voice_dictate_active: '停止听写',
voice_mode_toggle: '语音模式',
voice_mode_toggle_active: '退出语音模式',
subagent_children: '子代理会话',
},
// 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 伺服器失敗。',
mcp_restart_hint: 'Server changes are read-only here for now. Edit config.yaml and restart Hermes for changes to take effect.',
mcp_toggle_followup: 'Enable/disable controls are intentionally deferred until MCP reload semantics are explicit.',
mcp_status_active: 'Active',
mcp_status_configured: 'Configured',
mcp_status_disabled: 'Disabled',
mcp_status_invalid_config: 'Invalid config',
mcp_status_unknown: 'Unknown',
mcp_tool_count: '{0} tools',
mcp_enabled_yes: 'Enabled',
mcp_enabled_no: 'Disabled',
mcp_tools_title: 'MCP Tools',
mcp_tools_desc: 'Search known tools across active MCP servers.',
mcp_tools_search_placeholder: 'Search tools by name, server, or description…',
mcp_tools_no_tools: 'No MCP tools are available from the active runtime inventory.',
mcp_tools_no_matches: 'No MCP tools match your search.',
mcp_tools_load_failed: 'Failed to load MCP tools.',
mcp_tools_schema_empty: 'No schema parameters.',
mcp_tools_runtime_note: 'Tool inventory only uses already-known active MCP runtime data; the WebUI does not start or probe servers.',
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: '↑ 向上捲動或點擊以載入較早的訊息',
session_jump_start: '開頭',
session_jump_start_label: '跳至會話開頭',
session_jump_end: '結尾',
session_jump_end_label: '跳至會話結尾',
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: '此工作區為空。',
workspace_show_hidden_files: '顯示隱藏檔案',
workspace_show_hidden_files_desc: 'Include .DS_Store, .git, node_modules, and other hidden / system files in the file tree.',
workspace_hidden_files_visible: 'hidden visible',
workspace_hidden_files_visible_title: 'Hidden files are visible — click for options',
workspace_options: 'Workspace options',
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',
copy_file_path: '\u8907\u88fd\u6a94\u6848\u8def\u5f91',
path_copied: '\u6a94\u6848\u8def\u5f91\u5df2\u8907\u88fd\u5230\u526a\u8cbc\u7c3f',
path_copy_failed: '\u8907\u88fd\u8def\u5f91\u5931\u6557\uff1a',
session_rename: '\u91cd\u65b0\u547d\u540d\u5c0d\u8a71',
session_rename_desc: '\u7de8\u8f2f\u6b64\u5c0d\u8a71\u7684\u6a19\u984c',
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: '上傳失敗:',
upload_too_large: (maxMb, fileMb) => `檔案過大(${fileMb} MB)。最大上傳大小為 ${maxMb} MB。`,
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: '啟用後,工作區/檔案瀏覽器面板會在每次新會話時自動開啓。您仍可隨時手動關閉。',
settings_label_session_jump_buttons: '顯示會話跳轉按鈕',
settings_desc_session_jump_buttons: '閱讀較長會話歷史時顯示浮動的開頭與結尾按鈕。',
settings_label_session_endless_scroll: '向上捲動時載入較早訊息',
settings_desc_session_endless_scroll: '啟用後,向上捲動時會自動載入較早訊息。停用時請使用載入較早訊息按鈕。',
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_dashboard: 'Hermes 儀表板',
dashboard_loopback_warning: '儀表板在伺服器上僅限 loopback 存取。請從伺服器本機瀏覽,或使用 --host 0.0.0.0 重新啟動(不安全)。',
tab_logs: 'Logs',
tab_workspaces: '\u5de5\u4f5c\u5340',
tab_kanban: 'Kanban',
kanban_board: '看板',
kanban_visible_tasks: '{0} 個可見任務',
kanban_search_tasks: '搜尋任務',
kanban_all_assignees: '所有指派對象',
kanban_all_tenants: '所有租戶',
kanban_include_archived: '包含已封存',
kanban_no_matching_tasks: '沒有符合的任務',
kanban_no_data: '沒有看板資料',
kanban_work_queue_hint: '這是 Hermes Agent 的工作佇列。建立或分類任務、指派對象、移至 Ready,然後讓調度器認領。',
kanban_unavailable: '看板無法使用',
kanban_read_only: '唯讀檢視',
kanban_empty: '空',
kanban_task: '任務',
kanban_no_description: '無描述',
kanban_refresh: '重新整理',
kanban_status_triage: '分類',
kanban_status_todo: '待辦',
kanban_status_ready: '準備就緒',
kanban_status_running: '執行中',
kanban_status_blocked: '已封鎖',
kanban_status_done: '完成',
kanban_comments_count: '留言 ({0})',
kanban_events_count: '事件 ({0})',
kanban_links: '連結',
kanban_parents: '父任務',
kanban_children: '子任務',
kanban_runs_count: '執行 ({0})',
kanban_no_comments: '沒有留言',
kanban_no_events: '沒有事件',
kanban_no_runs: '沒有執行紀錄',
kanban_title: '標題',
kanban_description: '描述',
kanban_description_placeholder: '選填 — 需要完成的事項、驗收標準、連結',
kanban_status: '狀態',
kanban_status_original_hint: '實際狀態:{0}。此對話框僅支援編輯 Triage/Todo/Ready。',
kanban_assignee: '指派對象',
kanban_assignee_placeholder: '選填 — 個人資料或名稱',
kanban_tenant: '租戶',
kanban_tenant_placeholder: '預設',
kanban_priority: '優先順序',
kanban_priority_hint: '數字越大越先執行。預設為 0。',
kanban_title_required: '標題為必填。',
kanban_new_task: '新任務',
kanban_add_comment: '新增留言',
kanban_only_mine: '僅顯示我的',
kanban_bulk_action: '批次操作',
kanban_nudge_dispatcher: '預覽調度器',
kanban_stats: '統計',
kanban_worker_log: '工作者日誌',
kanban_block: '封鎖',
kanban_unblock: '解除封鎖',
kanban_back_to_board: '返回看板',
kanban_lanes_by_profile: '按設定檔分泳道',
kanban_new_board: '新看板…',
kanban_rename_board: '重新命名目前看板…',
kanban_archive_board: '封存目前看板…',
kanban_archive_board_confirm: '封存看板「{name}」?任務仍保留在磁碟上,可從 kanban/boards/_archived/ 復原。',
kanban_board_archived: '看板已封存',
kanban_board_name: '名稱',
kanban_board_slug: '代號(小寫、連字號)',
kanban_board_description: '描述(選填)',
kanban_board_icon: '圖示(表情符號,選填)',
kanban_board_color: '顏色(選填)',
kanban_board_name_required: '名稱為必填',
kanban_board_slug_required: '代號為必填',
kanban_card_complete: '完成',
kanban_card_archive: '封存',
kanban_unassigned: '未指派',
kanban_status_archived: '已封存',
kanban_edit_task: '編輯任務',
kanban_run_dispatcher: '執行調度器',
kanban_run_dispatcher_confirm: '將認領此看板的 Ready 任務並產生工作子程序(每次點擊最多 8 個)。是否繼續?',
kanban_assignee_profiles_label: 'Hermes 設定檔',
kanban_assignee_other_label: '其他(CLI 通道 / 已刪除的設定檔)',
kanban_assignee_unassigned: '— 未指派(不會自動執行)—',
kanban_ready_needs_assignee: '您選擇了「未指派」+「Ready」。調度器將跳過此任務。再次送出以確認,或選擇一個設定檔。',
kanban_dispatch_preview_prefix: '預覽:',
kanban_dispatch_run_prefix: '已調度:',
kanban_dispatch_spawned: '已啟動',
kanban_dispatch_promoted: '已提升',
kanban_dispatch_reclaimed: '已收回',
kanban_dispatch_skipped_unassigned: '跳過(未指派)',
kanban_dispatch_skipped_nonspawnable: '跳過(未知設定檔)',
kanban_dispatch_auto_blocked: '自動封鎖',
kanban_dispatch_timed_out: '逾時',
kanban_dispatch_crashed: '崩潰',
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} 則子`,
session_meta_segments: (n) => `${n}`,
session_lineage_segment_untitled: '未命名段',
session_lineage_segment_open: '開啟脈絡段',
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: '↑ 向上捲動或點擊以載入較早的訊息',
session_jump_start: '開頭',
session_jump_start_label: '跳至會話開頭',
session_jump_end: '結尾',
session_jump_end_label: '跳至會話結尾',
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} 則子`,
session_meta_segments: (n) => `${n}`,
session_lineage_segment_untitled: '未命名段',
session_lineage_segment_open: '開啟脈絡段',
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',
upload_too_large: (maxMb, fileMb) => `\u6a94\u6848\u904e\u5927\uff08${fileMb} MB\uff09\u3002\u6700\u5927\u4e0a\u50b3\u5927\u5c0f\u70ba ${maxMb} MB\u3002`,
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_goal: '設定或查看持久目標',
goal_evaluating_progress: 'Evaluating goal progress…',
goal_working_toward: 'Working toward goal…',
goal_continuing_toast: 'Continuing toward goal…',
goal_status_none: 'No active goal. Set one with /goal <text>.',
goal_status_active: (turns, max_turns, goal) => `⊙ Goal (active, ${turns}/${max_turns} turns): ${goal}`,
goal_status_paused: (turns, max_turns, reason, goal) => `⏸ Goal (paused, ${turns}/${max_turns}${reason ? `, ${reason}` : ''}): ${goal}`,
goal_status_done: (turns, max_turns, goal) => `✓ Goal done (${turns}/${max_turns}): ${goal}`,
goal_set: (turns, goal) => `⊙ Goal set (${turns}-turn budget): ${goal}`,
goal_paused: (goal) => `⏸ Goal paused: ${goal}`,
goal_resumed: (goal) => `▶ Goal resumed: ${goal}`,
goal_cleared: 'Goal cleared.',
goal_no_goal: 'No active goal.',
goal_achieved: (reason) => `✓ Goal achieved: ${reason}`,
goal_paused_budget_exhausted: (turns, max_turns) => `⏸ Goal paused — ${turns}/${max_turns} turns used. Use /goal resume to keep going, or /goal clear to stop.`,
goal_continuing: (turns, max_turns, reason) => `↻ Continuing toward goal (${turns}/${max_turns}): ${reason}`,
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_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_updated: '已更新',
status_ephemeral: '临时快照 — 不会保存到对话历史。',
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_provider: '供应商',
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: "循環任務請用 'every 1h' 或 Cron 表達式。像 '30m' 這樣的裸時長只會執行一次。",
cron_schedule_once_warning: "像 '30m' 這樣的時長寫法只會執行一次,並在執行後移除。要保留循環任務,請使用 'every 30m'。",
cron_prompt_label: '提示',
cron_deliver_label: '發送至',
cron_deliver_local: '僅本地儲存',
cron_profile_label: '設定檔',
cron_profile_server_default: '伺服器預設',
cron_profile_server_default_hint: '執行時使用 WebUI 伺服器預設設定檔。沒有設定檔的既有工作會保留此舊行為。',
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_daily_tokens: 'Daily Tokens',
insights_model_name: 'Model',
insights_model_sessions: 'Sessions',
insights_model_tokens: 'Tokens',
insights_model_cost: 'Cost',
insights_model_share: 'Share',
insights_no_usage_data: 'No usage data yet',
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: {
offline_title: 'Conexão perdida',
offline_browser_detail: 'O navegador informa que este dispositivo está offline.',
offline_network_detail: 'O Hermes está inacessível neste navegador agora.',
offline_autorefresh: 'Vou atualizar esta página automaticamente quando o Hermes voltar a responder.',
offline_check_now: 'Verificar agora',
offline_checking: 'Verificando…',
offline_stream_waiting: 'Conexão perdida. Aguardando para atualizar…',
_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',
session_jump_start: 'Início',
session_jump_start_label: 'Ir para o início da sessão',
session_jump_end: 'Fim',
session_jump_end_label: 'Ir para o fim da sessão',
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',
workspace_new_worktree_conversation: 'Nova conversa em worktree',
workspace_new_worktree_conversation_meta: 'Cria um git worktree isolado para este espaço de trabalho.',
workspace_worktree_created: 'Conversa em worktree criada',
workspace_worktree_failed: 'Falha ao criar worktree: ',
session_worktree_badge: 'Worktree',
// 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_goal: 'Definir ou consultar uma meta persistente',
goal_evaluating_progress: 'Evaluating goal progress…',
goal_working_toward: 'Working toward goal…',
goal_continuing_toast: 'Continuing toward goal…',
goal_status_none: 'No active goal. Set one with /goal <text>.',
goal_status_active: (turns, max_turns, goal) => `⊙ Goal (active, ${turns}/${max_turns} turns): ${goal}`,
goal_status_paused: (turns, max_turns, reason, goal) => `⏸ Goal (paused, ${turns}/${max_turns}${reason ? `, ${reason}` : ''}): ${goal}`,
goal_status_done: (turns, max_turns, goal) => `✓ Goal done (${turns}/${max_turns}): ${goal}`,
goal_set: (turns, goal) => `⊙ Goal set (${turns}-turn budget): ${goal}`,
goal_paused: (goal) => `⏸ Goal paused: ${goal}`,
goal_resumed: (goal) => `▶ Goal resumed: ${goal}`,
goal_cleared: 'Goal cleared.',
goal_no_goal: 'No active goal.',
goal_achieved: (reason) => `✓ Goal achieved: ${reason}`,
goal_paused_budget_exhausted: (turns, max_turns) => `⏸ Goal paused — ${turns}/${max_turns} turns used. Use /goal resume to keep going, or /goal clear to stop.`,
goal_continuing: (turns, max_turns, reason) => `↻ Continuing toward goal (${turns}/${max_turns}): ${reason}`,
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_provider: 'Provedor',
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_updated: 'Atualizado',
status_ephemeral: 'Instantâneo efêmero — não salvo no histórico.',
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.',
workspace_show_hidden_files: 'Mostrar arquivos ocultos',
workspace_show_hidden_files_desc: 'Include .DS_Store, .git, node_modules, and other hidden / system files in the file tree.',
workspace_hidden_files_visible: 'hidden visible',
workspace_hidden_files_visible_title: 'Hidden files are visible — click for options',
workspace_options: 'Workspace options',
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: ',
copy_file_path: 'Copiar caminho do arquivo',
path_copied: 'Caminho do arquivo copiado para a área de transferência',
path_copy_failed: 'Falha ao copiar caminho: ',
session_rename: 'Renomear conversa',
session_rename_desc: 'Editar o título desta conversa',
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: ',
upload_too_large: (maxMb, fileMb) => `O arquivo é grande demais (${fileMb} MB). O tamanho máximo de upload é ${maxMb} MB.`,
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.',
settings_label_session_jump_buttons: 'Mostrar botões de salto da sessão',
settings_desc_session_jump_buttons: 'Mostra botões flutuantes Início e Fim ao ler históricos longos de sessão.',
settings_label_session_endless_scroll: 'Carregar mensagens antigas ao rolar para cima',
settings_desc_session_endless_scroll: 'Quando ativado, mensagens antigas carregam automaticamente ao rolar para cima. Quando desativado, use o botão de mensagens antigas.',
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_work_queue_hint: 'This is the Hermes Agent work queue. Create or triage a task, assign it, move it to Ready, then let the dispatcher claim it.',
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_status_original_hint: 'Actual status: {0}. This dialog only supports Triage/Todo/Ready edits.',
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_title: 'Título',
kanban_description: 'Descrição',
kanban_description_placeholder: 'Opcional — o que precisa ser feito, critérios de aceitação, links',
kanban_status: 'Status',
kanban_assignee: 'Responsável',
kanban_assignee_placeholder: 'Opcional — deixe em branco para qualquer worker',
kanban_tenant: 'Tenant',
kanban_tenant_placeholder: 'Opcional — slug do projeto ou equipe',
kanban_priority: 'Prioridade',
kanban_priority_hint: 'Números maiores executam primeiro. Padrão: 0.',
kanban_title_required: 'O título é obrigatório.',
kanban_edit_task: 'Editar tarefa',
kanban_run_dispatcher: 'Executar despachador',
kanban_run_dispatcher_confirm: 'Isso reivindicará tarefas Ready neste quadro e gerará subprocessos worker (um por tarefa, até 8 por clique). Continuar?',
kanban_assignee_profiles_label: 'Perfis Hermes',
kanban_assignee_other_label: 'Outros (faixas CLI / perfis removidos)',
kanban_assignee_unassigned: '— Não atribuído (não rodará automaticamente) —',
kanban_ready_needs_assignee: 'Você selecionou «Não atribuído» + «Ready». O despachador pulará esta tarefa. Envie novamente para confirmar ou escolha um perfil.',
kanban_dispatch_preview_prefix: 'Prévia:',
kanban_dispatch_run_prefix: 'Despachado:',
kanban_dispatch_spawned: 'iniciadas',
kanban_dispatch_promoted: 'promovidas',
kanban_dispatch_reclaimed: 'reclamadas',
kanban_dispatch_skipped_unassigned: 'puladas (sem responsável)',
kanban_dispatch_skipped_nonspawnable: 'puladas (perfil desconhecido)',
kanban_dispatch_auto_blocked: 'auto-bloqueadas',
kanban_dispatch_timed_out: 'tempo esgotado',
kanban_dispatch_crashed: 'falharam',
kanban_new_task: 'New task',
kanban_add_comment: 'Add comment',
kanban_only_mine: 'Only mine',
kanban_bulk_action: 'Bulk action',
kanban_nudge_dispatcher: 'Preview 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_complete: 'complete',
kanban_card_archive: 'archive',
kanban_unassigned: 'unassigned',
kanban_status_archived: 'Archived',
tab_todos: 'Todos',
tab_insights: 'Estatísticas',
tab_dashboard: 'Painel Hermes',
dashboard_loopback_warning: 'O painel é somente loopback no servidor. Navegue pelo próprio servidor ou reinicie com --host 0.0.0.0 (inseguro).',
tab_logs: 'Logs',
tab_settings: 'Configurações',
logs_title: 'Logs', // TODO: translate
logs_file: 'File', // TODO: translate
logs_tail: 'Tail', // TODO: translate
logs_auto_refresh: 'Auto-refresh (5s)', // TODO: translate
logs_wrap: 'Wrap lines', // TODO: translate
logs_copy_all: 'Copy all', // TODO: translate
logs_empty: 'No log lines yet.', // TODO: translate
logs_loading: 'Loading logs…', // TODO: translate
logs_load_failed: 'Logs failed to load', // TODO: translate
logs_status_idle: 'Choose a log file to view recent lines.', // TODO: translate
logs_no_mtime: 'not written yet', // TODO: translate
logs_truncated_hint: 'Showing the tail of a large log file; older bytes were skipped to keep memory bounded.', // TODO: translate
logs_copied: 'Logs copied', // TODO: translate
logs_severity: 'Severity', // TODO: translate
logs_severity_all: 'All', // TODO: translate
logs_severity_errors: 'Errors', // TODO: translate
logs_severity_warnings: 'Warnings+', // TODO: translate
logs_filter_active: 'shown (filter active)', // TODO: translate
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'}`,
session_meta_segments: (n) => `${n} segment${n === 1 ? '' : 's'}`,
session_lineage_segment_untitled: 'Segmento sem título',
session_lineage_segment_open: 'Abrir segmento de linhagem',
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: "Use 'every 1h' ou uma expressão Cron para tarefas recorrentes. Durações como '30m' rodam uma vez.",
cron_schedule_once_warning: "Durações como '30m' rodam uma vez e são removidas após executar. Use 'every 30m' para manter uma tarefa recorrente.",
cron_prompt_label: 'Prompt',
cron_deliver_label: 'Entregar output para',
cron_deliver_local: 'Local (salvar output apenas)',
cron_profile_label: 'Perfil',
cron_profile_server_default: 'padrão do servidor',
cron_profile_server_default_hint: 'Usa o perfil padrão do servidor WebUI no momento da execução. Tarefas existentes sem perfil mantêm esse comportamento legado.',
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',
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: {
offline_title: '연결이 끊겼습니다',
offline_browser_detail: '브라우저가 이 장치가 오프라인이라고 보고합니다.',
offline_network_detail: '현재 이 브라우저에서 Hermes에 연결할 수 없습니다.',
offline_autorefresh: 'Hermes에 다시 연결되면 이 페이지를 자동으로 새로고침합니다.',
offline_check_now: '지금 확인',
offline_checking: '확인 중…',
offline_stream_waiting: '연결이 끊겼습니다. 새로고침을 기다리는 중…',
_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.',
mcp_restart_hint: 'Server changes are read-only here for now. Edit config.yaml and restart Hermes for changes to take effect.',
mcp_toggle_followup: 'Enable/disable controls are intentionally deferred until MCP reload semantics are explicit.',
mcp_status_active: 'Active',
mcp_status_configured: 'Configured',
mcp_status_disabled: 'Disabled',
mcp_status_invalid_config: 'Invalid config',
mcp_status_unknown: 'Unknown',
mcp_tool_count: '{0} tools',
mcp_enabled_yes: 'Enabled',
mcp_enabled_no: 'Disabled',
mcp_tools_title: 'MCP Tools',
mcp_tools_desc: 'Search known tools across active MCP servers.',
mcp_tools_search_placeholder: 'Search tools by name, server, or description…',
mcp_tools_no_tools: 'No MCP tools are available from the active runtime inventory.',
mcp_tools_no_matches: 'No MCP tools match your search.',
mcp_tools_load_failed: 'Failed to load MCP tools.',
mcp_tools_schema_empty: 'No schema parameters.',
mcp_tools_runtime_note: 'Tool inventory only uses already-known active MCP runtime data; the WebUI does not start or probe 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: '↑ 위로 스크롤하거나 클릭하여 이전 메시지 불러오기',
session_jump_start: '시작',
session_jump_start_label: '세션 시작으로 이동',
session_jump_end: '끝',
session_jump_end_label: '세션 끝으로 이동',
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: '워크스페이스를 찾을 수 없습니다',
workspace_new_worktree_conversation: 'worktree에서 새 대화',
workspace_new_worktree_conversation_meta: '이 워크스페이스용 격리된 git worktree를 만듭니다.',
workspace_worktree_created: 'worktree 대화가 생성되었습니다',
workspace_worktree_failed: 'worktree 생성 실패: ',
session_worktree_badge: 'Worktree',
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_goal: '지속 목표를 설정하거나 확인',
goal_evaluating_progress: 'Evaluating goal progress…',
goal_working_toward: 'Working toward goal…',
goal_continuing_toast: 'Continuing toward goal…',
goal_status_none: 'No active goal. Set one with /goal <text>.',
goal_status_active: (turns, max_turns, goal) => `⊙ Goal (active, ${turns}/${max_turns} turns): ${goal}`,
goal_status_paused: (turns, max_turns, reason, goal) => `⏸ Goal (paused, ${turns}/${max_turns}${reason ? `, ${reason}` : ''}): ${goal}`,
goal_status_done: (turns, max_turns, goal) => `✓ Goal done (${turns}/${max_turns}): ${goal}`,
goal_set: (turns, goal) => `⊙ Goal set (${turns}-turn budget): ${goal}`,
goal_paused: (goal) => `⏸ Goal paused: ${goal}`,
goal_resumed: (goal) => `▶ Goal resumed: ${goal}`,
goal_cleared: 'Goal cleared.',
goal_no_goal: 'No active goal.',
goal_achieved: (reason) => `✓ Goal achieved: ${reason}`,
goal_paused_budget_exhausted: (turns, max_turns) => `⏸ Goal paused — ${turns}/${max_turns} turns used. Use /goal resume to keep going, or /goal clear to stop.`,
goal_continuing: (turns, max_turns, reason) => `↻ Continuing toward goal (${turns}/${max_turns}): ${reason}`,
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_provider: '제공자',
status_workspace: '워크스페이스',
status_personality: '페르소나',
status_messages: '메시지',
status_agent_running: '에이전트 실행 중',
status_profile: '프로필',
status_hermes_home: 'Hermes 홈',
status_started: '시작 시간',
status_tokens: '토큰',
status_updated: '업데이트됨',
status_ephemeral: '임시 스냅샷 — 대화 기록에 저장되지 않습니다.',
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.',
workspace_show_hidden_files: '숨김 파일 표시',
workspace_show_hidden_files_desc: 'Include .DS_Store, .git, node_modules, and other hidden / system files in the file tree.',
workspace_hidden_files_visible: 'hidden visible',
workspace_hidden_files_visible_title: 'Hidden files are visible — click for options',
workspace_options: 'Workspace options',
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: '표시 실패: ',
copy_file_path: '파일 경로 복사',
path_copied: '파일 경로가 클립보드에 복사되었습니다',
path_copy_failed: '경로 복사 실패: ',
session_rename: '대화 이름 변경',
session_rename_desc: '이 대화의 제목 편집',
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: ',
upload_too_large: (maxMb, fileMb) => `File is too large (${fileMb} MB). Maximum upload size is ${maxMb} MB.`,
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: '활성화하면 새 세션마다 워크스페이스/파일 브라우저 패널이 자동으로 열립니다. 언제든지 수동으로 닫을 수 있습니다.',
settings_label_session_jump_buttons: '세션 이동 버튼 표시',
settings_desc_session_jump_buttons: '긴 세션 기록을 읽을 때 떠 있는 시작 및 끝 버튼을 표시합니다.',
settings_label_session_endless_scroll: '위로 스크롤할 때 이전 메시지 불러오기',
settings_desc_session_endless_scroll: '활성화하면 위로 스크롤할 때 이전 메시지를 자동으로 불러옵니다. 비활성화하면 이전 메시지 버튼을 사용합니다.',
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_work_queue_hint: 'This is the Hermes Agent work queue. Create or triage a task, assign it, move it to Ready, then let the dispatcher claim it.',
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_status_original_hint: 'Actual status: {0}. This dialog only supports Triage/Todo/Ready edits.',
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_title: '제목',
kanban_description: '설명',
kanban_description_placeholder: '선택 — 해야 할 일, 수락 기준, 링크',
kanban_status: '상태',
kanban_assignee: '담당자',
kanban_assignee_placeholder: '선택 — 비워두면 누구나 가능',
kanban_tenant: '테넌트',
kanban_tenant_placeholder: '선택 — 프로젝트 또는 팀 슬러그',
kanban_priority: '우선순위',
kanban_priority_hint: '높은 숫자가 먼저 실행됩니다. 기본값: 0.',
kanban_title_required: '제목은 필수입니다.',
kanban_edit_task: '작업 편집',
kanban_run_dispatcher: '디스패처 실행',
kanban_run_dispatcher_confirm: '이 보드의 Ready 작업을 클레임하고 워커 서브프로세스를 생성합니다(클릭당 최대 8개). 계속할까요?',
kanban_assignee_profiles_label: 'Hermes 프로필',
kanban_assignee_other_label: '기타 (CLI 레인 / 삭제된 프로필)',
kanban_assignee_unassigned: '— 미할당 (자동 실행되지 않음) —',
kanban_ready_needs_assignee: '«미할당» + «Ready»를 선택했습니다. 디스패처는 이 작업을 건너뜁니다. 확인하려면 다시 제출하거나 프로필을 선택하세요.',
kanban_dispatch_preview_prefix: '미리보기:',
kanban_dispatch_run_prefix: '디스패치됨:',
kanban_dispatch_spawned: '생성됨',
kanban_dispatch_promoted: '승격됨',
kanban_dispatch_reclaimed: '재요청됨',
kanban_dispatch_skipped_unassigned: '건너뜀 (담당자 없음)',
kanban_dispatch_skipped_nonspawnable: '건너뜀 (알 수 없는 프로필)',
kanban_dispatch_auto_blocked: '자동 차단',
kanban_dispatch_timed_out: '시간 초과',
kanban_dispatch_crashed: '충돌',
kanban_new_task: 'New task',
kanban_add_comment: 'Add comment',
kanban_only_mine: 'Only mine',
kanban_bulk_action: 'Bulk action',
kanban_nudge_dispatcher: 'Preview 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_complete: 'complete',
kanban_card_archive: 'archive',
kanban_unassigned: 'unassigned',
kanban_status_archived: 'Archived',
tab_todos: 'Todos',
tab_insights: '통계',
tab_dashboard: 'Hermes 대시보드',
dashboard_loopback_warning: '대시보드는 서버에서 loopback 전용입니다. 서버 자체에서 접속하거나 --host 0.0.0.0(안전하지 않음)으로 다시 시작하세요.',
tab_logs: 'Logs',
tab_settings: '설정',
logs_title: 'Logs', // TODO: translate
logs_file: 'File', // TODO: translate
logs_tail: 'Tail', // TODO: translate
logs_auto_refresh: 'Auto-refresh (5s)', // TODO: translate
logs_wrap: 'Wrap lines', // TODO: translate
logs_copy_all: 'Copy all', // TODO: translate
logs_empty: 'No log lines yet.', // TODO: translate
logs_loading: 'Loading logs…', // TODO: translate
logs_load_failed: 'Logs failed to load', // TODO: translate
logs_status_idle: 'Choose a log file to view recent lines.', // TODO: translate
logs_no_mtime: 'not written yet', // TODO: translate
logs_truncated_hint: 'Showing the tail of a large log file; older bytes were skipped to keep memory bounded.', // TODO: translate
logs_copied: 'Logs copied', // TODO: translate
logs_severity: 'Severity', // TODO: translate
logs_severity_all: 'All', // TODO: translate
logs_severity_errors: 'Errors', // TODO: translate
logs_severity_warnings: 'Warnings+', // TODO: translate
logs_filter_active: 'shown (filter active)', // TODO: translate
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'}`,
session_meta_segments: (n) => `${n} segment${n === 1 ? '' : 's'}`,
session_lineage_segment_untitled: '제목 없는 세그먼트',
session_lineage_segment_open: '계보 세그먼트 열기',
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',
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: "Use 'every 1h' or a cron expression for recurring jobs. Bare durations like '30m' run once.",
cron_schedule_once_warning: "Duration forms like '30m' run once and are removed after running. Use 'every 30m' to keep a recurring job.",
cron_prompt_label: 'Prompt',
cron_deliver_label: 'Deliver output to',
cron_deliver_local: 'Local (save output only)',
cron_profile_label: 'Profile',
cron_profile_server_default: 'server default',
cron_profile_server_default_hint: 'Uses the WebUI server default profile at run time. Existing jobs without a profile keep this legacy behavior.',
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_daily_tokens: '일별 토큰',
insights_model_name: '모델',
insights_model_sessions: '세션',
insights_model_tokens: '토큰',
insights_model_cost: '비용',
insights_model_share: '비율',
insights_no_usage_data: '아직 사용 데이터가 없습니다',
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) return;
if (el.hasAttribute('data-tooltip')) {
// Custom CSS tooltip is in use (#1775) — sync it and explicitly clear
// the native `title` attribute so the slow ~1.5s browser tooltip never
// co-fires alongside the fast custom tooltip.
el.setAttribute('data-tooltip', val);
if (el.hasAttribute('title')) el.removeAttribute('title');
} else {
// Element opted out of custom tooltips — fall back to the native title.
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;
});
document.querySelectorAll('[data-i18n-aria-label]').forEach(el => {
const key = el.getAttribute('data-i18n-aria-label');
const val = t(key);
if (val && val !== key) el.setAttribute('aria-label', val);
});
if (typeof syncAppTitlebar === 'function') syncAppTitlebar();
}
// Apply saved locale immediately so there's no flash of English on reload.
loadLocale();