import i18n from 'i18next'; import { initReactI18next } from 'react-i18next'; import LanguageDetector from 'i18next-browser-languagedetector'; import vi from './vi'; i18n .use(LanguageDetector) .use(initReactI18next) .init({ fallbackLng: 'en', detection: { order: ['localStorage', 'navigator'], caches: ['localStorage'], lookupLocalStorage: 'lang', }, supportedLngs: ['en', 'zh-CN', 'ru', 'vi'], load: 'currentOnly', // Only load the exact language code, not variants resources: { en: { translation: { appName: 'Gemini Nexus', common: { loading: 'Loading...', error: 'Error', unknown: 'Unknown', notAvailable: 'N/A', openMenu: 'Open menu', }, status: { checking: 'Checking status...', running: 'Gemini Nexus is running in background', stopped: 'Gemini Nexus service stopped', }, action: { stop: 'Stop', start: 'Start', switch: 'Switch', deleteBackup: 'Delete Backup', backupCurrent: 'Backup Current', retry: 'Retry', openLogs: 'Open Log Directory', }, error: { generic: 'An unexpected error occurred.', keychainUnavailable: 'Keychain is unavailable.', keychainHint: { translocation: 'Detected macOS App Translocation. Move the app to /Applications and reopen.', keychainDenied: 'Keychain access denied. The app may be unsigned; see README for the self-signing workaround.', signNotarize: 'Please use a signed and notarized build when available.', }, dataMigrationFailed: 'Unable to decrypt legacy account data.', dataMigrationHint: { relogin: 'Please re-login or re-add your accounts.', clearData: 'If the issue persists, clear local account data and sign in again.', }, }, nav: { accounts: 'Accounts', usage: 'Usage', proxy: 'API Proxy', settings: 'Settings', }, account: { current: 'Current', lastUsed: 'Last used {{time}}', }, home: { title: 'Accounts', description: 'Manage your Gemini Nexus Google Gemini accounts.', noBackups: { title: 'No backups found', description: 'Create a backup of your current Gemini Nexus account to get started.', action: 'Backup Current Account', }, }, settings: { title: 'Settings', description: 'Manage application preferences.', general: 'General', connection: 'Connection', models: 'Models', appearance: { title: 'Appearance', description: 'Customize how Gemini Nexus looks on your device.', }, darkMode: 'Dark Mode', darkModeDescription: 'Enable dark mode for better viewing at night.', language: { title: 'Language', description: 'Select your preferred language.', english: 'English', chinese: 'Chinese (Simplified)', russian: 'Russian', vietnamese: 'Vietnamese', }, about: { title: 'About', description: 'Application information.', }, version: 'Version', platform: 'Platform', license: 'License', openLogDir: 'Open', toast: { saved: { title: 'Settings saved', description: 'Your configuration has been updated.', }, saveFailed: { title: 'Error saving settings', }, }, account: { title: 'Account Settings', description: 'Configure automatic account refresh and sync.', auto_refresh: 'Auto Refresh Quota', auto_refresh_desc: 'Periodically refresh quota info for all accounts', auto_sync: 'Auto Sync Current Account', auto_sync_desc: 'Periodically sync active account information', }, startup: { title: 'Startup', description: 'Control application launch behavior at system startup.', auto_startup: 'Start with system', auto_startup_desc: 'Launch at sign-in and keep the app in the system tray', macos_hint: 'macOS requires a signed app for Login Items to work. If auto-start fails, please sign the app or enable it manually in System Settings.', }, privacy: { title: 'Privacy', description: 'Control how your data is used to improve the application.', error_reporting: 'Error Reporting', error_reporting_desc: 'Send anonymous error reports to help us improve the app. No personal data is collected.', restart_note: 'Changes to error reporting will take effect after restarting the application.', }, notifications: { title: 'Notifications', description: 'Configure desktop alerts for account events.', quotaAlert: 'Low Quota Alerts', quotaAlertDesc: 'Get notified when a model quota drops below the set threshold', quotaThreshold: 'Alert Threshold', quotaThresholdDesc: 'Percentage below which to trigger an alert', saveFailed: 'Failed to save notification settings', thresholdSaveFailed: 'Failed to save threshold setting', }, proxy: { title: 'Upstream Proxy', description: 'Configure a proxy for outgoing requests to Google/Gemini APIs.', enable: 'Enable Upstream Proxy', url: 'Proxy URL', timeout: 'Request Timeout (Seconds)', accountProxies: { title: 'Account Proxies', description: 'Configure specific proxies for individual accounts. These will override the global upstream proxy for that specific account.', }, }, modelMapping: { title: 'Model Mapping', description: 'Map Claude Code models to Gemini Nexus models. Optimize cost and speed by routing requests intelligently.', claudeKeyword: 'Claude Model (Keyword)', targetGemini: 'Target Gemini Model', addPlaceholderKey: 'e.g. op-3', addPlaceholderValue: 'e.g. gemini-3-flash', noMappings: 'No custom mappings defined.', mapsTo: 'Maps to', default: 'Default', restoreDefaults: 'Restore Defaults', }, modelVisibility: { title: 'Model Visibility', description: "Control which models are visible in account cards. Hidden models won't appear in the quota display.", searchPlaceholder: 'Search models...', showAll: 'Show All', hideAll: 'Hide All', reset: 'Reset to Defaults', save: 'Save Changes', noModels: 'No models found', modelsShown: '{{visible}} of {{total}} models visible', quotaManagement: 'Quota Management', hidden: 'Hidden', noModelsFound: 'No models found', totalModels: 'Total', visibleModels: 'Visible', hiddenModels: 'Hidden', saving: 'Saving...', }, providerGroupings: { title: 'Provider Groupings', description: 'Group models by provider for better organization', enabled: 'Enable Provider Groupings', models: '{{count}} models', avgLabel: 'avg', resetLabel: 'reset', overall: 'Overall', healthy: 'Healthy', degraded: 'Degraded', limited: 'Limited', critical: 'Critical', }, examples: { title: 'Usage Examples', description: 'Example commands to call the local API proxy.', curl: 'cURL', python: 'Python', copy: 'Copy', copied: 'Copied!', openai_protocol: 'OpenAI Protocol', anthropic_protocol: 'Anthropic Protocol', openai_tools: 'Cursor, Windsurf, NextChat', anthropic_tools: 'Claude Code CLI', flash: 'Fast', pro: 'Pro', flash_preview: 'Preview', pro_high: 'Best', sonnet: 'Thinking', opus: 'Opus', }, gateway: { title: 'API Proxy Service', description: 'Control the local API proxy server.', status_running: 'Running', status_stopped: 'Stopped', action_start: 'Start Service', action_stop: 'Stop Service', accounts_info: '{{count}} accounts available', port: 'Listen Port', port_hint: 'Default 8045, restart required to apply changes', timeout: 'Request Timeout', timeout_hint: 'Default 120s, range 30-600s', api_key: 'API Key', regenerate_key: 'Regenerate', regenerateConfirm: { title: 'Regenerate API Key?', description: 'This will invalidate the current API key immediately. Any applications using the old key will stop working.', cancel: 'Cancel', confirm: 'Regenerate', }, key_warning: 'Keep your API key secure. Do not share it.', auto_start: 'Auto Start with App', auto_start_desc: 'Start proxy service when application launches', }, proxy_tab: 'Proxy', save: 'Save Settings', }, toast: { backupSuccess: { title: 'Success', description: 'Account backup created successfully.', }, backupError: { title: 'Error', description: 'Failed to create backup: {{error}}', }, switchSuccess: { title: 'Success', description: 'Switched account successfully.', }, switchError: { title: 'Error', description: 'Failed to switch account: {{error}}', }, deleteSuccess: { title: 'Success', description: 'Account backup deleted successfully.', }, deleteError: { title: 'Error', description: 'Failed to delete backup: {{error}}', }, }, cloud: { title: 'Accounts', description: 'Manage your Google Gemini account pool.', autoSwitch: 'Auto-Switch', providerGroupings: 'Provider Groupings', addAccount: 'Add Account', syncFromIDE: 'Sync from IDE', checkQuota: 'Check Quota Now', polling: 'Polling triggered', globalQuota: 'Global Quota', layout: { auto: 'Auto', twoCol: '2 Columns', threeCol: '3 Columns', list: 'List', compact: 'Compact', }, authDialog: { title: 'Add Google Account', description: 'To add an account, you need to authorize the application.', oauthClient: 'OAuth Client', oauthClientPlaceholder: 'Select OAuth client', openLogin: 'Open Login Page', authCode: 'Authorization Code', placeholder: 'Paste the code starting with 4/...', instruction: 'Will open default browser for Google login. Copy the code from localhost page and paste here.', verify: 'Verify & Add', }, card: { active: 'Active', use: 'Use', rateLimited: 'Rate Limited', validationRiskControlled: 'Risk / Rate Limited', validationOAuthReauthRequired: 'OAuth Re-auth Required', validationRequired: 'Verification Required', left: 'left', used: 'Used', unknown: 'Unknown User', actions: 'Actions', useAccount: 'Use Account', identityProfile: 'Identity Profile', refresh: 'Refresh Quota', delete: 'Delete Account', noQuota: 'No quota data', rateLimitedQuota: 'Rate Limited', resetPrefix: 'reset', resetTime: 'Reset time', resetUnknown: 'Unknown', gemini3Ready: 'Gemini 3 Ready', groupGoogleGemini: 'Google Gemini', groupAnthropicClaude: 'Anthropic Claude', proxy: 'Proxy', proxyPlaceholder: 'e.g. http://127.0.0.1:7890', proxySaved: 'Proxy saved', noProxy: 'No proxy', aiCredits: 'AI Credits', aiCreditsValue: '{{amount}} credits', creditsExpiry: 'expires {{date}}', modelVisibility: 'Model Visibility', }, identity: { title: 'Identity Profile', loading: 'Loading...', generateAndBind: 'Create and Bind', captureAndBind: 'Capture and Bind Current', restoreOriginal: 'Restore Baseline', openFolder: 'Open Identity Storage', previewTitle: 'Generated Identity Preview', confirm: 'Confirm', cancel: 'Cancel', close: 'Close', currentStorage: 'Current Runtime Identity', accountBinding: 'Bound Account Identity', history: 'Identity History', noHistory: 'No identity history', current: 'Active', restore: 'Restore', generateSuccess: 'Identity created and bound', captureSuccess: 'Current identity captured and bound', restoreOriginalSuccess: 'Baseline identity restored', restoreVersionSuccess: 'Historical identity restored', deleteVersionSuccess: 'Historical identity deleted', openFolderSuccess: 'Identity storage opened', baseline: 'Baseline Identity', }, list: { noAccounts: 'No cloud accounts added yet.', }, error: { loadFailed: 'Failed to load cloud accounts.', }, toast: { syncSuccess: { title: 'Sync Successful', description: 'Imported {{email}} from IDE.', }, syncFailed: { title: 'Sync Failed', description: 'No active account found in IDE database.', }, addSuccess: 'Account added successfully!', addFailed: { title: 'Failed to add account', }, quotaRefreshed: 'Quota refreshed', refreshFailed: 'Failed to refresh quota', pollFailed: 'Failed to poll quota for all accounts', switched: { title: 'Account switched!', description: 'Restarting Gemini Nexus...', }, switchFailed: 'Failed to switch account', deleted: 'Account deleted', deleteFailed: 'Failed to delete account', deleteConfirm: 'Are you sure you want to delete this account?', autoSwitchOn: 'Auto-Switch Enabled', autoSwitchOff: 'Auto-Switch Disabled', updateSettingsFailed: 'Failed to update settings', actionFailed: 'Action failed', startAuthFailed: 'Failed to start sign-in flow', refreshCreditsAvailable: 'AI credits: {{amount}}', refreshCreditsUnavailable: 'AI credits not available for this refresh.', batchRefreshSuccess: 'Successfully refreshed {{count}} accounts.', batchRefreshPartial: { title: 'Refresh completed with issues', description: 'Refreshed {{successful}} accounts, {{failed}} failed.', }, batchDeleteSuccess: 'Successfully deleted {{count}} accounts.', batchDeletePartial: { title: 'Deletion completed with issues', description: 'Deleted {{successful}} accounts, {{failed}} failed.', }, }, batch: { selected: 'Selected {{count}}', delete: 'Delete Selected', refresh: 'Refresh Selected', selectAll: 'Select All', clear: 'Clear Selection', confirmDelete: 'Are you sure you want to delete {{count}} accounts?', }, sort: { recentlyUsed: 'Recently Used', quotaOverall: 'Overall Quota', quotaClaude: 'Claude Quota', quotaPro3: 'Pro3 Quota', quotaFlash: 'Flash Quota', }, exportImport: { export: 'Export', import: 'Import', exportTitle: 'Export Accounts', exportDesc: 'Choose whether to include authentication tokens in the export file.', includeTokens: 'Include tokens (less secure)', stripTokens: 'Strip tokens (safer for sharing)', exportSuccess: 'Accounts exported successfully', importTitle: 'Import Accounts', importDesc: 'Select a previously exported JSON file.', importStrategy: 'Import Strategy', strategyMerge: 'Merge - Update existing, add new', strategyOverwrite: 'Overwrite - Replace all existing data', strategySkip: 'Skip - Only add new accounts', importSuccess: 'Imported {{imported}}, updated {{updated}}, skipped {{skipped}}', importErrors: 'Import completed with {{count}} error(s)', selectFile: 'Select File', importing: 'Importing...', fileTooLarge: 'File size exceeds 5MB limit', invalidJson: 'Invalid JSON file format', readFileFailed: 'Failed to read file', }, }, proxy: { title: 'API Proxy', description: 'Manage the local API proxy service.', save: 'Save Settings', copy: 'Copy', copied: 'Copied!', regenerate: 'Regenerate', regenerateConfirm: { title: 'Regenerate API Key?', description: 'This will invalidate the current API key immediately. Any applications using the old key will stop working.', cancel: 'Cancel', confirm: 'Regenerate', }, service: { title: 'Service Status', description: 'Control the local API proxy server.', running: 'Running', stopped: 'Stopped', start: 'Start Service', stop: 'Stop Service', }, config: { port: 'Listen Port', timeout: 'Request Timeout', api_key: 'API Key', auto_start: 'Auto Start with App', auto_start_desc: 'Start proxy service when application launches', local_access: 'Local network access:', select_ip: 'Select IP', no_token_warning: '⚠️ API key is not set. Access is open to everyone!', show_key: 'Show', hide_key: 'Hide', }, mapping: { title: 'Model Mapping', description: 'Map Claude models to Gemini models for routing.', maps_to: 'Maps to', restore: 'Restore Defaults', }, examples: { title: 'Usage Examples', description: 'Example commands to call the local API proxy.', }, }, usage: { title: 'Token Usage', description: 'Monitor your API token consumption over time.', range24h: 'Last 24 Hours', range7d: 'Last 7 Days', range30d: 'Last 30 Days', totalTokens: 'Total Tokens', promptTokens: 'Prompt Tokens', completionTokens: 'Completion Tokens', totalRequests: 'Total Requests', dailyUsage: 'Daily Usage', byModel: 'Usage by Model', hourlyUsage: 'Hourly Usage', loadFailed: 'Failed to load usage data.', retry: 'Retry', allAccounts: 'All Accounts', noData: 'No data available', }, }, }, vi: { translation: vi, }, 'zh-CN': { translation: { appName: 'Gemini Nexus 管理器', common: { loading: '加载中...', error: '错误', unknown: '未知', notAvailable: '不适用', openMenu: '打开菜单', }, status: { checking: '正在检查状态...', running: 'Gemini Nexus 正在后台运行', stopped: 'Gemini Nexus 服务已停止', }, action: { stop: '停止', start: '启动', switch: '切换', deleteBackup: '删除备份', backupCurrent: '备份当前账号', retry: '重试', openLogs: '打开日志目录', }, error: { generic: '发生未知错误。', keychainUnavailable: 'Keychain 不可用。', keychainHint: { translocation: '检测到 macOS App Translocation。请将应用移动到 /Applications 后重试。', keychainDenied: 'Keychain 访问被拒绝。应用可能未签名,可参考 README 的“macOS 自签”说明。', signNotarize: '请在可用时使用已签名并公证的版本。', }, dataMigrationFailed: '旧版账号数据无法解密。', dataMigrationHint: { relogin: '请重新登录或重新添加账号。', clearData: '如仍失败,请清理本地账号数据后再登录。', }, }, nav: { accounts: '账号', usage: '用量', proxy: 'API 反代', settings: '设置', }, account: { current: '当前', lastUsed: '上次使用 {{time}}', }, home: { title: '账号列表', description: '管理您的 Gemini Nexus Google Gemini 账号。', noBackups: { title: '未找到备份', description: '备份您当前的 Gemini Nexus 账号以开始使用。', action: '备份当前账号', }, }, settings: { title: '设置', description: '管理应用偏好设置。', general: '常规', connection: '连接', models: '模型', appearance: { title: '外观', description: '自定义 Gemini Nexus 管理器在您设备上的显示方式。', }, darkMode: '深色模式', darkModeDescription: '启用深色模式以获得更好的夜间观看体验。', language: { title: '语言', description: '选择您的首选语言。', english: '英语', chinese: '中文 (简体)', russian: '俄语', vietnamese: '越南语', }, about: { title: '关于', description: '应用信息。', }, version: '版本', platform: '平台', license: '许可证', openLogDir: '打开', toast: { saved: { title: '设置已保存', description: '配置已更新。', }, saveFailed: { title: '保存设置失败', }, }, account: { title: '账号设置', description: '配置自动刷新和同步账号。', auto_refresh: '自动刷新配额', auto_refresh_desc: '定期自动刷新所有账号的配额信息', auto_sync: '自动获取当前账号', auto_sync_desc: '定期自动同步当前活跃账号信息', }, startup: { title: '启动', description: '控制系统启动时的应用行为。', auto_startup: '随系统启动', auto_startup_desc: '登录时自动启动并保持在托盘里', macos_hint: 'macOS 需要应用已签名才可生效。如自启动失败,请自行签名或在系统设置中手动启用。', }, privacy: { title: '隐私', description: '控制你的数据如何用于改进应用。', error_reporting: '错误上报', error_reporting_desc: '发送匿名错误报告以帮助我们改进应用。不收集个人数据。', restart_note: '错误上报设置会在重启应用后生效。', }, notifications: { title: '通知', description: '配置账号事件的桌面提醒。', quotaAlert: '低配额提醒', quotaAlertDesc: '当模型配额低于设定阈值时收到提醒', quotaThreshold: '提醒阈值', quotaThresholdDesc: '触发提醒的百分比阈值', saveFailed: '保存通知设置失败', thresholdSaveFailed: '保存阈值设置失败', }, proxy: { title: '上游代理', description: '为发往 Google/Gemini API 的请求配置代理。', enable: '启用上游代理', url: '代理地址', timeout: '请求超时 (秒)', accountProxies: { title: '独立账号代理', description: '为各个独立账号配置特定的代理。这些配置将覆盖该账号的全局上游代理。', }, }, modelMapping: { title: '模型映射', description: '将 Claude Code 模型映射到 Gemini Nexus 模型,智能路由请求以优化成本和速度。', claudeKeyword: 'Claude 模型 (关键词)', targetGemini: '目标 Gemini 模型', addPlaceholderKey: '例如 op-3', addPlaceholderValue: '例如 gemini-3-flash', noMappings: '暂无自定义映射。', mapsTo: '映射到', default: '默认', restoreDefaults: '恢复默认配置', }, modelVisibility: { title: '模型可见性', description: '控制哪些模型在账号卡片中可见。隐藏的模型不会在配额显示中出现。', searchPlaceholder: '搜索模型...', showAll: '显示全部', hideAll: '隐藏全部', reset: '重置为默认', save: '保存更改', noModels: '未找到模型', modelsShown: '{{visible}} / {{total}} 个模型可见', quotaManagement: '配额管理', hidden: '已隐藏', noModelsFound: '未找到模型', totalModels: '总数', visibleModels: '可见', hiddenModels: '隐藏', saving: '保存中...', }, providerGroupings: { title: '模型分组', description: '按供应商分组模型以便更好地管理', enabled: '启用供应商分组', models: '{{count}} 个模型', avgLabel: '平均', resetLabel: '重置', overall: '总览', healthy: '正常', degraded: '降级', limited: '受限', critical: '严重', }, examples: { title: '使用示例', description: '调用本地 API 代理的示例命令。', curl: 'cURL', python: 'Python', copy: '复制', copied: '已复制!', openai_protocol: 'OpenAI 协议', anthropic_protocol: 'Anthropic 协议', openai_tools: 'Cursor, Windsurf, NextChat', anthropic_tools: 'Claude Code CLI', flash: '极速', pro: '专业版', flash_preview: '预览版', pro_high: '最强', sonnet: '思维链', opus: 'Opus', }, gateway: { title: 'API 反代服务', description: '控制本地 API 代理服务器。', status_running: '运行中', status_stopped: '已停止', action_start: '启动服务', action_stop: '停止服务', accounts_info: '{{count}} 个账号可用', port: '监听端口', port_hint: '默认 8045,修改端口需重启服务', timeout: '请求超时', timeout_hint: '默认 120 秒,范围 30-600 秒', api_key: 'API 密钥', regenerate_key: '重新生成', regenerateConfirm: { title: '重新生成 API 密钥?', description: '这将立即废除当前 API 密钥。任何使用旧密钥的应用将无法继续工作。', cancel: '取消', confirm: '重新生成', }, key_warning: '请妥善保管您的 API 密钥,不要泄露给他人。', auto_start: '跟随应用自动启动', auto_start_desc: '应用启动时自动启动代理服务', }, proxy_tab: '反代', save: '保存设置', }, toast: { backupSuccess: { title: '成功', description: '账号备份创建成功。', }, backupError: { title: '错误', description: '创建备份失败:{{error}}', }, switchSuccess: { title: '成功', description: '切换账号成功。', }, switchError: { title: '错误', description: '切换账号失败:{{error}}', }, deleteSuccess: { title: '成功', description: '账号备份删除成功。', }, deleteError: { title: '错误', description: '删除备份失败:{{error}}', }, }, cloud: { title: '账号列表', description: '管理您的 Google Gemini 账号池。', autoSwitch: '自动切换', providerGroupings: '提供商分组', addAccount: '添加账号', syncFromIDE: '从 IDE 同步', checkQuota: '立即检查配额', polling: '已触发轮询', globalQuota: '全局配额', layout: { auto: '自动', twoCol: '2 列', threeCol: '3 列', list: '列表', compact: '紧凑', }, authDialog: { title: '添加 Google 账号', description: '添加账号需要进行应用授权。', oauthClient: 'OAuth 客户端', oauthClientPlaceholder: '请选择 OAuth 客户端', openLogin: '打开登录页面', authCode: '授权码', placeholder: '粘贴以 4/ 开头的代码...', instruction: '将打开默认浏览器进行 Google 登录授权,自动获取并保存 Token。', verify: '验证并添加', }, card: { active: '活跃', use: '使用', rateLimited: '受限', validationRiskControlled: '风控 / 限流', validationOAuthReauthRequired: '需要重新 OAuth 授权', validationRequired: '需要校验', left: '剩余', used: '已用', unknown: '未知用户', actions: '操作', useAccount: '使用账号', identityProfile: '身份配置', refresh: '刷新配额', delete: '删除账号', noQuota: '无配额数据', rateLimitedQuota: '已达限额', resetPrefix: '重置', resetTime: '重置时间', resetUnknown: '未知', gemini3Ready: 'Gemini 3 就绪', groupGoogleGemini: 'Google Gemini', groupAnthropicClaude: 'Anthropic Claude', proxy: '代理', proxyPlaceholder: '例如 http://127.0.0.1:7890', proxySaved: '代理已保存', noProxy: '无代理', aiCredits: 'AI 积分', aiCreditsValue: '{{amount}} 积分', creditsExpiry: '{{date}} 过期', modelVisibility: '模型可见性', }, identity: { title: '身份配置', loading: '加载中...', generateAndBind: '生成并绑定', captureAndBind: '采集当前并绑定', restoreOriginal: '恢复基线配置', openFolder: '打开身份存储目录', previewTitle: '生成配置预览', confirm: '确认', cancel: '取消', close: '关闭', currentStorage: '当前运行配置', accountBinding: '账号绑定配置', history: '配置历史', noHistory: '暂无配置历史', current: '当前生效', restore: '恢复', generateSuccess: '生成并绑定成功', captureSuccess: '采集当前并绑定成功', restoreOriginalSuccess: '基线配置已恢复', restoreVersionSuccess: '历史配置已恢复', deleteVersionSuccess: '历史配置已删除', openFolderSuccess: '身份存储目录已打开', baseline: '基线配置', }, list: { noAccounts: '暂无云账号。', }, error: { loadFailed: '加载云账号失败。', }, toast: { syncSuccess: { title: '同步成功', description: '已从 IDE 导入 {{email}}。', }, syncFailed: { title: '同步失败', description: 'IDE 数据库中未找到活跃账号。', }, addSuccess: '账号添加成功!', addFailed: { title: '添加账号失败', }, quotaRefreshed: '配额已刷新', refreshFailed: '刷新配额失败', pollFailed: '轮询所有账号配额失败', switched: { title: '账号已切换!', description: '正在重启 Gemini Nexus...', }, switchFailed: '切换账号失败', deleted: '账号已删除', deleteFailed: '删除账号失败', deleteConfirm: '确定要删除此账号吗?', autoSwitchOn: '自动切换已启用', autoSwitchOff: '自动切换已禁用', updateSettingsFailed: '更新设置失败', actionFailed: '操作失败', startAuthFailed: '启动登录流程失败', refreshCreditsAvailable: 'AI 积分:{{amount}}', refreshCreditsUnavailable: '本次刷新没有可用的 AI 积分信息。', batchRefreshSuccess: '成功刷新 {{count}} 个账号。', batchRefreshPartial: { title: '刷新已完成,但存在问题', description: '已刷新 {{successful}} 个账号,{{failed}} 个失败。', }, batchDeleteSuccess: '成功删除 {{count}} 个账号。', batchDeletePartial: { title: '删除已完成,但存在问题', description: '已删除 {{successful}} 个账号,{{failed}} 个失败。', }, }, batch: { selected: '已选 {{count}} 项', delete: '删除选中', refresh: '刷新选中', selectAll: '全选', clear: '取消选择', confirmDelete: '确定要删除选中的 {{count}} 个账号吗?', }, sort: { recentlyUsed: '最近使用', quotaOverall: '总体配额', quotaClaude: 'Claude 配额', quotaPro3: 'Pro3 配额', quotaFlash: 'Flash 配额', }, exportImport: { export: '导出', import: '导入', exportTitle: '导出账号', exportDesc: '选择是否在导出文件中包含认证令牌。', includeTokens: '包含令牌(安全性较低)', stripTokens: '移除令牌(适合分享)', exportSuccess: '账号导出成功', importTitle: '导入账号', importDesc: '选择之前导出的 JSON 文件。', importStrategy: '导入策略', strategyMerge: '合并 - 更新已有,添加新账号', strategyOverwrite: '覆盖 - 替换所有已有数据', strategySkip: '跳过 - 仅添加新账号', importSuccess: '导入 {{imported}},更新 {{updated}},跳过 {{skipped}}', importErrors: '导入完成,但有 {{count}} 个错误', selectFile: '选择文件', importing: '导入中...', fileTooLarge: '文件大小超过 5MB 限制', invalidJson: 'JSON 文件格式无效', readFileFailed: '读取文件失败', }, }, proxy: { title: 'API 反代', description: '管理本地 API 代理服务。', save: '保存设置', copy: '复制', copied: '已复制!', regenerate: '重新生成', regenerateConfirm: { title: '重新生成 API 密钥?', description: '这将立即废除当前 API 密钥。任何使用旧密钥的应用将无法继续工作。', cancel: '取消', confirm: '重新生成', }, service: { title: '服务状态', description: '控制本地 API 代理服务器。', running: '运行中', stopped: '已停止', start: '启动服务', stop: '停止服务', }, config: { port: '监听端口', timeout: '请求超时', api_key: 'API 密钥', auto_start: '随应用启动', auto_start_desc: '应用启动时自动启动代理服务', local_access: '局域网访问:', select_ip: '选择 IP', no_token_warning: '⚠️ 未设置 API 密钥。服务对公网开放!', show_key: '显示密钥', hide_key: '隐藏密钥', }, mapping: { title: '模型映射', description: '将 Claude 模型映射到 Gemini 模型进行路由。', maps_to: '映射到', restore: '恢复默认', }, examples: { title: '使用示例', description: '调用本地 API 代理的示例命令。', }, }, usage: { title: 'Token 用量', description: '监控您的 API Token 消耗情况。', range24h: '最近 24 小时', range7d: '最近 7 天', range30d: '最近 30 天', totalTokens: '总 Token 数', promptTokens: 'Prompt Token 数', completionTokens: 'Completion Token 数', totalRequests: '总请求数', dailyUsage: '每日用量', byModel: '按模型统计', hourlyUsage: '每小时用量', loadFailed: '加载用量数据失败。', retry: '重试', allAccounts: '所有账号', noData: '暂无数据', }, }, }, ru: { translation: { appName: 'Gemini Nexus', common: { loading: 'Загрузка...', error: 'Ошибка', unknown: 'Неизвестно', notAvailable: 'Н/Д', openMenu: 'Открыть меню', }, status: { checking: 'Проверка статуса...', running: 'Gemini Nexus работает в фоне', stopped: 'Служба Gemini Nexus остановлена', }, action: { stop: 'Стоп', start: 'Старт', switch: 'Переключить', deleteBackup: 'Удалить резервную копию', backupCurrent: 'Создать бэкап текущего', retry: 'Повторить', openLogs: 'Открыть папку логов', }, error: { generic: 'Произошла непредвиденная ошибка.', keychainUnavailable: 'Keychain недоступен.', keychainHint: { translocation: 'Обнаружено App Translocation (macOS). Переместите приложение в /Applications и откройте заново.', keychainDenied: 'Доступ к Keychain запрещен. Возможно, приложение не подписано. См. README для инструкции.', signNotarize: 'Пожалуйста, используйте подписанную версию приложения.', }, dataMigrationFailed: 'Не удалось расшифровать данные старого аккаунта.', dataMigrationHint: { relogin: 'Пожалуйста, перезайдите в аккаунт или добавьте его заново.', clearData: 'Если ошибка сохраняется, очистите локальные данные и войдите снова.', }, }, nav: { accounts: 'Аккаунты', usage: 'Использование', proxy: 'API Прокси', settings: 'Настройки', }, account: { current: 'Текущий', lastUsed: 'Последнее использование {{time}}', }, home: { title: 'Аккаунты', description: 'Управление вашими аккаунтами Gemini Nexus Google Gemini.', noBackups: { title: 'Бэкапы не найдены', description: 'Создайте резервную копию вашего текущего аккаунта Gemini Nexus, чтобы начать.', action: 'Создать бэкап текущего аккаунта', }, }, settings: { title: 'Настройки', description: 'Управление настройками приложения.', general: 'Общие', connection: 'Подключение', models: 'Модели', appearance: { title: 'Внешний вид', description: 'Настройте внешний вид Gemini Nexus.', }, darkMode: 'Темная тема', darkModeDescription: 'Включить темную тему для комфортной работы ночью.', language: { title: 'Язык', description: 'Выберите язык интерфейса.', english: 'English', chinese: '中文 (简体)', russian: 'Русский', vietnamese: 'Вьетнамский', }, about: { title: 'О программе', description: 'Информация о приложении.', }, version: 'Версия', platform: 'Платформа', license: 'Лицензия', openLogDir: 'Открыть', toast: { saved: { title: 'Настройки сохранены', description: 'Конфигурация обновлена.', }, saveFailed: { title: 'Ошибка сохранения настроек', }, }, account: { title: 'Настройки аккаунта', description: 'Настройка автоматического обновления и синхронизации.', auto_refresh: 'Автообновление квот', auto_refresh_desc: 'Периодически обновлять информацию о квотах для всех аккаунтов', auto_sync: 'Автосинхронизация текущего', auto_sync_desc: 'Периодически синхронизировать активный аккаунт', }, startup: { title: 'Автозагрузка', description: 'Управление запуском приложения при старте системы.', auto_startup: 'Запускать вместе с системой', auto_startup_desc: 'Запускать при входе и сворачивать в трей', macos_hint: 'macOS требует подписанное приложение для работы элементов входа. Если автозапуск не работает, подпишите приложение или включите его вручную в системных настройках.', }, privacy: { title: 'Конфиденциальность', description: 'Управление использованием данных для улучшения приложения.', error_reporting: 'Отчеты об ошибках', error_reporting_desc: 'Отправляйте анонимные отчеты об ошибках, чтобы помочь нам улучшить приложение. Личные данные не собираются.', restart_note: 'Изменения в отчетах об ошибках вступят в силу после перезапуска приложения.', }, notifications: { title: 'Уведомления', description: 'Настройте уведомления о событиях аккаунтов.', quotaAlert: 'Уведомления о низкой квоте', quotaAlertDesc: 'Получайте уведомления, когда квота модели падает ниже установленного порога', quotaThreshold: 'Порог уведомления', quotaThresholdDesc: 'Процент, ниже которого срабатывает уведомление', saveFailed: 'Не удалось сохранить настройки уведомлений', thresholdSaveFailed: 'Не удалось сохранить порог уведомления', }, proxy: { title: 'Верхнеуровневый прокси', description: 'Настроить прокси для исходящих запросов к Google/Gemini API.', enable: 'Включить прокси', url: 'URL прокси', timeout: 'Тайм-аут запроса (сек)', accountProxies: { title: 'Прокси аккаунтов', description: 'Настройка индивидуальных прокси для каждого аккаунта. Эти настройки переопределят глобальный прокси для данного аккаунта.', }, }, modelMapping: { title: 'Маппинг моделей', description: 'Сопоставьте модели Claude Code с моделями Gemini Nexus. Оптимизируйте затраты и скорость, разумно маршрутизируя запросы.', claudeKeyword: 'Модель Claude (Ключевое слово)', targetGemini: 'Целевая модель Gemini', addPlaceholderKey: 'например, op-3', addPlaceholderValue: 'например, gemini-3-flash', noMappings: 'Нет пользовательских сопоставлений.', mapsTo: 'Мапится в', default: 'По умолчанию', restoreDefaults: 'Сбросить по умолчанию', }, modelVisibility: { title: 'Видимость моделей', description: 'Управляйте тем, какие модели отображаются в карточках аккаунтов. Скрытые модели не будут показаны в отображении квот.', searchPlaceholder: 'Поиск моделей...', showAll: 'Показать все', hideAll: 'Скрыть все', reset: 'Сбросить по умолчанию', save: 'Сохранить изменения', noModels: 'Модели не найдены', modelsShown: '{{visible}} из {{total}} моделей видно', quotaManagement: 'Управление квотами', hidden: 'Скрыто', noModelsFound: 'Модели не найдены', totalModels: 'Всего', visibleModels: 'Видно', hiddenModels: 'Скрыто', saving: 'Сохранение...', }, providerGroupings: { title: 'Группировка провайдеров', description: 'Группировка моделей по провайдерам для лучшей организации', enabled: 'Включить группировку провайдеров', models: '{{count}} моделей', avgLabel: 'сред.', resetLabel: 'сброс', overall: 'Общее', healthy: 'Исправно', degraded: 'Снижено', limited: 'Ограничено', critical: 'Критично', }, examples: { title: 'Примеры использования', description: 'Примеры команд для вызова локального API прокси.', curl: 'cURL', python: 'Python', copy: 'Копировать', copied: 'Скопировано!', openai_protocol: 'Протокол OpenAI', anthropic_protocol: 'Протокол Anthropic', openai_tools: 'Cursor, Windsurf, NextChat', anthropic_tools: 'Claude Code CLI', flash: 'Быстрый (Flash)', pro: 'Про (Pro)', flash_preview: 'Превью (Flash Preview)', pro_high: 'Лучший (Pro High)', sonnet: 'Мыслящий (Sonnet)', opus: 'Opus', }, gateway: { title: 'Служба API Прокси', description: 'Управление локальным прокси-сервером API.', status_running: 'Запущено', status_stopped: 'Остановлено', action_start: 'Запустить службу', action_stop: 'Остановить службу', accounts_info: '{{count}} аккаунтов доступно', port: 'Порт прослушивания', port_hint: 'По умолчанию 8045, требуется перезапуск для применения', timeout: 'Тайм-аут запроса', timeout_hint: 'По умолчанию 120с, диапазон 30-600с', api_key: 'API Ключ', regenerate_key: 'Перегенерировать', regenerateConfirm: { title: 'Перегенерировать API ключ?', description: 'Это немедленно сделает текущий ключ недействительным. Все приложения, использующие старый ключ, перестанут работать.', cancel: 'Отмена', confirm: 'Перегенерировать', }, key_warning: 'Держите ваш API ключ в секрете. Не передавайте его никому.', auto_start: 'Автозапуск с приложением', auto_start_desc: 'Запускать прокси-службу при старте приложения', }, proxy_tab: 'Прокси', save: 'Сохранить настройки', }, toast: { backupSuccess: { title: 'Успешно', description: 'Бэкап аккаунта создан.', }, backupError: { title: 'Ошибка', description: 'Не удалось создать бэкап: {{error}}', }, switchSuccess: { title: 'Успешно', description: 'Аккаунт переключен.', }, switchError: { title: 'Ошибка', description: 'Не удалось переключить аккаунт: {{error}}', }, deleteSuccess: { title: 'Успешно', description: 'Бэкап удален.', }, deleteError: { title: 'Ошибка', description: 'Не удалось удалить бэкап: {{error}}', }, }, cloud: { title: 'Аккаунты', description: 'Управление пулом аккаунтов Google Gemini.', autoSwitch: 'Авто-переключение', providerGroupings: 'Группировка по провайдерам', addAccount: 'Добавить аккаунт', syncFromIDE: 'Синхр. из IDE', checkQuota: 'Проверить квоту', polling: 'Опрос запущен', globalQuota: 'Глобальная квота', layout: { auto: 'Авто', twoCol: '2 колонки', threeCol: '3 колонки', list: 'Список', compact: 'Компактный', }, authDialog: { title: 'Добавить Google Аккаунт', description: 'Для добавления аккаунта необходимо авторизовать приложение.', oauthClient: 'OAuth клиент', oauthClientPlaceholder: 'Выберите OAuth клиент', openLogin: 'Открыть страницу входа', authCode: 'Код авторизации', placeholder: 'Вставьте код, начинающийся с 4/...', instruction: 'Откроется браузер для входа в Google. Скопируйте код со страницы localhost и вставьте сюда.', verify: 'Проверить и добавить', }, card: { active: 'Активен', use: 'Использовать', rateLimited: 'Лимит исчерпан', validationRiskControlled: 'Риск / Ограничение', validationOAuthReauthRequired: 'Требуется повторный OAuth', validationRequired: 'Требуется проверка', left: 'ост.', used: 'Исп.', unknown: 'Неизвестный', actions: 'Действия', useAccount: 'Использовать этот аккаунт', identityProfile: 'Профиль идентичности', refresh: 'Обновить квоту', delete: 'Удалить аккаунт', noQuota: 'Нет данных', rateLimitedQuota: 'Лимит исчерпан', resetPrefix: 'Сброс', resetTime: 'Время сброса', resetUnknown: 'Неизвестно', gemini3Ready: 'Gemini 3 готов', groupGoogleGemini: 'Google Gemini', groupAnthropicClaude: 'Anthropic Claude', proxy: 'Прокси', proxyPlaceholder: 'напр. http://127.0.0.1:7890', proxySaved: 'Прокси сохранён', noProxy: 'Без прокси', aiCredits: 'AI Кредиты', aiCreditsValue: '{{amount}} кредитов', creditsExpiry: 'истекает {{date}}', modelVisibility: 'Видимость моделей', }, identity: { title: 'Профиль идентичности', loading: 'Загрузка...', generateAndBind: 'Создать и привязать', captureAndBind: 'Считать текущий и привязать', restoreOriginal: 'Восстановить базовый профиль', openFolder: 'Открыть хранилище профилей', previewTitle: 'Предпросмотр сгенерированного профиля', confirm: 'Подтвердить', cancel: 'Отмена', close: 'Закрыть', currentStorage: 'Текущий профиль окружения', accountBinding: 'Профиль, привязанный к аккаунту', history: 'История профилей', noHistory: 'История профилей пуста', current: 'Активный', restore: 'Восстановить', generateSuccess: 'Профиль создан и привязан', captureSuccess: 'Текущий профиль считан и привязан', restoreOriginalSuccess: 'Базовый профиль восстановлен', restoreVersionSuccess: 'Исторический профиль восстановлен', deleteVersionSuccess: 'Исторический профиль удален', openFolderSuccess: 'Хранилище профилей открыто', baseline: 'Базовый профиль', }, list: { noAccounts: 'Нет добавленных облачных аккаунтов.', }, error: { loadFailed: 'Не удалось загрузить аккаунты.', }, toast: { syncSuccess: { title: 'Синхронизация успешна', description: 'Импортирован {{email}} из IDE.', }, syncFailed: { title: 'Синхронизация не удалась', description: 'В базе данных IDE не найдено активных аккаунтов.', }, addSuccess: 'Аккаунт успешно добавлен!', addFailed: { title: 'Не удалось добавить аккаунт', }, quotaRefreshed: 'Квота обновлена', refreshFailed: 'Не удалось обновить квоту', pollFailed: 'Не удалось опросить квоты всех аккаунтов', switched: { title: 'Аккаунт переключен!', description: 'Перезапуск Gemini Nexus...', }, switchFailed: 'Не удалось переключить аккаунт', deleted: 'Аккаунт удален', deleteFailed: 'Не удалось удалить аккаунт', deleteConfirm: 'Вы уверены, что хотите удалить этот аккаунт?', autoSwitchOn: 'Авто-переключение включено', autoSwitchOff: 'Авто-переключение выключено', updateSettingsFailed: 'Не удалось обновить настройки', actionFailed: 'Не удалось выполнить действие', startAuthFailed: 'Не удалось запустить процесс входа', refreshCreditsAvailable: 'AI кредиты: {{amount}}', refreshCreditsUnavailable: 'AI кредиты недоступны для этого обновления.', batchRefreshSuccess: 'Успешно обновлено {{count}} аккаунтов.', batchRefreshPartial: { title: 'Обновление завершено с проблемами', description: 'Обновлено {{successful}} аккаунтов, {{failed}} с ошибкой.', }, batchDeleteSuccess: 'Успешно удалено {{count}} аккаунтов.', batchDeletePartial: { title: 'Удаление завершено с проблемами', description: 'Удалено {{successful}} аккаунтов, {{failed}} с ошибкой.', }, }, batch: { selected: 'Выбрано {{count}}', delete: 'Удалить выбранные', refresh: 'Обновить выбранные', selectAll: 'Выбрать все', clear: 'Снять выделение', confirmDelete: 'Вы уверены, что хотите удалить {{count}} аккаунтов?', }, sort: { recentlyUsed: 'Недавние', quotaOverall: 'Общая квота', quotaClaude: 'Квота Claude', quotaPro3: 'Квота Pro3', quotaFlash: 'Квота Flash', }, exportImport: { export: 'Экспорт', import: 'Импорт', exportTitle: 'Экспорт аккаунтов', exportDesc: 'Выберите, включать ли токены аутентификации в файл экспорта.', includeTokens: 'Включить токены (менее безопасно)', stripTokens: 'Удалить токены (безопаснее для обмена)', exportSuccess: 'Аккаунты успешно экспортированы', importTitle: 'Импорт аккаунтов', importDesc: 'Выберите ранее экспортированный JSON файл.', importStrategy: 'Стратегия импорта', strategyMerge: 'Объединить - Обновить существующие, добавить новые', strategyOverwrite: 'Перезаписать - Заменить все существующие данные', strategySkip: 'Пропустить - Добавить только новые аккаунты', importSuccess: 'Импортировано {{imported}}, обновлено {{updated}}, пропущено {{skipped}}', importErrors: 'Импорт завершён с {{count}} ошибкой(ами)', selectFile: 'Выбрать файл', importing: 'Импорт...', fileTooLarge: 'Размер файла превышает лимит в 5 МБ', invalidJson: 'Некорректный формат JSON-файла', readFileFailed: 'Не удалось прочитать файл', }, }, proxy: { title: 'API Прокси', description: 'Управление локальным прокси-сервером API.', save: 'Сохранить', copy: 'Копировать', copied: 'Скопировано!', regenerate: 'Перегенерировать', regenerateConfirm: { title: 'Перегенерировать API ключ?', description: 'Это немедленно сделает текущий ключ недействительным. Все приложения, использующие старый ключ, перестанут работать.', cancel: 'Отмена', confirm: 'Перегенерировать', }, service: { title: 'Статус сервиса', description: 'Управление локальным сервером.', running: 'Работает', stopped: 'Остановлен', start: 'Запустить', stop: 'Остановить', }, config: { port: 'Порт', timeout: 'Тайм-аут', api_key: 'API Ключ', auto_start: 'Автозапуск', auto_start_desc: 'Запускать прокси при старте приложения', local_access: 'Доступ из локальной сети:', select_ip: 'Выбрать IP', no_token_warning: '⚠️ API ключ не установлен. Доступ открыт всем!', show_key: 'Показать', hide_key: 'Скрыть', }, mapping: { title: 'Маппинг моделей', description: 'Настройка маршрутизации моделей.', maps_to: '->', restore: 'Сброс', }, examples: { title: 'Примеры', description: 'Примеры использования локального прокси.', }, }, usage: { title: 'Использование токенов', description: 'Мониторинг потребления API токенов.', range24h: 'Последние 24 часа', range7d: 'Последние 7 дней', range30d: 'Последние 30 дней', totalTokens: 'Всего токенов', promptTokens: 'Prompt токены', completionTokens: 'Completion токены', totalRequests: 'Всего запросов', dailyUsage: 'Ежедневное использование', byModel: 'По моделям', hourlyUsage: 'Почасовое использование', loadFailed: 'Не удалось загрузить данные об использовании.', retry: 'Повторить', allAccounts: 'Все аккаунты', noData: 'Нет данных', }, }, }, }, });