📄 i18n.ts • 32459 bytes
/**
* CmdCode V0.5 国际化系统
* 支持 /EN 和 /CN 命令切换语言
*/
import { readFileSync, writeFileSync, existsSync, mkdirSync } from 'node:fs'
import { join } from 'node:path'
import { homedir } from 'node:os'
// 语言配置文件路径
const CONFIG_DIR = join(homedir(), '.cmdcode')
const CONFIG_FILE = join(CONFIG_DIR, 'lang.json')
// 默认语言(默认英文,避免编码问题)
let currentLang: 'en' | 'zh' = 'en'
// 语言数据
const translations: Record<string, Record<string, string>> = {
en: {},
zh: {}
}
/**
* 初始化语言配置
*/
function initLang(): 'en' | 'zh' {
// 默认使用英文,避免编码问题
currentLang = 'en'
// 尝试读取用户配置
try {
if (existsSync(CONFIG_FILE)) {
const config = JSON.parse(readFileSync(CONFIG_FILE, 'utf-8'))
if (config.lang === 'en' || config.lang === 'zh') {
currentLang = config.lang
}
}
} catch {
// 配置读取失败,使用默认
}
// 加载语言文件
loadTranslations()
return currentLang
}
/**
* 加载翻译数据(内嵌JSON,避免运行时文件读取)
*/
function loadTranslations(): void {
// 英文翻译
translations.en = {
// Banner
'app.title': 'CmdCode v0.5.0',
'app.subtitle': 'Coding has never been so natural',
// Memory system
'memory.init': 'Initializing vector memory system...',
'memory.db_done': 'Database initialized',
'memory.backfill_start': 'Starting backfill (interval: {{interval}} min)',
'memory.ready': 'Memory system ready',
'memory.db_path': 'Database',
'memory.vector_count': 'Vectors',
'memory.backfill_running': 'Backfill already running',
'memory.backfill_stop': 'Backfill stopped',
'memory.backfill_process': 'Processing {{count}} messages...',
'memory.backfill_done': 'Backfill done: {{success}} ok, {{failed}} failed',
'memory.disk_count': 'Disk limit: File count reached {{count}}',
// Status panel
'status.user': 'User',
'status.history': 'messages',
'status.storage': 'Storage',
'status.model': 'Model',
'status.online': 'Online',
'status.offline': 'Offline',
'status.latency': 'ms',
// Input hints
'input.prompt': 'Enter prompt to start',
'input.help': '/help for commands',
'input.exit': '/exit to quit',
'input.truncated': 'History truncated',
'input.lines': 'lines',
'input.shortcuts': '[Ctrl+C:Copy Ctrl+X:Cut Ctrl+V:Paste Ctrl+E:Exit]',
'input.buffered': '📋 Task buffered ({size} chars): {preview}',
// Help section
'help.usage': 'Usage',
'help.interactive': 'Interactive mode',
'help.single': 'Single execution',
'help.continue_session': 'Continue last session',
'help.list_sessions': 'List sessions',
'help.options': 'Options',
'help.prompt_single': 'Prompt (single mode)',
'help.continue_last': 'Continue last session',
'help.list_all_sessions': 'List all sessions',
'help.specify_model': 'Specify model',
'help.show_version': 'Show version',
'help.show_help': 'Show help',
'help.interactive_commands': 'Interactive Commands',
'help.cmd_exit': 'Save and exit',
'help.cmd_clear': 'Clear context',
'help.cmd_set': 'Interactive API config',
'help.cmd_set_key': 'Quick API key setup',
'help.cmd_model': 'Switch model',
'help.cmd_pavr': 'Toggle PAVR loop (on/off)',
'help.cmd_card': 'Session list',
'help.cmd_session': 'Session management',
'help.cmd_en': 'Switch to English',
'help.cmd_cn': 'Switch to Chinese',
'help.cmd_help': 'Show help',
'help.env_vars': 'Environment Variables',
'help.env_api_key': 'API key',
'help.env_base_url': 'API base URL',
'help.env_model': 'Model name',
// User auth
'auth.verify': 'Verifying login status...',
'auth.expired': 'Login expired, please login again',
'auth.login': 'Login',
'auth.register': 'Register',
'auth.username': 'Username',
'auth.password': 'Password',
'auth.username_empty': 'Username cannot be empty',
'auth.password_empty': 'Password cannot be empty',
'auth.password_short': 'Password must be at least 6 characters',
'auth.logging_in': 'Logging in...',
'auth.login_success': 'Login successful',
'auth.registering': 'Registering...',
'auth.register_success': 'Registration successful',
'auth.confirm_password': 'Confirm password',
'auth.username_hint': '(letters/numbers/_, 3-32 chars)',
'auth.password_hint': '(at least 6 chars)',
'auth.username_invalid': 'Username: letters, numbers, underscore only, 3-32 chars',
'auth.choose_option': 'Enter 1 or 2',
// Signals
'signal.received': 'Received {{signal}} signal, saving...',
// Misc
'misc.copy': 'Copy',
'misc.cut': 'Cut',
'misc.paste': 'Paste',
'misc.quit': 'Quit',
'misc.lang_switched': 'Language switched to English',
'misc.lang_switched_cn': 'Language switched to Chinese',
// Model selection (cli.ts)
'model.select_title': 'Select AI Model',
'model.custom': 'Custom endpoint',
'model.selected': 'Selected:',
'model.api_key_hint': 'Get API Key:',
'model.api_key_empty': 'API Key cannot be empty',
'model.connect_success': 'Connection successful',
'model.connect_failed': 'Connection test failed:',
'model.network_unstable': 'Network may be unstable, still usable',
'model.custom_title': 'Custom OpenAI-compatible API',
'model.custom_prompt': 'Please enter the following parameters:',
'model.params_empty': 'Model ID, API URL and API Key cannot be empty',
'model.invalid_selection': 'Invalid selection',
'model.snapshot_failed': 'Snapshot restore failed:',
'model.memory_init_failed': 'Vector memory init failed (optional feature)',
'model.snapshot_check_failed': 'Snapshot check failed, starting fresh',
'model.test_failed': 'Connection test failed:',
'model.manage_hint': 'Enter /model to manage your model config',
'model.no_config_exit': 'No model configured, exiting. You can select again next startup.',
'model.saved': 'Saved to your model config',
'model.encrypted_saved': 'Config encrypted and saved',
'model.possible_reasons': 'Possible reasons: Network unstable / API Key expired / Service temporarily unavailable',
'model.manage_hint2': 'Enter /model to change model',
// Sessions (cli.ts)
'session.no_records': 'No session records',
'session.list_title': 'Session List',
'session.messages': 'Messages',
'session.preview': 'Preview',
'session.restored': 'Session restored:',
'session.messages_count': 'messages',
'session.no_restore': 'No sessions to restore, creating new session',
'session.saved': 'Session saved:',
'session.workspace_saved': 'Workspace saved, will auto-restore next login',
'session.save_failed': 'Workspace save failed, but session saved locally',
'session.context_cleared': 'Context cleared',
// Memory status (cli.ts)
'memory.system_title': 'Vector Memory System',
'memory.sessions': 'Sessions',
'memory.messages': 'Messages',
'memory.vectors': 'Vectors',
'memory.backfill_status': 'Backfill:',
'memory.status_running': 'Running',
'memory.status_stopped': 'Stopped',
'memory.usage_hint': 'Usage: /memory <search query>',
'memory.not_initialized': 'Memory system not initialized',
'memory.search_query': 'Search:',
'memory.no_results': 'No relevant memories found',
'memory.found_results': 'Found {{count}} relevant memories:',
'memory.search_failed': 'Search failed:',
'memory.api_config': 'Vector Memory API Config',
'memory.current_status': 'Current status:',
'memory.custom_key': 'Custom key configured',
'memory.using_default': 'Using default key',
'memory.api_url': 'API URL:',
'memory.model_name': 'Model:',
'memory.keep_current': 'No input, keeping current config',
'memory.api_key_encrypted': 'Vector Memory API Key encrypted and saved',
// API setup (cli.ts)
'api.wizard_title': 'API Configuration Wizard',
'api.wizard_hint': 'Please enter each field in order, press Enter to confirm',
'api.url_empty': 'URL cannot be empty, cancelled',
'api.key_empty': 'API Key cannot be empty, cancelled',
'api.model_empty': 'Model cannot be empty, cancelled',
'api.testing': 'Testing connection...',
'api.config_done': 'Configuration complete and applied!',
'api.key_encrypted': 'API Key: Encrypted',
'api.display_name': 'Display:',
'api.connect_failed': 'Connection failed:',
'api.fallback_default': 'Falling back to system default, continuing...',
'api.switched_default': 'Switched to system default model:',
'api.config_saved_hint': 'Your config is encrypted and saved, enter /set again to test',
'api.usage': 'Usage:',
'api.set_interactive': '/set Interactive config (recommended)',
'api.set_quick': '/set <api_key> Quick setup (uses default URL)',
'api.key_stored': 'API Key encrypted and stored',
'api.key_not_saved': 'API Key not saved due to connection test failure',
'api.engine_reinit': 'Engine reinitialized',
// Security warnings (P1 #28)
'security.fallback_warning': 'Encryption using fallback key - not secure in shared environments',
// Model management (cli.ts)
'model.manage_title': 'Model Management',
'model.current': 'Current model:',
'model.your_config': 'Your model config:',
'model.builtin_fast': 'Built-in models (quick add):',
'model.operations': 'Operations:',
'model.op_switch': 'Switch to configured model',
'model.op_add_builtin': 'Add built-in model',
'model.op_custom': 'Custom endpoint',
'model.op_delete': 'Delete model config',
'model.op_cancel': 'Cancel',
'model.switched': 'Model switched',
'model.deleted': 'Deleted',
'model.added_switched': 'Model added and switched',
// Rate limiting (chat.ts)
'ratelimit.switching': 'API rate limited, auto-switching to {{name}}...',
'ratelimit.exhausted': 'All default API keys exhausted!',
'ratelimit.add_own': 'Use /set command to add your own API Key',
'history.truncated': 'History truncated: {{from}} -> {{to}} messages',
// Errors
'error.network': 'Network connection failed:',
'error.check_network': 'Please check network, or enter /model to re-select',
'error.general': 'Error:',
'error.model_hint': 'Enter /model to re-select model provider',
'error.save_vector': 'Failed to store vector:',
'error.vector_search': 'Vector search failed:',
'error.fts_search': 'FTS5 search error:',
'error.embedding': 'Embedding failed:',
'error.embedding_ratelimit': 'Embedding API rate limited, auto-switching to {{name}}...',
'error.429': '429 rate limited, please retry later',
// Vectors loaded
'vector.loaded': 'Loaded {{count}} vectors into memory index',
// 429 handling
'model.key_switch': 'API key rotated to {{name}}',
// Additional session keys
'session.total': 'Total',
'session.updated': 'Updated',
// Keypool
'keypool.no_permission': 'Keypool management is available to admins only.',
'keypool.alternative': 'Tip: Use /set to add your personal API key instead.',
// Keypool management
'keypool.title': 'Key Pool Management',
'keypool.no_keys': 'No keys',
'keypool.add_hint': '/keypool add chat/embed <name> <model> <baseUrl> to add key',
'keypool.remove_hint': '/keypool remove chat/embed <index> to delete, Q to return',
'keypool.chat_added': 'Chat key added',
'keypool.embed_added': 'Embedding key added',
'keypool.details': 'Name / Model / URL',
'keypool.chat_deleted': 'Chat key deleted',
'keypool.embed_deleted': 'Embedding key deleted',
'keypool.not_found': 'Key not found',
'keypool.help_list': 'List all keys',
'keypool.help_add_chat': 'Add Chat key',
'keypool.help_add_embed': 'Add Embedding key',
'keypool.help_del_chat': 'Delete Chat key',
'keypool.help_del_embed': 'Delete Embedding key',
// Session extras
'session.msg_count': 'Messages: ',
// Goodbye
'misc.goodbye': 'Goodbye!',
// Clipboard (askREPL)
'clip.copied': 'Copied to clipboard',
'clip.cut': 'Cut',
// /model hardcoded prompts
'model.op_input_hint': 'Enter number/letter to select [Q] Back',
'model.select_prompt': 'Select model [1-{{max}}] (Q cancel): ',
'model.op_action_hint': 'Enter number/letter to select [Q] Back to main',
'model.select_action': 'Select action (Q cancel): ',
'model.delete_index': 'Delete model index [1-{{max}}]: ',
'model.confirm_delete': 'Delete {{name}}? [y/N]: ',
'model.custom_hint': '(Enter API URL and key manually)',
'model.cancelled': 'Cancelled',
'model.connection_test': 'Connection test:',
'model.testing_connection': 'Testing connection {{vendor}}...',
'model.continue_anyway': 'Continue? [Y/n]: ',
'model.note1': 'Note 1 (optional): ',
'model.note2': 'Note 2 (optional): ',
'model.is_default': '[Default]',
'model.is_current': '[Current]',
// Masterkey
'api.masterkey_hint': '/masterkey <password> Set dedicated encryption key',
// System prompt
'system.custom': 'Custom:',
'system.set_usage': 'Usage: /system <prompt> Set custom system prompt',
'system.cleared': 'System prompt cleared',
'system.set': 'System prompt set:',
// Connection flow
'model.connecting': 'Connecting',
'session.checking_snapshot': 'Checking workspace snapshot...',
// Error messages (single mode)
'error.429_single': '429 rate limited, please retry later',
'error.switch_model_hint': 'Enter /model to switch provider',
'error.network_single': 'Network connection failed:',
'error.check_network_hint': 'Please check network, or /model to re-select',
'error.general_single': 'Error:',
'error.model_hint_single': 'Enter /model to re-select model provider',
'error.model_saved_not_applied': 'Connection failed, config saved but not applied, use /model to retry',
// /system
'system.using_default': 'Using default (sandbox code generation mode)',
'system.usage': 'Usage: /system clear Reset to default prompt',
// /memory
'memory.op_hint': 'Enter /memory <keyword> to search, Enter to return',
// /set mem
'memory.new_key_prompt': 'New Volcano Engine API Key (Enter to skip, Q cancel): ',
// Custom API wizard
'api.op_hint': 'Enter each field in order, Q to cancel anytime',
'api.url_prompt': 'URL (Q cancel): ',
'api.key_prompt': 'API Key (Q cancel): ',
'api.model_prompt': 'Model ID (Q cancel): ',
// /session
'session.read_hint': 'Enter /session read <id> for details, /session cleanup, Enter to return',
'session.commands_hint': 'Commands: /session read <id> | /session delete <id> | /session cleanup',
'session.specify_id': 'Please specify session ID: /session read <id>',
'session.not_found': 'Session not found:',
'session.detail_title': 'Session details:',
'session.detail_count': 'Messages:',
'session.detail_size': 'Size:',
'session.detail_created': 'Created:',
'session.detail_modified': 'Modified:',
'session.detail_content': '=== Session Content ===',
'session.truncated': '... [truncated]',
'session.page_hint': '── Press Enter to continue, Q to quit ──',
'session.back_hint': 'Press Enter to return',
'session.delete_hint': 'Enter /session read <id> for details, /session cleanup, Enter to return',
'session.confirm_delete': 'Delete session {{id}}? [y/N]: ',
'session.deleted': 'Session deleted:',
'session.delete_failed': 'Delete failed or not found:',
'session.cleanup_no_low': 'No low-value sessions to clean',
'session.cleanup_found': 'Found {{count}} low-value sessions:',
'session.cleanup_reason': 'Reason:',
'session.cleanup_confirm': 'Confirm cleanup of {{count}} sessions above? [y/N]: ',
'session.cleanup_done': 'Cleaned {{deleted}} sessions',
'session.cleanup_failed': 'failed',
'session.specify_delete_id': 'Please specify session ID: /session delete <id>',
}
// 中文翻译
translations.zh = {
// Banner
'app.title': 'CmdCode v0.5.0',
'app.subtitle': '编程从未如此自然',
// Memory system
'memory.init': '初始化向量记忆系统...',
'memory.db_done': '数据库初始化完成',
'memory.backfill_start': '启动向量回填任务(间隔: {{interval}} 分钟)',
'memory.ready': '记忆系统就绪',
'memory.db_path': '数据库',
'memory.vector_count': '向量数',
'memory.backfill_running': '回填任务已在运行',
'memory.backfill_stop': '回填任务已停止',
'memory.backfill_process': '开始回填 {{count}} 条消息...',
'memory.backfill_done': '回填完成: 成功 {{success}}, 失败 {{failed}}',
'memory.disk_count': '磁盘限制: 文件数已达上限 {{count}}',
// Status panel
'status.user': '用户',
'status.history': '条历史',
'status.storage': '存储',
'status.model': '模型',
'status.online': '在线',
'status.offline': '离线',
'status.latency': 'ms',
// Input hints
'input.prompt': '输入提示词开始对话',
'input.help': '/help 查看命令',
'input.exit': '/exit 退出',
'input.truncated': '历史已截断',
'input.lines': '行',
'input.shortcuts': '[Ctrl+C:复制 Ctrl+X:剪切 Ctrl+V:粘贴 Ctrl+E:退出]',
'input.buffered': '📋 任务已缓冲({size}字符): {preview}',
// Help section
'help.usage': '用法',
'help.interactive': '交互模式',
'help.single': '单次执行',
'help.continue_session': '继续上次会话',
'help.list_sessions': '列出会话',
'help.options': '选项',
'help.prompt_single': '提示词(单次执行模式)',
'help.continue_last': '继续上次会话',
'help.list_all_sessions': '列出所有会话',
'help.specify_model': '指定模型',
'help.show_version': '显示版本',
'help.show_help': '显示帮助',
'help.interactive_commands': '交互命令',
'help.cmd_exit': '自动保存后退出',
'help.cmd_clear': '清空上下文',
'help.cmd_set': '交互式配置API(推荐)',
'help.cmd_set_key': '快捷设置API Key',
'help.cmd_model': '切换模型',
'help.cmd_pavr': '开关 PAVR 循环 (on/off)',
'help.cmd_card': '会话列表',
'help.cmd_session': '会话管理',
'help.cmd_en': '切换到英文',
'help.cmd_cn': '切换到中文',
'help.cmd_help': '显示帮助',
'help.env_vars': '环境变量',
'help.env_api_key': 'API密钥',
'help.env_base_url': 'API地址',
'help.env_model': '模型名称',
// User auth
'auth.verify': '验证登录状态...',
'auth.expired': '登录已过期, 请重新登录',
'auth.login': '登录',
'auth.register': '注册',
'auth.username': '用户名',
'auth.password': '密码',
'auth.username_empty': '用户名不能为空',
'auth.password_empty': '密码不能为空',
'auth.password_short': '密码至少6位',
'auth.logging_in': '登录中...',
'auth.login_success': '登录成功',
'auth.registering': '注册中...',
'auth.register_success': '注册成功',
'auth.confirm_password': '确认密码',
'auth.username_hint': '(字母/数字/_, 3-32位)',
'auth.password_hint': '(至少6位)',
'auth.username_invalid': '用户名只能包含字母、数字、下划线,3-32位',
'auth.choose_option': '请输入 1 或 2',
// Signals
'signal.received': '收到 {{signal}} 信号,正在保存...',
// Misc
'misc.copy': '复制',
'misc.cut': '剪切',
'misc.paste': '粘贴',
'misc.quit': '退出',
'misc.lang_switched': 'Language switched to English',
'misc.lang_switched_cn': '语言已切换为中文',
// Model selection (cli.ts)
'model.select_title': '选择 AI 模型',
'model.custom': '自定义接入',
'model.selected': '已选择:',
'model.api_key_hint': '获取API Key:',
'model.api_key_empty': 'API Key 不能为空',
'model.connect_success': '连接成功',
'model.connect_failed': '连接测试:',
'model.network_unstable': '网络可能不稳定,仍可尝试使用',
'model.custom_title': '自定义 OpenAI 兼容 API',
'model.custom_prompt': '请输入以下参数:',
'model.params_empty': '模型ID、API地址和API Key不能为空',
'model.invalid_selection': '无效选择',
'model.snapshot_failed': '快照恢复失败:',
'model.memory_init_failed': '向量记忆系统初始化失败(可选功能)',
'model.snapshot_check_failed': '快照检查失败,从头开始',
'model.test_failed': '连接测试失败:',
'model.manage_hint': '输入 /model 管理您的模型配置',
'model.no_config_exit': '未配置模型,退出。下次启动可重新选择。',
'model.saved': '已保存到您的模型配置',
'model.encrypted_saved': '配置已加密存储',
'model.possible_reasons': '可能原因: 网络不稳定 / API Key过期 / 服务暂时不可用',
'model.manage_hint2': '输入 /model 管理模型配置',
// Sessions (cli.ts)
'session.no_records': '暂无会话记录',
'session.list_title': '会话列表',
'session.messages': '消息',
'session.preview': '预览',
'session.restored': '已恢复会话:',
'session.messages_count': '条消息',
'session.no_restore': '没有可恢复的会话,将创建新会话',
'session.saved': '会话已保存:',
'session.workspace_saved': '工作区已保存,下次登录自动恢复',
'session.save_failed': '工作区保存失败,但会话已本地保存',
'session.context_cleared': '上下文已清空',
// Memory status (cli.ts)
'memory.system_title': '向量记忆系统',
'memory.sessions': '会话数',
'memory.messages': '消息数',
'memory.vectors': '向量数',
'memory.backfill_status': '回填状态:',
'memory.status_running': '运行中',
'memory.status_stopped': '已停止',
'memory.usage_hint': '用法: /memory <搜索关键词>',
'memory.not_initialized': '记忆系统未初始化',
'memory.search_query': '搜索:',
'memory.no_results': '未找到相关记忆',
'memory.found_results': '找到 {{count}} 条相关记忆:',
'memory.search_failed': '搜索失败:',
'memory.api_config': '向量记忆 API 配置',
'memory.current_status': '当前状态:',
'memory.custom_key': '已配置自定义密钥',
'memory.using_default': '使用默认密钥',
'memory.api_url': 'API地址:',
'memory.model_name': '模型:',
'memory.keep_current': '未输入,保持当前配置',
'memory.api_key_encrypted': '向量记忆 API Key 已加密保存',
// API setup (cli.ts)
'api.wizard_title': 'API 配置向导',
'api.wizard_hint': '请按顺序输入各项信息,按回车确认',
'api.url_empty': 'URL 不能为空,已取消',
'api.key_empty': 'API Key 不能为空,已取消',
'api.model_empty': '模型型号不能为空,已取消',
'api.testing': '测试连接...',
'api.config_done': '配置完成并已应用!',
'api.key_encrypted': 'API Key: 已加密',
'api.display_name': '显示:',
'api.connect_failed': '连接失败:',
'api.fallback_default': '回退到系统默认配置,继续对话...',
'api.switched_default': '切换到系统默认模型:',
'api.config_saved_hint': '配置已加密保存,再次输入 /set 测试连接',
'api.usage': '用法:',
'api.set_interactive': '/set 交互式配置(推荐)',
'api.set_quick': '/set <api_key> 快速设置(使用默认URL)',
'api.key_stored': 'API Key 已加密存储',
'api.key_not_saved': '连接测试失败,API Key 未保存',
'api.engine_reinit': '引擎已重新初始化',
// Security warnings (P1 #28)
'security.fallback_warning': '加密使用回退密钥 - 共享环境不安全',
// Model management (cli.ts)
'model.manage_title': '模型管理',
'model.current': '当前模型:',
'model.your_config': '您的模型配置:',
'model.builtin_fast': '内置模型(快速添加):',
'model.operations': '操作:',
'model.op_switch': '切换到已配置模型',
'model.op_add_builtin': '添加内置模型',
'model.op_custom': '自定义接入',
'model.op_delete': '删除模型配置',
'model.op_cancel': '取消',
'model.switched': '模型已添加并切换',
'model.deleted': '已删除',
'model.added_switched': '已添加并切换到',
// Rate limiting (chat.ts)
'ratelimit.switching': 'API 限流,自动切换到 {{name}}...',
'ratelimit.exhausted': '所有默认 API 密钥已用尽!',
'ratelimit.add_own': '请使用 /set 命令添加您自己的 API Key',
'history.truncated': '历史已截断: {{from}} → {{to}} 条',
// Errors
'error.network': '网络连接失败:',
'error.check_network': '请检查网络连接,或输入 /model 重新选择',
'error.general': '错误:',
'error.model_hint': '输入 /model 可重新选择模型提供商',
'error.save_vector': '存储向量失败:',
'error.vector_search': '向量搜索失败:',
'error.fts_search': 'FTS5 搜索错误:',
'error.embedding': 'Embedding 失败:',
'error.embedding_ratelimit': 'Embedding API 限流,自动切换到 {{name}}...',
'error.429': '429 限流,请稍后重试',
// Vectors loaded
'vector.loaded': '已加载 {{count}} 个向量到内存索引',
// 429 handling
'model.key_switch': 'API 密钥已轮换至 {{name}}',
// Additional session keys
'session.total': '共',
'session.updated': '更新',
// Keypool
'keypool.no_permission': '密钥池管理仅限管理员使用。',
'keypool.alternative': '提示:可使用 /set 添加个人API密钥。',
// Keypool management
'keypool.title': '密钥池管理',
'keypool.no_keys': '无密钥',
'keypool.add_hint': '/keypool add chat/embed <name> <model> <baseUrl> 添加密钥',
'keypool.remove_hint': '/keypool remove chat/embed <序号> 删除密钥,Q 返回主界面',
'keypool.chat_added': 'Chat 密钥已添加',
'keypool.embed_added': 'Embedding 密钥已添加',
'keypool.details': '名称 / 模型 / URL',
'keypool.chat_deleted': 'Chat 密钥已删除',
'keypool.embed_deleted': 'Embedding 密钥已删除',
'keypool.not_found': '密钥不存在',
'keypool.help_list': '列出所有密钥',
'keypool.help_add_chat': '添加 Chat 密钥',
'keypool.help_add_embed': '添加 Embedding 密钥',
'keypool.help_del_chat': '删除 Chat 密钥',
'keypool.help_del_embed': '删除 Embedding 密钥',
// Session extras
'session.msg_count': '消息: ',
// Goodbye
'misc.goodbye': '再见!',
// Clipboard (askREPL)
'clip.copied': '已复制到剪贴板',
'clip.cut': '已剪切',
// /model hardcoded prompts
'model.op_input_hint': '输入数字/字母选择 [Q] 返回',
'model.select_prompt': '选择模型 [1-{{max}}] (Q 取消): ',
'model.op_action_hint': '输入数字/字母选择 [Q] 返回主界面',
'model.select_action': '选择操作 (Q 取消): ',
'model.delete_index': '删除模型序号 [1-{{max}}]: ',
'model.confirm_delete': '确认删除 {{name}}? [y/N]: ',
'model.custom_hint': '(自行填写 API 地址和密钥)',
'model.cancelled': '已取消',
'model.connection_test': '连接测试:',
'model.testing_connection': '测试连接 {{vendor}} ...',
'model.continue_anyway': '是否继续? [Y/n]: ',
'model.note1': '备注1 (可选): ',
'model.note2': '备注2 (可选): ',
'model.is_default': '[默认]',
'model.is_current': '[当前]',
// Masterkey
'api.masterkey_hint': '/masterkey <密码> 设置专属加密密钥',
// System prompt
'system.custom': '自定义:',
'system.set_usage': '用法: /system <提示词> 设置自定义提示词',
'system.cleared': '固定提示词已清除',
'system.set': '固定提示词已设置:',
// Connection flow
'model.connecting': '连接',
'session.checking_snapshot': '检查工作区快照...',
// Error messages (single mode)
'error.429_single': '429 限流,请稍后重试',
'error.switch_model_hint': '输入 /model 切换到其他模型提供商',
'error.network_single': '网络连接失败:',
'error.check_network_hint': '请检查网络连接,或输入 /model 重新选择',
'error.general_single': '错误:',
'error.model_hint_single': '输入 /model 可重新选择模型提供商',
'error.model_saved_not_applied': '连接失败,配置已保存但未应用,请检查后使用 /model 重试',
// /system
'system.using_default': '使用默认 (沙箱代码生成模式)',
'system.usage': '用法: /system clear 恢复默认提示词',
// /memory
'memory.op_hint': '输入 /memory <关键词> 搜索,直接回车返回',
// /set mem
'memory.new_key_prompt': '输入新的火山引擎 API Key (回车跳过, Q 取消): ',
// Custom API wizard
'api.op_hint': '按顺序输入各项信息,输入 Q 可随时取消',
'api.url_prompt': 'URL (Q 取消): ',
'api.key_prompt': 'API Key (Q 取消): ',
'api.model_prompt': '模型型号 (Q 取消): ',
// /session
'session.read_hint': '输入 /session read <id> 查看详情,/session cleanup 清理,直接回车返回',
'session.commands_hint': '命令: /session read <id> | /session delete <id> | /session cleanup',
'session.specify_id': '请指定会话ID: /session read <id>',
'session.not_found': '会话不存在:',
'session.detail_title': '会话详情:',
'session.detail_count': '消息数:',
'session.detail_size': '大小:',
'session.detail_created': '创建:',
'session.detail_modified': '修改:',
'session.detail_content': '=== 会话内容 ===',
'session.truncated': '... [截断]',
'session.page_hint': '── 按回车继续阅读,Q 退出 ──',
'session.back_hint': '直接回车返回主界面',
'session.delete_hint': '输入 /session read <id> 查看详情,/session cleanup 清理,直接回车返回',
'session.confirm_delete': '确认删除会话 {{id}}? [y/N]: ',
'session.deleted': '已删除会话:',
'session.delete_failed': '删除失败或会话不存在:',
'session.cleanup_no_low': '没有低价值会话需要清理',
'session.cleanup_found': '发现 {{count}} 个低价值会话:',
'session.cleanup_reason': '原因:',
'session.cleanup_confirm': '确认清理以上 {{count}} 个会话? [y/N]: ',
'session.cleanup_done': '已清理 {{deleted}} 个会话',
'session.cleanup_failed': '失败',
'session.specify_delete_id': '请指定会话ID: /session delete <id>',
}
}
/**
* 翻译函数
* @param key 翻译键
* @param params 插值参数
*/
export function t(key: string, params?: Record<string, string | number>): string {
const dict = translations[currentLang] || translations.en
let text = dict[key] || key
// 插值替换
if (params) {
for (const [k, v] of Object.entries(params)) {
text = text.replace(new RegExp(`\\{\\{${k}\\}\\}`, 'g'), String(v))
}
}
return text
}
/**
* 获取当前语言
*/
export function getLang(): 'en' | 'zh' {
return currentLang
}
/**
* 切换语言
*/
export function setLang(lang: 'en' | 'zh'): void {
currentLang = lang
// 保存到配置文件
try {
if (!existsSync(CONFIG_DIR)) {
mkdirSync(CONFIG_DIR, { recursive: true })
}
writeFileSync(CONFIG_FILE, JSON.stringify({ lang }, null, 2))
} catch {
// 保存失败不影响程序运行
}
}
/**
* 切换语言并返回消息
*/
export function switchLang(lang: 'en' | 'zh'): string {
setLang(lang)
return lang === 'en'
? translations.en['misc.lang_switched']
: translations.zh['misc.lang_switched_cn']
}
// 导出初始化函数
export const initI18n = initLang