const translations: Record<string, Record<string, string>> = {
  zh: {
    console: '控制台',
    nav_chat: '对话',
    nav_manage: '管理',
    nav_monitor: '监控',
    menu_chat: '对话',
    menu_config: '配置',
    menu_skills: '技能',
    menu_memory: '记忆',
    menu_channels: '通道',
    menu_tasks: '定时',
    menu_logs: '日志',
    menu_models: '模型',
    menu_knowledge: '知识',
    menu_settings: '设置',
    // knowledge
    knowledge_title: '知识库',
    knowledge_desc: '浏览和探索你的知识库',
    knowledge_tab_docs: '文档',
    knowledge_tab_graph: '图谱',
    knowledge_search: '搜索文档...',
    knowledge_stats: '{pages} 篇 · {size}',
    knowledge_select_hint: '从左侧选择一个文档查看',
    knowledge_empty: '知识库还是空的',
    knowledge_empty_guide: '在对话中发送文档、链接或主题给 Agent，它会自动整理到你的知识库中',
    knowledge_go_chat: '开始对话',
    knowledge_loading: '加载知识库中...',
    knowledge_graph_empty: '暂无关联图谱',
    knowledge_disabled: '知识库未启用',
    knowledge_doc_load_error: '文档加载失败',
    // knowledge management
    knowledge_new: '新建',
    knowledge_new_category: '新建分类',
    knowledge_new_document: '新建文档',
    knowledge_import_documents: '导入文档',
    knowledge_working: '处理中...',
    knowledge_importing: '正在导入...',
    knowledge_request_failed: '请求失败，请稍后重试',
    knowledge_import_failed: '导入失败',
    knowledge_category_created: '分类已创建',
    knowledge_document_created: '文档已创建',
    knowledge_dialog_confirm: '确定',
    knowledge_dialog_cancel: '取消',
    knowledge_field_required: '此项不能为空',
    knowledge_category_label: '分类路径',
    knowledge_category_hint: '支持嵌套路径，例如 research/ai',
    knowledge_category_subtitle: '分类会创建为 knowledge/ 下的目录',
    knowledge_need_category: '请先创建分类',
    knowledge_destination: '目标分类',
    knowledge_doc_choose_category: '先选择分类，然后输入文件名',
    knowledge_doc_save_to: '保存到 {category}',
    knowledge_doc_filename: '文件名',
    knowledge_doc_filename_required: '文件名不能为空',
    knowledge_doc_must_md: '新建文档仅支持 .md 文件名',
    knowledge_doc_content: 'Markdown 内容',
    knowledge_doc_content_required: '内容不能为空',
    knowledge_doc_content_too_large: '内容不能超过 10MB',
    knowledge_doc_insert_template: '插入模板',
    knowledge_import_selected: '已选择 {count} 个文件',
    knowledge_import_hint: '支持 Markdown 和 TXT，TXT 会转成 Markdown 文档',
    knowledge_import_need_category: '请先创建一个分类',
    knowledge_import_choose_files: '请选择 .md 或 .txt 文件',
    knowledge_import_too_many: '一次最多导入 {max} 个文件',
    knowledge_import_file_too_large: '{name} 超过 10MB',
    knowledge_import_total_too_large: '单次导入总大小不能超过 200MB',
    knowledge_import_result: '导入 {imported} 个，跳过 {skipped} 个，失败 {failed} 个',
    knowledge_drop_hint: '拖放 .md / .txt 文件到此导入',
    nav_expand: '展开侧栏',
    nav_collapse: '收起侧栏',
    update_available: '发现新版本',
    update_download: '下载更新',
    update_downloading: '正在下载',
    update_restart: '重启以更新',
    update_later: '稍后',
    update_latest: '已是最新版本',
    // onboarding
    onboarding_welcome_title: '欢迎使用 CowAgent',
    onboarding_welcome_desc: '你的私人超级 AI 助手。几步设置，即可开始对话。',
    onboarding_lang_label: '界面语言',
    onboarding_model_title: '配置对话模型',
    onboarding_model_desc: '选择模型厂商并填入 API Key，即可开始使用。',
    onboarding_provider: '模型厂商',
    onboarding_select_provider: '选择厂商',
    onboarding_apikey: 'API Key',
    onboarding_apikey_placeholder: '输入 API 密钥',
    onboarding_key_guide: '没有秘钥？前往创建',
    onboarding_apibase: 'API 地址（可选）',
    onboarding_model: '模型',
    onboarding_select_model: '选择模型',
    onboarding_done_title: '一切就绪',
    onboarding_done_desc: '配置完成，开始你的第一次对话吧。',
    onboarding_next: '下一步',
    onboarding_back: '上一步',
    onboarding_skip: '跳过',
    onboarding_finish: '开始对话',
    onboarding_step: '第 {n} / {total} 步',
    onboarding_saving: '保存中...',
    onboarding_save_failed: '保存失败，请检查后重试',
    sessions_title: '会话',
    session_new: '新对话',
    session_rename: '重命名',
    session_delete: '删除',
    session_empty: '暂无会话',
    session_today: '今天',
    session_yesterday: '昨天',
    session_earlier: '更早',
    msg_copy: '复制',
    msg_copied: '已复制',
    msg_regenerate: '重新生成',
    msg_edit: '编辑',
    msg_delete: '删除',
    msg_cancelled: '已中止',
    msg_self_learned: '自主学习',
    msg_stop: '停止',
    chat_clear_context: '清除上下文',
    chat_load_earlier: '加载更早的消息',
    chat_send: '发送',
    chat_attach: '添加附件',
    slash_hint: '输入 / 查看命令',
    chat_welcome: '有什么可以帮你的？',
    chat_empty_hint: '发送一条消息开始对话',
    welcome_subtitle: '我可以帮你解答问题、管理你的电脑、创建并执行技能，\n还能通过长期记忆不断成长。',
    example_sys_title: '系统管理',
    example_sys_text: '帮我查看工作空间里有哪些文件',
    example_task_title: '技能系统',
    example_task_text: '查看所有支持的工具和技能',
    example_code_title: '编程助手',
    example_code_text: '帮我编写一个Python爬虫脚本',
    input_placeholder: '输入消息...',
    config_title: '配置管理',
    config_desc: '管理模型和 Agent 配置',
    config_model: '模型配置',
    config_agent: 'Agent 配置',
    config_provider: '模型厂商',
    config_model_name: '模型',
    config_custom_model_hint: '输入自定义模型名称',
    config_save: '保存',
    config_saved: '已保存',
    config_save_error: '保存失败',
    config_custom_option: '自定义',
    config_max_tokens: '最大上下文 Token',
    config_max_turns: '最大记忆轮次',
    config_max_steps: '最大执行步数',
    config_max_tokens_hint: '对话中 Agent 能输入的最大 Token 长度，超过后会智能压缩处理',
    config_max_turns_hint: '一问一答为一轮，超过后会智能压缩处理',
    config_max_steps_hint: '单次对话中 Agent 最多调用工具的次数',
    config_thinking: '深度思考',
    config_thinking_hint: '是否启用深度思考模式',
    config_evolution: '自主进化',
    config_evolution_hint: '会话空闲后自动复盘，沉淀记忆、优化技能、处理未完成事项',
    config_security: '安全设置',
    config_password: '访问密码',
    config_password_hint: '留空则不启用密码保护',
    config_password_placeholder: '留空表示不设密码',
    config_password_saved: '密码已更新，请重新登录',
    config_password_cleared: '密码已清除',
    config_language: '语言',
    config_language_hint: '界面与回复语言',
    config_credentials_link: 'API Key 与接口地址请在「模型配置」中设置',
    config_goto_models: '前往配置',
    config_provider_unconfigured: '未配置',
    config_provider_unconfigured_hint: '该厂商尚未配置 API Key，请先前往配置',
    config_cancel: '取消',
    // settings tabs
    settings_tab_basic: '基础配置',
    settings_tab_models: '模型配置',
    // models tab
    models_vendors: '厂商凭据',
    models_vendors_sub: '一处配置，多个模型能力共享',
    models_configured: '已配置',
    models_no_vendor: '尚未配置任何厂商',
    models_add_vendor: '添加厂商',
    models_custom_vendor: '自定义',
    models_add_custom: '添加自定义厂商',
    models_add_custom_hint: '接口需遵循 OpenAI API 协议',
    models_edit_custom: '编辑自定义厂商',
    models_custom_name: '名称',
    models_custom_base_hint: '接口需遵循 OpenAI API 协议',
    models_clear: '清除凭据',
    models_delete: '删除',
    models_clear_confirm: '确认清除该厂商的 API Key 与 Base URL 吗？相关能力将不再可用。',
    models_delete_confirm: '确定删除该自定义厂商吗？此操作无法撤销。',
    models_provider: '厂商',
    models_model: '模型',
    models_voice: '音色',
    models_select_provider: '待选择',
    models_select_model: '请选择模型',
    models_select_voice: '请选择音色',
    models_no_options: '暂无可选项',
    models_auto: '自动',
    models_asr_auto: '自动（跟随主模型）',
    models_disabled: '不启用',
    models_fallback: '兜底',
    models_cap_chat: '主模型',
    models_cap_chat_sub: '用于基础对话和 Agent 推理',
    models_cap_vision: '图像理解',
    models_cap_vision_sub: '识别图片内容，用于图像识别工具',
    models_cap_image: '图像生成',
    models_cap_image_sub: '生成图片，用于图像生成技能',
    models_cap_asr: '语音识别',
    models_cap_asr_sub: '语音转文字',
    models_cap_tts: '语音合成',
    models_cap_tts_sub: '文字转语音',
    models_cap_embedding: '向量',
    models_cap_embedding_sub: '用于记忆与知识的向量化检索',
    models_cap_search: '联网搜索',
    models_cap_search_sub: '实时网页检索能力，用于搜索工具',
    models_tts_reply_mode: '语音回复模式',
    models_tts_reply_mode_hint: '决定何时以语音回复用户',
    models_tts_mode_off: '关闭',
    models_tts_mode_if_voice: '仅当用户发语音时',
    models_tts_mode_always: '始终语音回复',
    models_embedding_dim: '维度',
    models_embedding_rebuild_hint: '切换向量模型后，已有索引将失效，需要重建',
    models_search_strategy: '策略',
    models_search_auto: '自动',
    models_search_fixed: '指定',
    models_search_provider: '搜索厂商',
    models_search_bocha_key: '配置博查 API Key',
    models_search_bocha_hint: '前往博查开放平台创建 API Key',
    skills_title: '技能管理',
    skills_desc: '查看、启用或禁用 Agent 工具和技能',
    skills_hub_btn: '探索技能广场',
    tools_section_title: '内置工具',
    skills_section_title: '技能',
    tools_loading: '加载工具中...',
    skills_loading: '加载技能中...',
    skills_loading_desc: '技能将在加载后显示',
    skill_enabled: '已启用',
    skill_disabled: '已禁用',
    tools_empty: '暂无内置工具',
    skills_empty: '暂无技能',
    memory_title: '记忆管理',
    memory_desc: '查看 Agent 记忆文件和内容',
    memory_tab_files: '记忆文件',
    memory_tab_dreams: '自主进化',
    memory_loading: '加载记忆文件中...',
    memory_loading_desc: '记忆文件将在加载后显示',
    memory_col_name: '文件名',
    memory_col_type: '类型',
    memory_col_size: '大小',
    memory_col_updated: '更新时间',
    memory_back: '返回列表',
    memory_empty_files: '暂无记忆文件',
    memory_empty_evolution: '暂无进化记录',
    memory_type_global: '全局',
    memory_type_daily: '每日',
    memory_type_evolution: '进化',
    memory_type_dream: '梦境',
    memory_doc_load_error: '内容加载失败',
    memory_prev: '上一页',
    memory_next: '下一页',
    channels_title: '通道管理',
    channels_desc: '查看和管理消息通道',
    channels_add: '添加通道',
    channels_connected: '已连接',
    channels_disconnected: '未连接',
    channels_connect: '连接',
    channels_disconnect: '断开',
    channels_save: '保存',
    channels_loading: '加载通道中...',
    channels_connected_section: '已连接',
    channels_available_section: '可添加',
    channels_empty_connected: '暂无已连接的通道',
    channels_qr_hint: '该通道通过扫码登录，请前往 Web 控制台完成扫码连接',
    channels_save_ok: '已保存',
    channels_save_error: '保存失败',
    channels_connect_error: '连接失败',
    channels_scan_login: '扫码登录',
    channels_scan_register: '扫码注册',
    weixin_scan_title: '微信扫码登录',
    weixin_scan_desc: '使用微信扫描下方二维码登录',
    weixin_scan_loading: '正在获取二维码...',
    weixin_scan_waiting: '等待扫码',
    weixin_scan_scanned: '已扫描，请在手机上确认',
    weixin_scan_success: '登录成功',
    weixin_scan_expired: '二维码已过期，正在刷新...',
    weixin_scan_fail: '获取二维码失败',
    weixin_qr_tip: '请使用登录的微信扫码',
    feishu_scan_title: '飞书扫码注册',
    feishu_scan_desc: '扫码后将自动创建并连接飞书机器人',
    feishu_scan_loading: '正在生成二维码...',
    feishu_scan_waiting: '请使用飞书扫码授权',
    feishu_scan_tip: '扫码后在飞书中确认授权',
    feishu_scan_open_link: '打开授权链接',
    feishu_scan_success: '注册成功',
    feishu_scan_expired: '二维码已过期',
    feishu_scan_denied: '授权被拒绝',
    feishu_scan_fail: '注册失败',
    feishu_scan_retry: '重试',
    tasks_title: '定时任务',
    tasks_desc: '查看和管理定时任务',
    tasks_active: '运行中',
    tasks_paused: '已暂停',
    tasks_empty: '暂无定时任务',
    tasks_empty_guide: '在对话中告诉 Agent「每天 9 点提醒我…」即可创建定时任务',
    tasks_go_chat: '去对话创建',
    tasks_next_run: '下次执行',
    tasks_loading: '加载定时任务中...',
    task_edit_title: '编辑任务',
    task_name: '名称',
    task_enabled: '启用',
    task_schedule_type: '调度类型',
    task_type_cron: 'Cron 表达式',
    task_type_interval: '固定间隔',
    task_type_once: '单次执行',
    task_cron_expr: 'Cron 表达式',
    task_cron_hint: '如 0 9 * * * 表示每天 9 点',
    task_interval_seconds: '间隔（秒）',
    task_once_time: '执行时间',
    task_action_type: '动作类型',
    task_action_send: '发送消息',
    task_action_agent: 'Agent 任务',
    task_message_content: '消息内容',
    task_task_description: '任务描述',
    task_channel: '通道',
    task_receiver: '接收者',
    task_channel_locked: '通道与接收者创建后不可修改',
    task_save: '保存',
    task_cancel: '取消',
    task_delete: '删除',
    task_delete_confirm: '确定删除该任务吗？此操作不可撤销。',
    task_save_error: '保存失败',
    logs_title: '日志',
    logs_desc: '实时日志输出 (run.log)',
    logs_live: '实时',
    logs_connecting: '日志流将在连接后显示...',
    status_starting: '正在启动 CowAgent...',
    status_starting_desc: '正在初始化客户端，请稍候',
    status_error: '初始化失败',
    status_error_desc: '客户端初始化失败，请重试',
    status_retry: '重试',
    // slash command descriptions
    slash_menu_title: '命令',
    slash_new: '新建对话',
    slash_clear: '清除对话上下文',
    slash_help: '显示命令帮助',
    slash_status: '查看运行状态',
    slash_context: '查看对话上下文',
    slash_skill_list: '查看已安装技能',
    slash_skill_search: '搜索技能',
    slash_skill_install: '安装技能 (名称或 GitHub URL)',
    slash_memory_dream: '手动触发记忆蒸馏 (可指定天数, 默认3)',
    slash_knowledge: '查看知识库统计',
    slash_knowledge_list: '查看知识库文件树',
    slash_config: '查看当前配置',
    slash_cancel: '中止当前正在运行的 Agent 任务',
    slash_logs: '查看最近日志',
    slash_version: '查看版本',
  },
  en: {
    console: 'Console',
    nav_chat: 'Chat',
    nav_manage: 'Management',
    nav_monitor: 'Monitor',
    menu_chat: 'Chat',
    menu_config: 'Config',
    menu_skills: 'Skills',
    menu_memory: 'Memory',
    menu_channels: 'Channels',
    menu_tasks: 'Tasks',
    menu_logs: 'Logs',
    menu_models: 'Models',
    menu_knowledge: 'Knowledge',
    // knowledge
    knowledge_title: 'Knowledge Base',
    knowledge_desc: 'Browse and explore your knowledge base',
    knowledge_tab_docs: 'Documents',
    knowledge_tab_graph: 'Graph',
    knowledge_search: 'Search documents...',
    knowledge_stats: '{pages} pages · {size}',
    knowledge_select_hint: 'Select a document to view',
    knowledge_empty: 'Your knowledge base is empty',
    knowledge_empty_guide: 'Send documents, links or topics to the agent in chat — it will organize them into your knowledge base',
    knowledge_go_chat: 'Start chatting',
    knowledge_loading: 'Loading knowledge base...',
    knowledge_graph_empty: 'No graph available',
    knowledge_disabled: 'Knowledge base is disabled',
    knowledge_doc_load_error: 'Failed to load document',
    // knowledge management
    knowledge_new: 'New',
    knowledge_new_category: 'New category',
    knowledge_new_document: 'New document',
    knowledge_import_documents: 'Import documents',
    knowledge_working: 'Working...',
    knowledge_importing: 'Importing...',
    knowledge_request_failed: 'Request failed, please try again',
    knowledge_import_failed: 'Import failed',
    knowledge_category_created: 'Category created',
    knowledge_document_created: 'Document created',
    knowledge_dialog_confirm: 'Confirm',
    knowledge_dialog_cancel: 'Cancel',
    knowledge_field_required: 'This field is required',
    knowledge_category_label: 'Category path',
    knowledge_category_hint: 'Nested paths are supported, e.g. research/ai',
    knowledge_category_subtitle: 'Creates a directory under knowledge/',
    knowledge_need_category: 'Create a category first',
    knowledge_destination: 'Destination category',
    knowledge_doc_choose_category: 'Choose a category, then enter a filename',
    knowledge_doc_save_to: 'Save to {category}',
    knowledge_doc_filename: 'Filename',
    knowledge_doc_filename_required: 'Filename is required',
    knowledge_doc_must_md: 'New documents must be .md files',
    knowledge_doc_content: 'Markdown content',
    knowledge_doc_content_required: 'Content is required',
    knowledge_doc_content_too_large: 'Content cannot exceed 10MB',
    knowledge_doc_insert_template: 'Insert template',
    knowledge_import_selected: '{count} file(s) selected',
    knowledge_import_hint: 'Markdown and TXT are supported. TXT is converted to Markdown.',
    knowledge_import_need_category: 'Create a category first',
    knowledge_import_choose_files: 'Choose .md or .txt files',
    knowledge_import_too_many: 'Import at most {max} files at a time',
    knowledge_import_file_too_large: '{name} exceeds 10MB',
    knowledge_import_total_too_large: 'Total import size cannot exceed 200MB',
    knowledge_import_result: '{imported} imported · {skipped} skipped · {failed} failed',
    knowledge_drop_hint: 'Drop .md / .txt files here to import',
    menu_settings: 'Settings',
    nav_expand: 'Expand sidebar',
    nav_collapse: 'Collapse sidebar',
    update_available: 'New version available',
    update_download: 'Download update',
    update_downloading: 'Downloading',
    update_restart: 'Restart to update',
    update_later: 'Later',
    update_latest: 'You are up to date',
    // onboarding
    onboarding_welcome_title: 'Welcome to CowAgent',
    onboarding_welcome_desc: 'Your personal super AI assistant. A few quick steps and you are ready to chat.',
    onboarding_lang_label: 'Language',
    onboarding_model_title: 'Set up your chat model',
    onboarding_model_desc: 'Pick a provider and paste its API key to get started.',
    onboarding_provider: 'Provider',
    onboarding_select_provider: 'Select a provider',
    onboarding_apikey: 'API Key',
    onboarding_apikey_placeholder: 'Enter your API key',
    onboarding_key_guide: 'No key yet? Create one',
    onboarding_apibase: 'API base (optional)',
    onboarding_model: 'Model',
    onboarding_select_model: 'Select a model',
    onboarding_done_title: 'All set',
    onboarding_done_desc: 'Setup complete. Start your first conversation.',
    onboarding_next: 'Next',
    onboarding_back: 'Back',
    onboarding_skip: 'Skip',
    onboarding_finish: 'Start chatting',
    onboarding_step: 'Step {n} of {total}',
    onboarding_saving: 'Saving...',
    onboarding_save_failed: 'Save failed, please check and retry',
    sessions_title: 'Chats',
    session_new: 'New chat',
    session_rename: 'Rename',
    session_delete: 'Delete',
    session_empty: 'No conversations yet',
    session_today: 'Today',
    session_yesterday: 'Yesterday',
    session_earlier: 'Earlier',
    msg_copy: 'Copy',
    msg_copied: 'Copied',
    msg_regenerate: 'Regenerate',
    msg_edit: 'Edit',
    msg_delete: 'Delete',
    msg_cancelled: 'Cancelled',
    msg_self_learned: 'Self-learned',
    msg_stop: 'Stop',
    chat_clear_context: 'Clear context',
    chat_load_earlier: 'Load earlier messages',
    chat_send: 'Send',
    chat_attach: 'Attach file',
    slash_hint: 'Type / for commands',
    chat_welcome: 'How can I help you?',
    chat_empty_hint: 'Send a message to start the conversation',
    welcome_subtitle: 'I can help you answer questions, manage your computer, create and execute skills,\nand keep growing through long-term memory.',
    example_sys_title: 'System',
    example_sys_text: 'Show me the files in the workspace',
    example_task_title: 'Skills',
    example_task_text: 'Show current tools and skills',
    example_code_title: 'Coding',
    example_code_text: 'Write a Python web scraper script',
    input_placeholder: 'Type a message...',
    config_title: 'Configuration',
    config_desc: 'Manage model and agent settings',
    config_model: 'Model Configuration',
    config_agent: 'Agent Configuration',
    config_provider: 'Provider',
    config_model_name: 'Model',
    config_custom_model_hint: 'Enter custom model name',
    config_save: 'Save',
    config_saved: 'Saved',
    config_save_error: 'Save failed',
    config_custom_option: 'Custom',
    config_max_tokens_hint: 'Max token length the Agent can take in; longer context is compressed automatically',
    config_max_turns_hint: 'One question and answer is a turn; older turns are compressed automatically',
    config_max_steps_hint: 'Max tool calls the Agent can make in one turn',
    config_thinking: 'Deep Thinking',
    config_thinking_hint: 'Whether to enable deep thinking mode',
    config_evolution: 'Self-Evolution',
    config_evolution_hint: 'Review automatically when idle: consolidate memory, refine skills, finish pending tasks',
    config_security: 'Security',
    config_password: 'Access Password',
    config_password_hint: 'Leave empty to disable password protection',
    config_password_placeholder: 'Leave empty for no password',
    config_password_saved: 'Password updated, please log in again',
    config_password_cleared: 'Password cleared',
    config_language: 'Language',
    config_language_hint: 'Interface and reply language',
    config_credentials_link: 'Set API key and endpoint in "Models"',
    config_goto_models: 'Configure',
    config_provider_unconfigured: 'Not configured',
    config_provider_unconfigured_hint: 'This provider has no API key yet — configure it first',
    config_cancel: 'Cancel',
    // settings tabs
    settings_tab_basic: 'Basic',
    settings_tab_models: 'Models',
    // models tab
    models_vendors: 'Provider Credentials',
    models_vendors_sub: 'Configured once, shared by multiple model capabilities',
    models_configured: 'configured',
    models_no_vendor: 'No provider configured yet',
    models_add_vendor: 'Add Provider',
    models_custom_vendor: 'Custom',
    models_add_custom: 'Add custom provider',
    models_add_custom_hint: 'Endpoint must follow the OpenAI API protocol',
    models_edit_custom: 'Edit custom provider',
    models_custom_name: 'Name',
    models_custom_base_hint: 'Endpoint must follow the OpenAI API protocol',
    models_clear: 'Clear credentials',
    models_delete: 'Delete',
    models_clear_confirm: 'Clear the API key and base URL for this provider? Related capabilities will stop working.',
    models_delete_confirm: 'Delete this custom provider? This cannot be undone.',
    models_provider: 'Provider',
    models_model: 'Model',
    models_voice: 'Voice',
    models_select_provider: 'Select',
    models_select_model: 'Select a model',
    models_select_voice: 'Select a voice',
    models_no_options: 'No options',
    models_auto: 'Auto',
    models_asr_auto: 'Auto (follow main model)',
    models_disabled: 'Disabled',
    models_fallback: 'Fallback',
    models_cap_chat: 'Main Model',
    models_cap_chat_sub: 'Used for basic chat and agent reasoning',
    models_cap_vision: 'Image Understanding',
    models_cap_vision_sub: 'Recognizes image content, used by image recognition tools',
    models_cap_image: 'Image Generation',
    models_cap_image_sub: 'Generates images, used by image generation skills',
    models_cap_asr: 'Speech Recognition',
    models_cap_asr_sub: 'Voice to text',
    models_cap_tts: 'Speech Synthesis',
    models_cap_tts_sub: 'Text to voice',
    models_cap_embedding: 'Embedding',
    models_cap_embedding_sub: 'Used for vectorized retrieval of memory and knowledge',
    models_cap_search: 'Web Search',
    models_cap_search_sub: 'Real-time web retrieval, used by search tools',
    models_tts_reply_mode: 'Voice Reply Mode',
    models_tts_reply_mode_hint: 'When to reply with voice',
    models_tts_mode_off: 'Off',
    models_tts_mode_if_voice: 'Only when user sends voice',
    models_tts_mode_always: 'Always reply with voice',
    models_embedding_dim: 'Dimension',
    models_embedding_rebuild_hint: 'Existing index becomes invalid and must be rebuilt after changing the model',
    models_search_strategy: 'Strategy',
    models_search_auto: 'Auto',
    models_search_fixed: 'Pinned',
    models_search_provider: 'Search provider',
    models_search_bocha_key: 'Configure Bocha API Key',
    models_search_bocha_hint: 'Create a key at the Bocha open platform',
    config_max_tokens: 'Max Context Tokens',
    config_max_turns: 'Max Memory Turns',
    config_max_steps: 'Max Steps',
    skills_title: 'Skills',
    skills_desc: 'View, enable, or disable agent tools and skills',
    skills_hub_btn: 'Skill Hub',
    tools_section_title: 'Built-in Tools',
    skills_section_title: 'Skills',
    tools_loading: 'Loading tools...',
    skills_loading: 'Loading skills...',
    skills_loading_desc: 'Skills will be displayed here after loading',
    skill_enabled: 'Enabled',
    skill_disabled: 'Disabled',
    tools_empty: 'No built-in tools',
    skills_empty: 'No skills found',
    memory_title: 'Memory',
    memory_desc: 'View agent memory files and contents',
    memory_tab_files: 'Memory Files',
    memory_tab_dreams: 'Self-Evolution',
    memory_loading: 'Loading memory files...',
    memory_loading_desc: 'Memory files will be displayed here',
    memory_col_name: 'Filename',
    memory_col_type: 'Type',
    memory_col_size: 'Size',
    memory_col_updated: 'Updated',
    memory_back: 'Back to list',
    memory_empty_files: 'No memory files',
    memory_empty_evolution: 'No evolution records yet',
    memory_type_global: 'Global',
    memory_type_daily: 'Daily',
    memory_type_evolution: 'Evolution',
    memory_type_dream: 'Dream',
    memory_doc_load_error: 'Failed to load content',
    memory_prev: 'Prev',
    memory_next: 'Next',
    channels_title: 'Channels',
    channels_desc: 'View and manage messaging channels',
    channels_add: 'Add channel',
    channels_connected: 'Connected',
    channels_disconnected: 'Disconnected',
    channels_connect: 'Connect',
    channels_disconnect: 'Disconnect',
    channels_save: 'Save',
    channels_loading: 'Loading channels...',
    channels_connected_section: 'Connected',
    channels_available_section: 'Available',
    channels_empty_connected: 'No connected channels yet',
    channels_qr_hint: 'This channel uses QR login — please connect it from the Web console',
    channels_save_ok: 'Saved',
    channels_save_error: 'Failed to save',
    channels_connect_error: 'Failed to connect',
    channels_scan_login: 'QR login',
    channels_scan_register: 'QR register',
    weixin_scan_title: 'WeChat QR Login',
    weixin_scan_desc: 'Scan the QR code below with WeChat to log in',
    weixin_scan_loading: 'Fetching QR code...',
    weixin_scan_waiting: 'Waiting for scan',
    weixin_scan_scanned: 'Scanned, please confirm on your phone',
    weixin_scan_success: 'Logged in',
    weixin_scan_expired: 'QR code expired, refreshing...',
    weixin_scan_fail: 'Failed to fetch QR code',
    weixin_qr_tip: 'Scan with the WeChat account to log in',
    feishu_scan_title: 'Feishu QR Register',
    feishu_scan_desc: 'Scanning will create and connect a Feishu bot automatically',
    feishu_scan_loading: 'Generating QR code...',
    feishu_scan_waiting: 'Scan with Feishu to authorize',
    feishu_scan_tip: 'Confirm the authorization in Feishu after scanning',
    feishu_scan_open_link: 'Open authorization link',
    feishu_scan_success: 'Registered',
    feishu_scan_expired: 'QR code expired',
    feishu_scan_denied: 'Authorization denied',
    feishu_scan_fail: 'Registration failed',
    feishu_scan_retry: 'Retry',
    tasks_title: 'Scheduled Tasks',
    tasks_desc: 'View and manage scheduled tasks',
    tasks_active: 'Active',
    tasks_paused: 'Paused',
    tasks_empty: 'No scheduled tasks',
    tasks_empty_guide: 'Tell the agent "remind me every day at 9am…" in chat to create a scheduled task',
    tasks_go_chat: 'Create in chat',
    tasks_next_run: 'Next run',
    tasks_loading: 'Loading scheduled tasks...',
    task_edit_title: 'Edit Task',
    task_name: 'Name',
    task_enabled: 'Enabled',
    task_schedule_type: 'Schedule type',
    task_type_cron: 'Cron',
    task_type_interval: 'Interval',
    task_type_once: 'Once',
    task_cron_expr: 'Cron expression',
    task_cron_hint: 'e.g. 0 9 * * * runs daily at 9am',
    task_interval_seconds: 'Interval (seconds)',
    task_once_time: 'Run at',
    task_action_type: 'Action type',
    task_action_send: 'Send message',
    task_action_agent: 'Agent task',
    task_message_content: 'Message content',
    task_task_description: 'Task description',
    task_channel: 'Channel',
    task_receiver: 'Receiver',
    task_channel_locked: 'Channel and receiver cannot be changed after creation',
    task_save: 'Save',
    task_cancel: 'Cancel',
    task_delete: 'Delete',
    task_delete_confirm: 'Delete this task? This cannot be undone.',
    task_save_error: 'Failed to save',
    logs_title: 'Logs',
    logs_desc: 'Real-time log output (run.log)',
    logs_live: 'Live',
    logs_connecting: 'Log streaming will connect shortly...',
    status_starting: 'Starting CowAgent...',
    status_starting_desc: 'Initializing the client, please wait',
    status_error: 'Initialization Failed',
    status_error_desc: 'Failed to initialize the client, please retry',
    status_retry: 'Retry',
    // slash command descriptions
    slash_menu_title: 'Commands',
    slash_new: 'New chat',
    slash_clear: 'Clear conversation context',
    slash_help: 'Show command help',
    slash_status: 'Show running status',
    slash_context: 'Show conversation context',
    slash_skill_list: 'List installed skills',
    slash_skill_search: 'Search skills',
    slash_skill_install: 'Install a skill (name or GitHub URL)',
    slash_memory_dream: 'Trigger memory distillation (optional days, default 3)',
    slash_knowledge: 'Show knowledge base stats',
    slash_knowledge_list: 'Show knowledge base file tree',
    slash_config: 'Show current config',
    slash_cancel: 'Abort the running agent task',
    slash_logs: 'Show recent logs',
    slash_version: 'Show version',
  },
}

export type Lang = 'zh' | 'en'

// First-run default: follow the OS language so zh-* systems start in Chinese
// and everyone else in English. Once the user picks a language it's persisted
// in cow_lang and always wins. Falls back to 'en' when the locale is unknown.
function detectDefaultLang(): Lang {
  const locale = (window.electronAPI?.systemLocale || navigator.language || '').toLowerCase()
  return locale.startsWith('zh') ? 'zh' : 'en'
}

const savedLang = localStorage.getItem('cow_lang') as Lang | null
let currentLang: Lang = savedLang === 'zh' || savedLang === 'en' ? savedLang : detectDefaultLang()

export function t(key: string): string {
  return translations[currentLang]?.[key] || translations['en']?.[key] || key
}

export function getLang(): Lang {
  return currentLang
}

export function setLang(lang: Lang) {
  currentLang = lang
  localStorage.setItem('cow_lang', lang)
}

/** Resolve a possibly-localized label ({zh,en} or plain string) for the current language. */
export function localizedLabel(label: string | { zh: string; en: string } | undefined): string {
  if (!label) return ''
  if (typeof label === 'string') return label
  return label[currentLang] || label.en || label.zh || ''
}
