export type UiLanguage = 'zh' | 'en';

const zh = {
  'common.cancel': '取消',
  'common.close': '关闭',
  'common.closeDrawer': '关闭抽屉',
  'common.confirm': '确定',
  'common.delete': '删除',
  'common.deleting': '删除中',
  'common.details': '查看详情',
  'common.disabled': '未启用',
  'common.enabled': '已启用',
  'common.failure': '失败',
  'common.hideContent': '隐藏内容',
  'common.itemsCount': '{count}只',
  'common.loading': '正在加载',
  'common.noData': '暂无数据',
  'common.processing': '处理中...',
  'common.readOnly': '只读',
  'common.retry': '重试',
  'common.selectAllCurrent': '全选当前',
  'common.selectPlaceholder': '请选择',
  'common.selectedCount': '已选 {count}',
  'common.sensitive': '敏感',
  'common.showContent': '显示内容',
  'common.success': '成功',
  'common.copy': '复制',
  'common.copied': '已复制!',

  'language.current': '中文',
  'language.english': 'English',
  'language.short.en': 'EN',
  'language.short.zh': '中',
  'language.toggle': '切换界面语言',
  'language.uiLanguage': '界面语言',

  'theme.dark': '深色',
  'theme.light': '浅色',
  'theme.menu': '主题模式',
  'theme.system': '跟随系统',
  'theme.theme': '主题',
  'theme.toggle': '切换主题',

  'layout.appFallbackDescription': 'Web workspace',
  'layout.appFallbackTitle': 'Daily Stock Analysis',
  'layout.collapseSidebar': '折叠侧边栏',
  'layout.desktopSidebar': '桌面侧边导航',
  'layout.expandSidebar': '展开侧边栏',
  'layout.mainNav': '主导航',
  'layout.nav.alerts': '告警',
  'layout.nav.backtest': '回测',
  'layout.nav.chat': '问股',
  'layout.nav.decisionSignals': 'AI 建议',
  'layout.nav.home': '首页',
  'layout.nav.portfolio': '持仓',
  'layout.nav.settings': '设置',
  'layout.nav.screening': '选股',
  'layout.nav.usage': '用量',
  'layout.navMenu': '导航菜单',
  'layout.newChatMessage': '问股有新消息',
  'layout.openNav': '打开导航菜单',
  'layout.route.alerts.description': '规则、触发记录与通知尝试',
  'layout.route.alerts.title': '告警',
  'layout.route.backtest.description': '回测任务与结果浏览',
  'layout.route.backtest.title': '回测',
  'layout.route.chat.description': '多轮策略问答与历史会话管理',
  'layout.route.chat.title': '问股',
  'layout.route.decisionSignals.description': 'AI 建议、风险与观察条件',
  'layout.route.decisionSignals.title': 'AI 建议',
  'layout.route.home.description': '股票分析与历史报告工作台',
  'layout.route.home.title': '首页',
  'layout.route.portfolio.description': '组合快照、手工录入与风险分析',
  'layout.route.portfolio.title': '持仓',
  'layout.route.settings.description': '系统配置、模型与认证管理',
  'layout.route.settings.title': '设置',
  'layout.route.screening.description': 'AlphaSift 策略选股与候选研究',
  'layout.route.screening.title': '选股',
  'layout.route.usage.description': 'LLM Token 消耗与模型调用明细',
  'layout.route.usage.title': '用量',
  'layout.logout': '退出',
  'layout.logoutConfirm': '确认退出',
  'layout.logoutMessage': '确认退出当前登录状态吗？退出后需要重新输入密码。',
  'layout.logoutTitle': '退出登录',

  'usage.breakdown': 'Breakdown',
  'usage.callType.agent': '问股 Agent',
  'usage.callType.analysis': '个股分析',
  'usage.callType.marketReview': '大盘复盘',
  'usage.callType.unknown': '{type}',
  'usage.callTypeDetail': '{calls} 次 · Prompt {prompt} · Completion {completion}',
  'usage.callTypeTitle': '调用类型',
  'usage.calls': '{count} 次调用',
  'usage.completionTokens': 'Completion tokens',
  'usage.completionTokensHint': '模型输出消耗',
  'usage.dateRange': '{from} 至 {to}',
  'usage.description': '查看 LLM 调用次数、Prompt/Completion Token 消耗、模型用量和最近调用明细。',
  'usage.emptyDescription': '完成一次分析、大盘复盘或问股调用后，这里会显示模型用量。',
  'usage.emptyTitle': '暂无 Token 用量记录',
  'usage.error.message': 'Token 用量数据加载失败',
  'usage.error.title': 'Token 用量加载失败',
  'usage.eyebrow': 'Usage',
  'usage.maxSingleCall': '单次峰值',
  'usage.modelUsage': '模型用量',
  'usage.modelUsageDescription': '按模型聚合 Token 消耗、调用次数和单次峰值。',
  'usage.noRecentCalls': '暂无最近调用记录',
  'usage.period.all': '全部',
  'usage.period.month': '本月',
  'usage.period.today': '今日',
  'usage.promptTokens': 'Prompt tokens',
  'usage.promptTokensHint': '输入上下文消耗',
  'usage.recentCalls': '最近调用',
  'usage.recentCallsDescription': '最近 50 条 LLM token 审计记录。',
  'usage.refresh': '刷新',
  'usage.table.model': '模型',
  'usage.table.time': '时间',
  'usage.table.type': '类型',
  'usage.title': 'Token 用量监控',
  'usage.totalCalls': '调用次数',
  'usage.totalCallsHint': '已记录的 LLM 调用',
  'usage.totalTokens': '总 tokens',

  'routeError.backHome': '返回首页',
  'routeError.description': '当前页面资源或组件未能正常加载，可能是网络中断或页面版本已更新。请重新加载页面，或返回首页后再试。',
  'routeError.reload': '重新加载页面',
  'routeError.title': '页面加载失败',
  'notFound.backHome': '返回首页',
  'notFound.description': '抱歉，您访问的页面不存在或已被移动',
  'notFound.pageTitle': '页面未找到 - DSA',
  'notFound.title': '页面未找到',

  'login.adminLogin': '管理员登录',
  'login.adminPassword': '管理员密码',
  'login.confirmPassword': '确认密码',
  'login.confirmPasswordPlaceholder': '再次确认管理员密码',
  'login.loginDescription': '访问 DSA 量化决策引擎需要有效的身份凭证。',
  'login.loginFailed': '登录失败',
  'login.loginPassword': '登录密码',
  'login.loginPasswordPlaceholder': '请输入密码',
  'login.loginSubmit': '授权进入工作台',
  'login.loginSubmitting': '正在建立连接...',
  'login.pageTitle': '登录 - DSA',
  'login.passwordMismatch': '两次输入的密码不一致',
  'login.setupDescription': '首次启用认证，请为系统工作台设置管理员密码。',
  'login.setupFailed': '配置失败',
  'login.setupPasswordPlaceholder': '请设置 6 位以上密码',
  'login.setupSubmit': '完成设置并登录',
  'login.setupSubmitting': '初始化中...',
  'login.setupTitle': '设置初始密码',
  'login.validationFailed': '验证未通过',

  'home.analyze': '分析',
  'home.analyzing': '分析中',
  'home.askAi': '追问 AI',
  'home.defaultStrategyDescription': '沿用系统默认分析框架',
  'home.defaultStrategyName': '默认策略',
  'home.duplicateTask': '任务已存在',
  'home.goSettings': '去配置',
  'home.historyButton': '历史记录',
  'home.historyTrend': '历史趋势',
  'home.inputInvalid': '输入有误',
  'home.loadingReport': '加载报告中...',
  'home.marketReview': '大盘复盘',
  'home.marketReviewCompleted': '大盘复盘已完成',
  'home.marketReviewCompletedWithReport': '大盘复盘任务已完成，结果如下：',
  'home.marketReviewCompletedWithoutReport': '大盘复盘任务已完成，结果已生成并按配置推送。',
  'home.marketReviewFailed': '大盘复盘执行失败。',
  'home.marketReviewHistoryEmptyDescription': '运行大盘复盘后，这里会集中展示历史记录。',
  'home.marketReviewHistoryEmptyTitle': '暂无大盘复盘',
  'home.marketReviewHistoryTitle': '大盘复盘历史',
  'home.marketReviewInProgress': '大盘复盘进行中',
  'home.marketReviewSubmitted': '大盘复盘已提交',
  'home.marketReviewTimeout': '大盘复盘已超时',
  'home.marketReviewTimeoutMessage': '任务长时间未返回最终结果，请在任务列表/历史中查看。',
  'home.marketReviewUnknownStatus': '大盘复盘状态异常',
  'home.notify': '推送通知',
  'home.pageTitle': '每日选股分析 - DSA',
  'home.placeholder': '输入股票代码或名称，如 600519、贵州茅台、AAPL',
  'home.progressActive': '进行中',
  'home.reanalyze': '重新分析',
  'home.rerunMarketReview': '重新复盘',
  'home.fullReport': '完整分析报告',
  'home.setupIncomplete': '基础配置未完成',
  'home.setupMissingGeneric': '还缺少基础配置，完成后即可开始最小可用分析。',
  'home.setupMissingWithLabels': '还缺少 {labels}，完成后即可开始最小可用分析。',
  'home.startAnalysisDescription': '输入股票代码进行分析，或从左侧选择历史报告查看。',
  'home.startAnalysisTitle': '开始分析',
  'home.strategy': '策略',
  'home.submitMarketReview': '提交中',
  'home.taskStatus': '任务状态：{status}（{progress}）',
  'home.unknownTaskStatus': '收到未知任务状态：{status}',

  'decisionSignals.action': '动作',
  'decisionSignals.active': '有效',
  'decisionSignals.activeOnly': '默认展示 active 信号',
  'decisionSignals.allActions': '全部动作',
  'decisionSignals.allMarkets': '全部市场',
  'decisionSignals.allPhases': '全部阶段',
  'decisionSignals.allSources': '全部来源',
  'decisionSignals.allStatuses': '全部状态',
  'decisionSignals.archive': '归档',
  'decisionSignals.archiveConfirm': '确认将这条信号归档吗？归档后不会再作为当前 active 建议展示。',
  'decisionSignals.archived': '已归档',
  'decisionSignals.close': '关闭信号',
  'decisionSignals.closeConfirm': '确认关闭这条信号吗？关闭表示你不再跟踪这条建议。',
  'decisionSignals.closed': '已关闭',
  'decisionSignals.confidence': '置信度',
  'decisionSignals.confirmStatusTitle': '更新信号状态',
  'decisionSignals.createdAt': '创建时间',
  'decisionSignals.catalystSummary': '催化',
  'decisionSignals.dataQuality': '数据质量',
  'decisionSignals.description': '按股票、阶段、来源和状态查询结构化 AI 建议，并保留风险与数据质量上下文。',
  'decisionSignals.detailTitle': '信号详情',
  'decisionSignals.directionExpected': '预期方向',
  'decisionSignals.emptyDescription': '完成一次普通个股分析后，系统会从报告中沉淀可查询的结构化建议。',
  'decisionSignals.emptyTitle': '暂无决策信号',
  'decisionSignals.entryRange': '入场区间',
  'decisionSignals.errorTitle': '决策信号加载失败',
  'decisionSignals.evidence': '证据',
  'decisionSignals.expired': '已过期',
  'decisionSignals.expiresAt': '过期时间',
  'decisionSignals.feedback.not_useful': '无用',
  'decisionSignals.feedback.useful': '有用',
  'decisionSignals.feedbackNone': '暂无反馈',
  'decisionSignals.feedbackTitle': '用户反馈',
  'decisionSignals.filter': '筛选',
  'decisionSignals.horizon': '周期',
  'decisionSignals.horizon.1d': '1 日',
  'decisionSignals.horizon.3d': '3 日',
  'decisionSignals.horizon.5d': '5 日',
  'decisionSignals.horizon.10d': '10 日',
  'decisionSignals.horizon.intraday': '盘中',
  'decisionSignals.horizon.long': '长期',
  'decisionSignals.horizon.swing': '波段',
  'decisionSignals.invalidation': '失效条件',
  'decisionSignals.invalidate': '标记失效',
  'decisionSignals.invalidateConfirm': '确认将这条信号标记为失效吗？失效后不会再作为当前 active 建议展示。',
  'decisionSignals.invalidated': '已失效',
  'decisionSignals.latestButton': '查询最新',
  'decisionSignals.latestDescription': '输入股票代码，直接读取该股票最新 active 信号。',
  'decisionSignals.latestInput': '最新股票代码',
  'decisionSignals.latestPlaceholder': '例如 600519、HK00700、AAPL',
  'decisionSignals.latestTitle': '按股票查询最新信号',
  'decisionSignals.market': '市场',
  'decisionSignals.market.cn': 'A 股',
  'decisionSignals.market.hk': '港股',
  'decisionSignals.market.jp': '日股',
  'decisionSignals.market.kr': '韩股',
  'decisionSignals.market.tw': '台股',
  'decisionSignals.market.us': '美股',
  'decisionSignals.marketPhase': '阶段',
  'decisionSignals.marketPhase.closing_auction': '集合竞价',
  'decisionSignals.marketPhase.intraday': '盘中',
  'decisionSignals.marketPhase.lunch_break': '午间休市',
  'decisionSignals.marketPhase.non_trading': '非交易时段',
  'decisionSignals.marketPhase.postmarket': '盘后',
  'decisionSignals.marketPhase.premarket': '盘前',
  'decisionSignals.marketPhase.unknown': '未知阶段',
  'decisionSignals.metadata': '元数据',
  'decisionSignals.noLatestDescription': '该股票当前没有 active 信号，或信号已过期。',
  'decisionSignals.noLatestTitle': '暂无最新有效信号',
  'decisionSignals.noOutcomes': '暂无后验结果',
  'decisionSignals.noStatsDescription': '触发一次信号后验计算后，这里会显示命中、未命中和无法评估统计。',
  'decisionSignals.noStatsTitle': '暂无后验统计',
  'decisionSignals.outcome.hit': '命中',
  'decisionSignals.outcome.miss': '未命中',
  'decisionSignals.outcome.neutral': '中性',
  'decisionSignals.outcome.unable': '无法评估',
  'decisionSignals.outcomes': '后验结果',
  'decisionSignals.pageTitle': 'AI 建议 - DSA',
  'decisionSignals.planQuality': '计划质量',
  'decisionSignals.planQuality.complete': '完整',
  'decisionSignals.planQuality.minimal': '最小',
  'decisionSignals.planQuality.partial': '部分',
  'decisionSignals.planQuality.unknown': '未知',
  'decisionSignals.pricePlan': '价格计划',
  'decisionSignals.profile': '风格',
  'decisionSignals.reason': '理由',
  'decisionSignals.refresh': '刷新',
  'decisionSignals.returnPct': '区间收益',
  'decisionSignals.riskSummary': '风险',
  'decisionSignals.score': '评分',
  'decisionSignals.source': '来源',
  'decisionSignals.sourceType.agent': 'Agent',
  'decisionSignals.sourceType.alert': '告警',
  'decisionSignals.sourceType.analysis': '分析报告',
  'decisionSignals.sourceType.manual': '手动',
  'decisionSignals.sourceType.market_review': '大盘复盘',
  'decisionSignals.sourceReport': '来源报告',
  'decisionSignals.sourceReportId': '来源报告 ID',
  'decisionSignals.statsDescription': '基于当前后验引擎版本统计信号表现，默认排除已归档信号。',
  'decisionSignals.statsErrorTitle': '后验统计加载失败',
  'decisionSignals.statsHitRate': '命中率',
  'decisionSignals.statsTitle': '信号表现统计',
  'decisionSignals.statsTotal': '评估数',
  'decisionSignals.status': '状态',
  'decisionSignals.stockCode': '股票代码',
  'decisionSignals.stopLoss': '止损',
  'decisionSignals.targetPrice': '目标价',
  'decisionSignals.title': 'AI 建议',
  'decisionSignals.total': '共 {total} 条信号',
  'decisionSignals.timelineAlertShape': '菱形点表示 alert',
  'decisionSignals.timelineDescription': '按单支股票查看同一建议随时间变化的轨迹。',
  'decisionSignals.timelineEmptyDescription': '当前时间范围内没有该股票的信号。',
  'decisionSignals.timelineEmptyTitle': '暂无时间线信号',
  'decisionSignals.timelineErrorTitle': '时间线加载失败',
  'decisionSignals.timelineFamilyBullish': '偏多',
  'decisionSignals.timelineFamilyDefensive': '防御',
  'decisionSignals.timelineFamilyNeutral': '中性',
  'decisionSignals.timelineGuideDescription': '输入股票代码后再查询；不会在空股票代码时拉取全局信号。',
  'decisionSignals.timelineGuideTitle': '输入股票代码查看时间线',
  'decisionSignals.timelineMarket': '时间线市场',
  'decisionSignals.timelineRange': '时间范围',
  'decisionSignals.timelineRange.30d': '30 天',
  'decisionSignals.timelineRange.90d': '90 天',
  'decisionSignals.timelineRange.180d': '180 天',
  'decisionSignals.timelineSearch': '查询时间线',
  'decisionSignals.timelineSelected': '已选第 {index} 个点',
  'decisionSignals.timelineStatus': '时间线状态',
  'decisionSignals.timelineStatus.active': '仅有效',
  'decisionSignals.timelineStatus.all': '全部历史',
  'decisionSignals.timelineStockCode': '时间线股票代码',
  'decisionSignals.timelineStockPlaceholder': '例如 600519、HK00700、AAPL',
  'decisionSignals.timelineTitle': '股票信号时间线',
  'decisionSignals.timelineTruncatedDescription': '仅展示最近 100 条信号，请缩小时间范围。',
  'decisionSignals.timelineTruncatedTitle': '时间线已截断',
  'decisionSignals.unableReason': '无法评估原因',
  'decisionSignals.watchConditions': '观察条件',
  'decisionSignals.viewDetailsFor': '查看 {stock} AI 建议详情',
  'decisionSignals.portfolioColumn': 'AI 建议',
  'decisionSignals.portfolioEmpty': '—',
  'decisionSignals.portfolioLoading': '加载中',
  'decisionSignals.portfolioPartialWarning': 'AI 建议只加载了部分数据：{message}',
  'decisionSignals.portfolioWarningTitle': 'AI 建议降级',

  'history.analysisCount': '{count}次',
  'history.bottomReached': '已到底部',
  'history.defaultEmptyDescription': '完成首次分析后，这里会保留最近结果。',
  'history.defaultEmptyTitle': '暂无历史分析记录',
  'history.defaultTitle': '历史分析',
  'history.deleteRecord': '删除 {name} 历史记录',
  'history.itemAria': '{name} {code} 历史记录',
  'history.loading': '加载历史记录中...',
  'history.actionAdd': '加仓',
  'history.actionAlert': '预警',
  'history.actionAvoid': '回避',
  'history.actionBuy': '买入',
  'history.actionHold': '持有',
  'history.actionReduce': '减仓',
  'history.actionSell': '卖出',
  'history.actionWatch': '观望',
  'history.sentiment': '情绪',
  'history.selectAllHistoryAria': '全选当前已加载历史记录',
  'history.selectAllStockAria': '全选当前个股',
  'stockBar.emptyDescription': '完成首次分析后，这里将按股票展示最新分析结果。',
  'stockBar.emptyTitle': '暂无个股记录',
  'stockBar.loading': '加载个股中...',
  'stockBar.market': '大盘',
  'stockBar.title': '个股栏',

  'stockTrend.allHistory': '全部历史',
  'stockTrend.averageScore': '平均分 {score}',
  'stockTrend.backToCurrentReport': '返回当前报告',
  'stockTrend.currentAdvice': '当前观点',
  'stockTrend.currentScore': '当前分数',
  'stockTrend.historyModelCount': '历史模型 {count} 种',
  'stockTrend.loadedSummary': '已加载 {loaded} / {total} 条 · 排序：最新优先 · 模型：全部',
  'stockTrend.loadFailed': '历史趋势加载失败',
  'stockTrend.loading': '加载同股历史中...',
  'stockTrend.loadMore': '加载更多',
  'stockTrend.loadingMore': '加载中...',
  'stockTrend.latestTime': '最近一次 {time}',
  'stockTrend.model': '模型',
  'stockTrend.modelCountSuffix': '{count}次',
  'stockTrend.moreEmptyDescription': '完成多次分析后，这里会展示观点变化、评分走势和模型记录。',
  'stockTrend.moreEmptyTitle': '暂无更多同股历史分析',
  'stockTrend.neverRecorded': '未记录',
  'stockTrend.noModelTitle': '未记录模型',
  'stockTrend.records': '历史分析记录',
  'stockTrend.reload': '重新加载',
  'stockTrend.report': '查看报告',
  'stockTrend.result': '分析结果',
  'stockTrend.score': '分数',
  'stockTrend.stockPrice': '股价',
  'stockTrend.table.action': '操作',
  'stockTrend.time': '时间',
  'stockTrend.title': '历史趋势',
  'stockTrend.volumeRatio': '量比',
  'stockTrend.window30': '近30天',
  'stockTrend.window90': '近90天',
  'stockTrend.changePct': '涨跌幅',
  'stockTrend.turnoverRate': '换手率',

  'taskPanel.diagnostics': '运行诊断',
  'taskPanel.pending': '等待中',
  'taskPanel.pendingTasks': '{count} 等待中',
  'taskPanel.processing': '分析中',
  'taskPanel.processingAria': '任务进行中',
  'taskPanel.processingTasks': '{count} 进行中',
  'taskPanel.cancelRequested': '请求取消',
  'taskPanel.cancelRequestedAria': '任务请求取消',
  'taskPanel.cancelled': '已取消',
  'taskPanel.pendingAria': '任务等待中',
  'taskPanel.openRunFlow': '查看运行流',
  'taskPanel.openRunFlowAria': '查看 {stock} 运行流',
  'taskPanel.statusAria': '任务状态：{status}',
  'taskPanel.title': '分析任务',

  'runFlow.drawerTitle': '运行流',
  'runFlow.eyebrow': '运行流',
  'runFlow.title': '数据流与信息流',
  'runFlow.open': '查看运行流',
  'runFlow.openHistoryAria': '查看历史记录 {recordId} 运行流',
  'runFlow.taskDrawerTitle': '{stock} 运行流',
  'runFlow.historyDrawerTitle': '{stock} 历史运行流',
  'runFlow.loadingTitle': '正在加载运行流',
  'runFlow.loadingDescription': '正在读取任务快照、运行诊断和事件链路。',
  'runFlow.errorTitle': '运行流加载失败',
  'runFlow.retry': '重新加载',
  'runFlow.refresh': '刷新',
  'runFlow.refreshing': '刷新中',
  'runFlow.emptyTitle': '暂无运行流',
  'runFlow.emptyDescription': '请选择一个活跃任务或历史报告查看运行流。',
  'runFlow.emptySnapshotTitle': '暂无运行流细节',
  'runFlow.emptySnapshotDescription': '当前快照没有节点或事件；缺少 diagnostics 时会显示骨架或空状态。',
  'runFlow.valueUnavailable': '未记录',
  'runFlow.durationMs': '{value} ms',
  'runFlow.durationSeconds': '{value} 秒',
  'runFlow.durationMinutes': '{value} 分钟',
  'runFlow.status.pending': '等待中',
  'runFlow.status.running': '运行中',
  'runFlow.status.success': '成功',
  'runFlow.status.failed': '失败',
  'runFlow.status.degraded': '部分降级',
  'runFlow.status.fallback': '降级回退',
  'runFlow.status.timeout': '超时',
  'runFlow.status.cancelRequested': '请求取消',
  'runFlow.status.cancelled': '已取消',
  'runFlow.status.skipped': '已跳过',
  'runFlow.status.unknown': '未知',
  'runFlow.severity.info': '信息',
  'runFlow.severity.success': '成功',
  'runFlow.severity.warning': '告警',
  'runFlow.severity.danger': '危险',
  'runFlow.edge.data': '数据',
  'runFlow.edge.control': '控制',
  'runFlow.edge.fallback': '降级回退',
  'runFlow.edge.retry': '重试',
  'runFlow.edgeLabel.invoke': '调用',
  'runFlow.edgeLabel.details': '详情',
  'runFlow.nodeKind.entry': '入口',
  'runFlow.nodeKind.queue': '队列',
  'runFlow.nodeKind.dataSource': '数据源',
  'runFlow.nodeKind.analysis': '分析',
  'runFlow.nodeKind.model': '模型',
  'runFlow.nodeKind.artifact': '产物',
  'runFlow.nodeKind.notification': '通知',
  'runFlow.summary.elapsed': '总耗时',
  'runFlow.summary.fallbackCount': '降级回退/重试',
  'runFlow.summary.failedAttempts': '失败尝试',
  'runFlow.summary.dataSources': '数据源',
  'runFlow.summary.task': 'Task',
  'runFlow.summary.trace': 'Trace',
  'runFlow.summary.model': '模型',
  'runFlow.summary.generatedAt': '生成时间',
  'runFlow.graph.title': '运行拓扑',
  'runFlow.graph.description': '自动分层展示入口、数据来源、分析引擎和产物链路。',
  'runFlow.graph.nodeAria': '{label} 节点，状态 {status}',
  'runFlow.graph.startedAt': '开始',
  'runFlow.graph.expand': '展开',
  'runFlow.graph.collapse': '收起',
  'runFlow.graph.expandNode': '展开 {label} 运行尝试',
  'runFlow.graph.collapseNode': '收起 {label} 运行尝试',
  'runFlow.events.title': '事件流',
  'runFlow.events.count': '{count} 条事件',
  'runFlow.events.filters': '事件筛选',
  'runFlow.events.filter.all': '全部',
  'runFlow.events.filter.important': '关键',
  'runFlow.events.filter.problems': '失败/告警',
  'runFlow.events.filter.fallback': '降级回退/重试',
  'runFlow.events.filter.cancelled': '取消',
  'runFlow.events.openNode': '查看事件 {title} 关联节点',
  'runFlow.events.empty': '当前筛选下暂无事件。',
  'runFlow.nodeDetails.empty': '选择一个节点查看详情。',
  'runFlow.nodeDetails.title': '节点详情',
  'runFlow.nodeDetails.close': '关闭节点详情',
  'runFlow.nodeDetails.kind': '类型',
  'runFlow.nodeDetails.version': '版本',
  'runFlow.nodeDetails.provider': '提供方',
  'runFlow.nodeDetails.duration': '耗时',
  'runFlow.nodeDetails.attempts': '尝试次数',
  'runFlow.nodeDetails.recordCount': '记录数',
  'runFlow.nodeDetails.startedAt': '开始时间',
  'runFlow.nodeDetails.endedAt': '结束时间',
  'runFlow.nodeDetails.metadata': '元数据',
  'runFlow.nodeDetails.expandAttempts': '展开尝试',
  'runFlow.nodeDetails.collapseAttempts': '收起尝试',
  'runFlow.nodeDetails.attemptList': '运行尝试',
  'runFlow.nodeDetails.contextBlocks': '上下文输入',
  'runFlow.nodeDetails.column.name': '名称',
  'runFlow.nodeDetails.column.status': '状态',
  'runFlow.nodeDetails.column.duration': '耗时',
  'runFlow.nodeDetails.column.records': '记录',
  'runFlow.nodeDetails.column.time': '时间',
  'runFlow.nodeDetails.contextQuality': '上下文质量',
  'runFlow.nodeDetails.overallScore': '综合评分',
  'runFlow.nodeDetails.qualityLevel': '等级',
  'runFlow.nodeDetails.blockScores': '数据块评分',
  'runFlow.nodeDetails.count.available': '可用',
  'runFlow.nodeDetails.count.missing': '缺失',
  'runFlow.nodeDetails.count.partial': '部分',
  'runFlow.nodeDetails.count.degraded': '部分降级',
  'runFlow.nodeDetails.count.fallback': '降级回退',
  'runFlow.nodeDetails.count.skipped': '跳过',

  'report.addToWatchlist': '加入自选',
  'report.removeFromWatchlist': '从自选删除',
  'report.watchlist': '自选',

  'settings.actionSuccess': '操作成功',
  'settings.activePanelDescription': '使用统一字段卡片维护当前分类的系统配置。',
  'settings.activePanelTitle': '当前分类配置项',
  'settings.agentSettings': 'Agent 设置',
  'settings.alphaSift': 'AlphaSift 选股',
  'settings.alphaSiftDescription': '启用内置 AlphaSift 实验性质选股能力。',
  'settings.alphaSiftDisabled': '选股未开启',
  'settings.alphaSiftEnabled': '选股已开启',
  'settings.alphaSiftRisk': '实验功能与风险提示：选股结果仅用于研究和辅助判断，不构成投资建议；市场有风险，交易决策和损益由使用者自行承担。',
  'settings.alphaSiftSummary': '开启后左侧导航会显示“选股”；策略和候选生成来自 AlphaSift，DSA 会补充行情、基本面和新闻上下文。',
  'settings.authCurrentPassword': '当前管理员密码',
  'settings.authDescription': '管理管理员密码认证，保护您的系统配置安全。',
  'settings.authDisabled': '未启用',
  'settings.authEnabled': '已启用',
  'settings.authFailure': '认证设置失败',
  'settings.authHelperDefault': '管理员认证可保护 Web 设置页及 API 接口，防止未经授权的访问。',
  'settings.authHelperEnabled': '管理员认证已启用。如需更新密码，请使用下方的“修改密码”功能。',
  'settings.authHelperNoPassword': '系统尚未设置密码。启用认证前请先设置初始管理员密码，设置后请妥善保管。',
  'settings.authHelperPasswordRetained': '系统已保留之前设置的管理员密码。输入当前密码即可快速重新启用认证。',
  'settings.authHelperTurnOff': '若当前登录会话仍有效，可直接关闭认证；若会话已失效，请输入当前管理员密码。',
  'settings.authPasswordHintOff': '关闭认证前可能需要验证身份',
  'settings.authPasswordHintRetained': '输入旧密码以重新激活认证',
  'settings.authPasswordPlaceholder': '请输入当前密码',
  'settings.authRequiredPassword': '设置新密码是必填项',
  'settings.authSetPassword': '设置管理员密码',
  'settings.authSetPasswordPlaceholder': '输入新密码 (至少 6 位)',
  'settings.authStatus': '管理员认证',
  'settings.authSuccessDisabled': '认证已关闭',
  'settings.authSuccessUpdated': '认证设置已更新',
  'settings.authTitle': '认证与登录保护',
  'settings.categoryNavDescription': '按模块整理系统设置与认证能力。',
  'settings.categoryNavTitle': '配置分类',
  'settings.changePasswordConfirm': '确认新密码',
  'settings.changePasswordConfirmPlaceholder': '再次输入新密码',
  'settings.changePasswordCurrent': '当前密码',
  'settings.changePasswordCurrentPlaceholder': '输入当前密码',
  'settings.changePasswordDescription': '更新当前管理员登录密码。修改成功后，后续登录请使用新密码。',
  'settings.changePasswordFailure': '修改失败',
  'settings.changePasswordNew': '新密码',
  'settings.changePasswordNewHint': '至少 6 位。',
  'settings.changePasswordNewPlaceholder': '输入新密码',
  'settings.changePasswordRequiredCurrent': '请输入当前密码',
  'settings.changePasswordRequiredNew': '请输入新密码',
  'settings.changePasswordSave': '保存新密码',
  'settings.changePasswordShort': '新密码至少 6 位',
  'settings.changePasswordSuccess': '修改成功',
  'settings.changePasswordSuccessMessage': '管理员密码已更新。',
  'settings.changePasswordTitle': '修改密码',
  'settings.checkDesktopUpdate': '检查更新',
  'settings.checkingDesktopUpdate': '检查中...',
  'settings.configBackup': '配置备份',
  'settings.configBackupDescription': '导出当前已保存的 .env 备份，或从备份文件恢复配置。导入会覆盖备份中出现的键并立即重载。',
  'settings.currentCategoryEmptyDescription': '当前分类没有可编辑字段；可切换左侧分类继续查看其它系统配置。',
  'settings.currentCategoryEmptyTitle': '当前分类下暂无配置项',
  'settings.desktopCheckError': '检查更新失败',
  'settings.desktopChecking': '正在检查更新',
  'settings.desktopCurrentNoStatus': '当前尚无更新状态，应用启动后会在后台自动检查。',
  'settings.desktopDownload': '前往下载',
  'settings.desktopDownloaded': '更新已下载',
  'settings.desktopDownloading': '正在下载更新',
  'settings.desktopInstall': '重启安装',
  'settings.desktopInstalling': '正在安装更新',
  'settings.desktopLatest': '最新版本',
  'settings.desktopManualUnsupported': '当前桌面端不支持自动安装更新，请前往发布页手动更新。',
  'settings.desktopUpdate': '桌面端更新',
  'settings.desktopUpdateAvailable': '发现新版本',
  'settings.desktopUpdateDescription': '启动后会自动检查 GitHub Releases 最新正式版；Windows 安装版会后台下载更新，确认后静默重启安装。',
  'settings.desktopUpdateDownloadedMessage': '新版本已下载，可重启应用完成安装。',
  'settings.desktopUpdateDownloadingMessage': '正在后台下载桌面端更新{percent}。',
  'settings.desktopUpdateErrorMessage': '无法完成更新检查，请稍后重试。',
  'settings.desktopUpdateInstallingMessage': '正在重启并安装更新。',
  'settings.desktopUpdateMessage': '当前 {current}，最新 {latest}。{message}',
  'settings.desktopUpdateReleaseMessage': '可前往 GitHub Releases 下载更新。',
  'settings.desktopUpdateCheckingMessage': '正在检查 GitHub Releases 中是否有可用新版本。',
  'settings.desktopUpToDate': '已是最新版本',
  'settings.desktopUpToDateMessage': '当前桌面端已是最新版本。',
  'settings.diagnosticHintDesktop': '请查看并提供桌面端日志 desktop.log，同时补充 release 版本、Windows 版本和触发入口。',
  'settings.diagnosticHintWeb': '请查看浏览器开发者工具控制台与后端日志，并补充 release 版本、浏览器版本和触发入口。',
  'settings.disabledAuthBackupWarning': '当前 Web 端未开启管理员鉴权，导出/导入 `.env` 备份功能已停用；请先将 `ADMIN_AUTH_ENABLED` 设为 `true` 并完成管理员登录后再使用。',
  'settings.enableAuth': '开启认证',
  'settings.disableAuth': '关闭认证',
  'settings.keepAuthDisabled': '保持已关闭',
  'settings.keepAuthEnabled': '保持已开启',
  'settings.enableAlphaSift': '开启选股',
  'settings.disableAlphaSift': '关闭选股',
  'settings.enablingAlphaSift': '开启中...',
  'settings.disablingAlphaSift': '关闭中...',
  'settings.enabledAlphaSiftSuccess': '已开启 AlphaSift 选股。',
  'settings.disabledAlphaSiftSuccess': '已关闭 AlphaSift 选股。',
  'settings.setupStatusConfigured': '已配置',
  'settings.setupStatusInherited': '已继承',
  'settings.setupStatusNeedsAction': '待处理',
  'settings.setupStatusOptional': '可选',
  'settings.setupGuideHiddenTitle': '首次启动配置检查已隐藏',
  'settings.setupGuideHiddenDescription': '需要重新检查基础配置、模型和通知时，可再次展开。',
  'settings.setupGuideOpen': '展开检查',
  'settings.setupGuideTitle': '首次启动配置检查',
  'settings.setupGuideDescription': '按最小可用分析流程检查自选股、模型渠道和通知配置，完成后可直接发起一次简短试跑。',
  'settings.setupGuideCheckingTitle': '正在检查首次启动配置',
  'settings.setupGuideCheckingSummary': '正在读取配置状态，完成后会显示缺失项和试跑入口。',
  'settings.setupGuideUnknownTitle': '暂无法判断配置状态',
  'settings.setupGuideUnknownSummary': '配置状态读取失败。可先检查或修改设置项，稍后刷新检查结果。',
  'settings.setupGuideCompleteTitle': '基础配置已满足最小可用分析',
  'settings.setupGuideIncompleteTitle': '还有基础配置需要处理',
  'settings.setupGuideMissingSummary': '还缺少 {count} 项：{labels}',
  'settings.setupGuideReadySummary': '所有必需项已就绪，可运行一次简短分析验证链路。',
  'settings.setupGuideRefreshing': '刷新中...',
  'settings.setupGuideRefresh': '刷新检查',
  'settings.setupGuideHide': '暂时隐藏',
  'settings.setupGuideConfigureLlm': '配置模型',
  'settings.setupGuideAddStocks': '维护自选股',
  'settings.setupGuideConfigureNotification': '配置通知',
  'settings.setupGuideSmokeRunning': '提交中...',
  'settings.setupGuideSmokeNeedsStock': '需要至少一个自选股代码后才能试跑。',
  'settings.setupGuideRunSmoke': '简短试跑',
  'settings.setupGuideSmokeNotReady': '请先完成必需配置后再运行试跑。',
  'settings.setupGuideSmokeUnavailableTitle': '暂不能试跑',
  'settings.setupGuideSmokeAcceptedWithTask': '已提交 {stock} 的简短分析任务：{taskId}',
  'settings.setupGuideSmokeAccepted': '已提交 {stock} 的简短分析任务。',
  'settings.schedulerAddTime': '添加时间',
  'settings.schedulerDescription': '配置自动分析的每日执行时间，保存后长运行的 Web/API/Desktop 进程会按新配置生效。',
  'settings.schedulerDisabled': '未启用',
  'settings.schedulerEffectiveTimes': '生效时间',
  'settings.schedulerEnable': '启用定时任务',
  'settings.schedulerEnabled': '已启用',
  'settings.schedulerEnableDescription': '开启后会按下方时间自动执行分析任务。',
  'settings.schedulerLastError': '最近错误',
  'settings.schedulerLastSuccess': '上次成功',
  'settings.schedulerNextRun': '下次执行',
  'settings.schedulerRefresh': '刷新状态',
  'settings.schedulerRefreshing': '刷新中...',
  'settings.schedulerRemoveTime': '删除时间',
  'settings.schedulerRunAccepted': '已提交执行请求。',
  'settings.schedulerRunNow': '立即执行一次',
  'settings.schedulerRunning': '运行中',
  'settings.schedulerRunningNow': '执行中...',
  'settings.schedulerStatus': '当前状态',
  'settings.schedulerTimeInputAria': '定时执行时间 {index}',
  'settings.schedulerTimes': '定时执行时间',
  'settings.schedulerTitle': '定时任务',
  'settings.envExported': '已导出当前已保存的 .env 备份。',
  'settings.envImported': '已导入 .env 备份并重新加载配置。',
  'settings.envImportedRefreshFailedMessage': '备份已导入，但重新加载配置失败，请手动重载页面。',
  'settings.envImportedRefreshFailedRaw': 'Env import succeeded but config refresh failed',
  'settings.envImportedRefreshFailedTitle': '配置已导入但刷新失败',
  'settings.exportEnv': '导出 .env',
  'settings.exportingEnv': '导出中...',
  'settings.fallbackVersionWarning': '当前 package.json 仍为占位版本 0.0.0，页面已自动回退展示构建标识，避免误判旧资源仍在生效。',
  'settings.fieldAddKey': '添加 Key',
  'settings.fieldDelete': '删除',
  'settings.fieldSensitiveHint': '敏感内容默认隐藏，可点击眼睛图标查看明文。',
  'settings.fieldSensitiveMultiHint': ' 支持添加多个输入框进行增删。',
  'settings.helpClose': '关闭配置说明',
  'settings.helpExamples': '配置样例',
  'settings.helpImpact': '影响范围',
  'settings.helpNotes': '注意事项',
  'settings.helpPurpose': '用途',
  'settings.helpRelatedDocs': '相关文档',
  'settings.helpTitleFallback': '配置说明',
  'settings.helpTooltip': '查看配置说明',
  'settings.helpValueNotes': '取值说明',
  'settings.importConfirmContinue': '继续导入',
  'settings.importConfirmMessage': '当前页面还有未保存修改。继续导入会丢弃这些本地草稿，并立即用备份文件中的键值更新已保存配置。',
  'settings.importConfirmTitle': '导入会覆盖当前草稿',
  'settings.importEnv': '导入 .env',
  'settings.importingEnv': '导入中...',
  'settings.intelligentImport': '智能导入',
  'settings.intelligentImportDescription': '从图片、文件或剪贴板中提取股票代码，并合并到自选股列表。',
  'settings.intelligentImportSupportedInputs': '支持图片、CSV/Excel 文件与剪贴板文本',
  'settings.intelligentImportHint': '图片识别需预先配置 Vision 模型。建议先人工核对解析结果，再合并到自选股。',
  'settings.intelligentImportChooseImage': '选择图片',
  'settings.intelligentImportChooseFile': '选择文件',
  'settings.intelligentImportPastePlaceholder': '或粘贴 CSV/Excel 复制的文本...',
  'settings.intelligentImportParse': '解析',
  'settings.intelligentImportReviewWarning': '建议人工逐条核对后再合并。高置信度默认勾选，中/低置信度需手动确认。',
  'settings.intelligentImportSelectionSummary': '共 {valid} 条可合并，已勾选 {checked} 条',
  'settings.intelligentImportClear': '清空',
  'settings.intelligentImportMergeToWatchlist': '合并到自选股',
  'settings.intelligentImportImageTypeError': '图片仅支持 JPG、PNG、WebP、GIF',
  'settings.intelligentImportImageSizeError': '图片不超过 5MB',
  'settings.intelligentImportFileSizeError': '文件不超过 2MB',
  'settings.intelligentImportTextSizeError': '粘贴文本不超过 100KB',
  'settings.intelligentImportRecognitionFailed': '识别失败，请重试',
  'settings.intelligentImportRateLimited': '请求过于频繁，请稍后再试',
  'settings.intelligentImportTimeout': '请求超时，请检查网络后重试',
  'settings.intelligentImportParseFailed': '解析失败',
  'settings.intelligentImportLoadConfigFirst': '请先加载配置后再合并',
  'settings.intelligentImportConfigUpdated': '配置已更新，请再次点击「合并到自选股」',
  'settings.intelligentImportMergeFailed': '合并保存失败',
  'settings.llmAccess': 'AI 模型接入',
  'settings.llmAccessDescription': '统一管理模型渠道、基础地址、API Key、主模型与备选模型。',
  'settings.notificationSettings': '通知设置',
  'settings.notificationTest': '通知测试',
  'settings.notificationTestBody': '正文',
  'settings.notificationTestChannel': '渠道',
  'settings.notificationTestContent': '这是一条来自 DSA Web 设置页的通知测试消息。',
  'settings.notificationTestDescription': '使用当前页面草稿发送一条真实测试通知；测试不会保存配置。',
  'settings.notificationTestFailure': '测试失败',
  'settings.notificationTestSend': '发送测试',
  'settings.notificationTestSuccess': '测试成功',
  'settings.notificationTestTimeout': '超时秒数',
  'settings.notificationTestTitle': '标题',
  'settings.notificationTestTitleValue': 'DSA 通知测试',
  'settings.notificationTesting': '测试中...',
  'settings.openConfigItems': '查看配置项',
  'settings.pageDescription': '统一管理模型、数据源、通知、安全认证与导入能力。',
  'settings.pageTitle': '系统设置',
  'settings.pageTitleDocument': '系统设置 - DSA',
  'settings.promptCacheAdvancedDescription': '维护 provider prompt cache 的观测、主动 hint 与脱敏诊断；默认配置已适合普通使用。',
  'settings.promptCacheAdvancedTitle': 'Provider Prompt Cache 高级设置',
  'settings.reload': '重新加载',
  'settings.reset': '重置',
  'settings.revert': '还原',
  'settings.saveConfig': '保存配置',
  'settings.saveConfigWithCount': '保存配置 ({count})',
  'settings.saveRetry': '重试保存',
  'settings.saving': '保存中...',
  'settings.updateBuildDescription': '重新执行前端构建或 Docker 镜像构建后，此处的构建标识和构建时间会更新，可用来确认当前页面资源是否已切换。',
  'settings.versionBuildId': '构建标识',
  'settings.versionBuildTime': '构建时间',
  'settings.versionDesktop': '桌面端版本',
  'settings.versionInfo': '版本信息',
  'settings.versionInfoDescription': '用于确认当前 WebUI 静态资源是否已经切换到最新构建。',
  'settings.versionWebui': 'WebUI 版本',
  'settings.viewConfigItems': '查看配置项',
  'settings.envExportNote': '导出内容仅包含当前已保存配置，不包含页面上尚未保存的本地草稿。',
  'settings.envDockerNote': 'Docker 部署中，`--env-file` / Compose `env_file` 只会在启动时注入环境变量；此处导出/导入的是后端当前活跃的 `.env` 文件。若需要让 WebUI 保存值随容器重建保留，请将 `ENV_FILE` 指向 `/app/data/runtime.env` 等可写数据卷文件，并避免启动环境里继续保留同名旧值。',
} as const;

export type UiTextKey = keyof typeof zh;

const en: Record<UiTextKey, string> = {
  'common.cancel': 'Cancel',
  'common.close': 'Close',
  'common.closeDrawer': 'Close drawer',
  'common.confirm': 'OK',
  'common.delete': 'Delete',
  'common.deleting': 'Deleting',
  'common.details': 'View details',
  'common.disabled': 'Disabled',
  'common.enabled': 'Enabled',
  'common.failure': 'Failed',
  'common.hideContent': 'Hide content',
  'common.itemsCount': '{count}',
  'common.loading': 'Loading',
  'common.noData': 'No data',
  'common.processing': 'Processing...',
  'common.readOnly': 'Read-only',
  'common.retry': 'Retry',
  'common.selectAllCurrent': 'Select current',
  'common.selectPlaceholder': 'Select',
  'common.selectedCount': '{count} selected',
  'common.sensitive': 'Sensitive',
  'common.showContent': 'Show content',
  'common.success': 'Success',
  'common.copy': 'Copy',
  'common.copied': 'Copied!',

  'language.current': 'English',
  'language.english': 'English',
  'language.short.en': 'EN',
  'language.short.zh': '中',
  'language.toggle': 'Switch UI language',
  'language.uiLanguage': 'UI language',

  'theme.dark': 'Dark',
  'theme.light': 'Light',
  'theme.menu': 'Theme mode',
  'theme.system': 'System',
  'theme.theme': 'Theme',
  'theme.toggle': 'Toggle theme',

  'layout.appFallbackDescription': 'Web workspace',
  'layout.appFallbackTitle': 'Daily Stock Analysis',
  'layout.collapseSidebar': 'Collapse sidebar',
  'layout.desktopSidebar': 'Desktop sidebar navigation',
  'layout.expandSidebar': 'Expand sidebar',
  'layout.mainNav': 'Main navigation',
  'layout.nav.alerts': 'Alerts',
  'layout.nav.backtest': 'Backtest',
  'layout.nav.chat': 'Ask',
  'layout.nav.decisionSignals': 'AI signals',
  'layout.nav.home': 'Home',
  'layout.nav.portfolio': 'Portfolio',
  'layout.nav.settings': 'Settings',
  'layout.nav.screening': 'Screening',
  'layout.nav.usage': 'Usage',
  'layout.navMenu': 'Navigation',
  'layout.newChatMessage': 'New Ask update',
  'layout.openNav': 'Open navigation',
  'layout.route.alerts.description': 'Rules, triggers, and notification attempts',
  'layout.route.alerts.title': 'Alerts',
  'layout.route.backtest.description': 'Backtest jobs and result review',
  'layout.route.backtest.title': 'Backtest',
  'layout.route.chat.description': 'Multi-turn strategy Q&A and sessions',
  'layout.route.chat.title': 'Ask',
  'layout.route.decisionSignals.description': 'AI recommendations, risks, and watch conditions',
  'layout.route.decisionSignals.title': 'AI signals',
  'layout.route.home.description': 'Stock analysis and report workspace',
  'layout.route.home.title': 'Home',
  'layout.route.portfolio.description': 'Portfolio snapshots, manual entries, and risk analysis',
  'layout.route.portfolio.title': 'Portfolio',
  'layout.route.settings.description': 'System config, models, and authentication',
  'layout.route.settings.title': 'Settings',
  'layout.route.screening.description': 'AlphaSift strategy screening and candidate research',
  'layout.route.screening.title': 'Screening',
  'layout.route.usage.description': 'LLM token consumption and model call details',
  'layout.route.usage.title': 'Usage',
  'layout.logout': 'Log out',
  'layout.logoutConfirm': 'Log out',
  'layout.logoutMessage': 'Log out of the current session? You will need to enter the password again.',
  'layout.logoutTitle': 'Log out',

  'usage.breakdown': 'Breakdown',
  'usage.callType.agent': 'Ask Agent',
  'usage.callType.analysis': 'Stock analysis',
  'usage.callType.marketReview': 'Market review',
  'usage.callType.unknown': '{type}',
  'usage.callTypeDetail': '{calls} calls · Prompt {prompt} · Completion {completion}',
  'usage.callTypeTitle': 'Call type',
  'usage.calls': '{count} calls',
  'usage.completionTokens': 'Completion tokens',
  'usage.completionTokensHint': 'Model output consumption',
  'usage.dateRange': '{from} to {to}',
  'usage.description': 'Inspect LLM call count, Prompt/Completion token consumption, model usage, and recent call details.',
  'usage.emptyDescription': 'After an analysis, market review, or Ask call completes, model usage will appear here.',
  'usage.emptyTitle': 'No token usage records',
  'usage.error.message': 'Failed to load token usage data',
  'usage.error.title': 'Failed to load token usage',
  'usage.eyebrow': 'Usage',
  'usage.maxSingleCall': 'Single-call peak',
  'usage.modelUsage': 'Model usage',
  'usage.modelUsageDescription': 'Token consumption, call count, and single-call peaks grouped by model.',
  'usage.noRecentCalls': 'No recent call records',
  'usage.period.all': 'All',
  'usage.period.month': 'This month',
  'usage.period.today': 'Today',
  'usage.promptTokens': 'Prompt tokens',
  'usage.promptTokensHint': 'Input context consumption',
  'usage.recentCalls': 'Recent calls',
  'usage.recentCallsDescription': 'Latest 50 LLM token audit records.',
  'usage.refresh': 'Refresh',
  'usage.table.model': 'Model',
  'usage.table.time': 'Time',
  'usage.table.type': 'Type',
  'usage.title': 'Token usage',
  'usage.totalCalls': 'Calls',
  'usage.totalCallsHint': 'Recorded LLM calls',
  'usage.totalTokens': 'Total tokens',

  'routeError.backHome': 'Back home',
  'routeError.description': 'This page or component could not load. The network may be unavailable, or the page version may have changed. Reload the page or return home and try again.',
  'routeError.reload': 'Reload page',
  'routeError.title': 'Page failed to load',
  'notFound.backHome': 'Back home',
  'notFound.description': 'The page you requested does not exist or has moved.',
  'notFound.pageTitle': 'Page not found - DSA',
  'notFound.title': 'Page not found',

  'login.adminLogin': 'Admin login',
  'login.adminPassword': 'Admin password',
  'login.confirmPassword': 'Confirm password',
  'login.confirmPasswordPlaceholder': 'Confirm the admin password',
  'login.loginDescription': 'A valid credential is required to access the DSA decision workspace.',
  'login.loginFailed': 'Login failed',
  'login.loginPassword': 'Password',
  'login.loginPasswordPlaceholder': 'Enter password',
  'login.loginSubmit': 'Enter workspace',
  'login.loginSubmitting': 'Connecting...',
  'login.pageTitle': 'Login - DSA',
  'login.passwordMismatch': 'The two passwords do not match',
  'login.setupDescription': 'Authentication is being enabled for the first time. Set an admin password for the workspace.',
  'login.setupFailed': 'Setup failed',
  'login.setupPasswordPlaceholder': 'Set a password with at least 6 characters',
  'login.setupSubmit': 'Finish setup and sign in',
  'login.setupSubmitting': 'Initializing...',
  'login.setupTitle': 'Set initial password',
  'login.validationFailed': 'Validation failed',

  'home.analyze': 'Analyze',
  'home.analyzing': 'Analyzing',
  'home.askAi': 'Ask AI',
  'home.defaultStrategyDescription': 'Use the system default analysis framework',
  'home.defaultStrategyName': 'Default strategy',
  'home.duplicateTask': 'Task already exists',
  'home.goSettings': 'Configure',
  'home.historyButton': 'History',
  'home.historyTrend': 'History trend',
  'home.inputInvalid': 'Invalid input',
  'home.loadingReport': 'Loading report...',
  'home.marketReview': 'Market review',
  'home.marketReviewCompleted': 'Market review completed',
  'home.marketReviewCompletedWithReport': 'Market review completed. Result:',
  'home.marketReviewCompletedWithoutReport': 'Market review completed. The result was generated and sent according to your configuration.',
  'home.marketReviewFailed': 'Market review failed.',
  'home.marketReviewHistoryEmptyDescription': 'Market review records will appear here after you run one.',
  'home.marketReviewHistoryEmptyTitle': 'No market reviews',
  'home.marketReviewHistoryTitle': 'Market review history',
  'home.marketReviewInProgress': 'Market review in progress',
  'home.marketReviewSubmitted': 'Market review submitted',
  'home.marketReviewTimeout': 'Market review timed out',
  'home.marketReviewTimeoutMessage': 'The task did not return a final result in time. Check the task list or history.',
  'home.marketReviewUnknownStatus': 'Unexpected market review status',
  'home.notify': 'Send notification',
  'home.pageTitle': 'Daily Stock Analysis - DSA',
  'home.placeholder': 'Enter a stock code or name, e.g. 600519, Kweichow Moutai, AAPL',
  'home.progressActive': 'In progress',
  'home.reanalyze': 'Reanalyze',
  'home.rerunMarketReview': 'Rerun market review',
  'home.fullReport': 'Full analysis report',
  'home.setupIncomplete': 'Base configuration incomplete',
  'home.setupMissingGeneric': 'Base configuration is still incomplete. Complete it before running the minimal analysis flow.',
  'home.setupMissingWithLabels': 'Missing {labels}. Complete them before running the minimal analysis flow.',
  'home.startAnalysisDescription': 'Enter a stock code to analyze, or pick a historical report from the left.',
  'home.startAnalysisTitle': 'Start analysis',
  'home.strategy': 'Strategy',
  'home.submitMarketReview': 'Submitting',
  'home.taskStatus': 'Task status: {status} ({progress})',
  'home.unknownTaskStatus': 'Received unknown task status: {status}',

  'decisionSignals.action': 'Action',
  'decisionSignals.active': 'Active',
  'decisionSignals.activeOnly': 'Active signals are shown by default',
  'decisionSignals.allActions': 'All actions',
  'decisionSignals.allMarkets': 'All markets',
  'decisionSignals.allPhases': 'All phases',
  'decisionSignals.allSources': 'All sources',
  'decisionSignals.allStatuses': 'All statuses',
  'decisionSignals.archive': 'Archive',
  'decisionSignals.archiveConfirm': 'Archive this signal? Archived signals are no longer shown as current active recommendations.',
  'decisionSignals.archived': 'Archived',
  'decisionSignals.close': 'Close signal',
  'decisionSignals.closeConfirm': 'Close this signal? Closed signals are no longer tracked as current recommendations.',
  'decisionSignals.closed': 'Closed',
  'decisionSignals.confidence': 'Confidence',
  'decisionSignals.confirmStatusTitle': 'Update signal status',
  'decisionSignals.createdAt': 'Created',
  'decisionSignals.catalystSummary': 'Catalyst',
  'decisionSignals.dataQuality': 'Data quality',
  'decisionSignals.description': 'Query structured AI recommendations by stock, phase, source, and status while keeping risk and data-quality context visible.',
  'decisionSignals.detailTitle': 'Signal details',
  'decisionSignals.directionExpected': 'Expected direction',
  'decisionSignals.emptyDescription': 'After a regular stock analysis completes, extracted structured recommendations appear here.',
  'decisionSignals.emptyTitle': 'No decision signals',
  'decisionSignals.entryRange': 'Entry range',
  'decisionSignals.errorTitle': 'Failed to load decision signals',
  'decisionSignals.evidence': 'Evidence',
  'decisionSignals.expired': 'Expired',
  'decisionSignals.expiresAt': 'Expires',
  'decisionSignals.feedback.not_useful': 'Not useful',
  'decisionSignals.feedback.useful': 'Useful',
  'decisionSignals.feedbackNone': 'No feedback yet',
  'decisionSignals.feedbackTitle': 'User feedback',
  'decisionSignals.filter': 'Filter',
  'decisionSignals.horizon': 'Horizon',
  'decisionSignals.horizon.1d': '1 day',
  'decisionSignals.horizon.3d': '3 days',
  'decisionSignals.horizon.5d': '5 days',
  'decisionSignals.horizon.10d': '10 days',
  'decisionSignals.horizon.intraday': 'Intraday',
  'decisionSignals.horizon.long': 'Long term',
  'decisionSignals.horizon.swing': 'Swing',
  'decisionSignals.invalidation': 'Invalidation',
  'decisionSignals.invalidate': 'Mark invalid',
  'decisionSignals.invalidateConfirm': 'Mark this signal invalid? Invalidated signals are no longer shown as current active recommendations.',
  'decisionSignals.invalidated': 'Invalidated',
  'decisionSignals.latestButton': 'Query latest',
  'decisionSignals.latestDescription': 'Enter a stock code to read the latest active signals for that stock.',
  'decisionSignals.latestInput': 'Latest stock code',
  'decisionSignals.latestPlaceholder': 'e.g. 600519, HK00700, AAPL',
  'decisionSignals.latestTitle': 'Latest signals by stock',
  'decisionSignals.market': 'Market',
  'decisionSignals.market.cn': 'A-shares',
  'decisionSignals.market.hk': 'Hong Kong',
  'decisionSignals.market.jp': 'Japan',
  'decisionSignals.market.kr': 'Korea',
  'decisionSignals.market.tw': 'Taiwan',
  'decisionSignals.market.us': 'US',
  'decisionSignals.marketPhase': 'Phase',
  'decisionSignals.marketPhase.closing_auction': 'Closing auction',
  'decisionSignals.marketPhase.intraday': 'Intraday',
  'decisionSignals.marketPhase.lunch_break': 'Lunch break',
  'decisionSignals.marketPhase.non_trading': 'Non-trading',
  'decisionSignals.marketPhase.postmarket': 'Post-market',
  'decisionSignals.marketPhase.premarket': 'Pre-market',
  'decisionSignals.marketPhase.unknown': 'Unknown phase',
  'decisionSignals.metadata': 'Metadata',
  'decisionSignals.noLatestDescription': 'This stock has no current active signal, or existing signals have expired.',
  'decisionSignals.noLatestTitle': 'No latest active signals',
  'decisionSignals.noOutcomes': 'No outcome results yet',
  'decisionSignals.noStatsDescription': 'After signal outcome evaluation runs, hit, miss, neutral, and unable counts appear here.',
  'decisionSignals.noStatsTitle': 'No outcome stats yet',
  'decisionSignals.outcome.hit': 'Hit',
  'decisionSignals.outcome.miss': 'Miss',
  'decisionSignals.outcome.neutral': 'Neutral',
  'decisionSignals.outcome.unable': 'Unable',
  'decisionSignals.outcomes': 'Outcome results',
  'decisionSignals.pageTitle': 'AI signals - DSA',
  'decisionSignals.planQuality': 'Plan quality',
  'decisionSignals.planQuality.complete': 'Complete',
  'decisionSignals.planQuality.minimal': 'Minimal',
  'decisionSignals.planQuality.partial': 'Partial',
  'decisionSignals.planQuality.unknown': 'Unknown',
  'decisionSignals.pricePlan': 'Price plan',
  'decisionSignals.profile': 'Profile',
  'decisionSignals.reason': 'Reason',
  'decisionSignals.refresh': 'Refresh',
  'decisionSignals.returnPct': 'Window return',
  'decisionSignals.riskSummary': 'Risk',
  'decisionSignals.score': 'Score',
  'decisionSignals.source': 'Source',
  'decisionSignals.sourceType.agent': 'Agent',
  'decisionSignals.sourceType.alert': 'Alert',
  'decisionSignals.sourceType.analysis': 'Analysis report',
  'decisionSignals.sourceType.manual': 'Manual',
  'decisionSignals.sourceType.market_review': 'Market review',
  'decisionSignals.sourceReport': 'Source report',
  'decisionSignals.sourceReportId': 'Source report ID',
  'decisionSignals.statsDescription': 'Signal performance from the current outcome engine version, excluding archived signals by default.',
  'decisionSignals.statsErrorTitle': 'Failed to load outcome stats',
  'decisionSignals.statsHitRate': 'Hit rate',
  'decisionSignals.statsTitle': 'Signal performance',
  'decisionSignals.statsTotal': 'Evaluations',
  'decisionSignals.status': 'Status',
  'decisionSignals.stockCode': 'Stock code',
  'decisionSignals.stopLoss': 'Stop loss',
  'decisionSignals.targetPrice': 'Target price',
  'decisionSignals.title': 'AI signals',
  'decisionSignals.total': '{total} signals',
  'decisionSignals.timelineAlertShape': 'Diamond points indicate alert',
  'decisionSignals.timelineDescription': 'Track how one stock signal changes over time.',
  'decisionSignals.timelineEmptyDescription': 'No signals for this stock in the selected range.',
  'decisionSignals.timelineEmptyTitle': 'No timeline signals',
  'decisionSignals.timelineErrorTitle': 'Failed to load timeline',
  'decisionSignals.timelineFamilyBullish': 'Bullish',
  'decisionSignals.timelineFamilyDefensive': 'Defensive',
  'decisionSignals.timelineFamilyNeutral': 'Neutral',
  'decisionSignals.timelineGuideDescription': 'Enter a stock code before searching; empty stock code never loads global signals.',
  'decisionSignals.timelineGuideTitle': 'Enter a stock code to view the timeline',
  'decisionSignals.timelineMarket': 'Timeline market',
  'decisionSignals.timelineRange': 'Range',
  'decisionSignals.timelineRange.30d': '30 days',
  'decisionSignals.timelineRange.90d': '90 days',
  'decisionSignals.timelineRange.180d': '180 days',
  'decisionSignals.timelineSearch': 'Search timeline',
  'decisionSignals.timelineSelected': 'Selected point {index}',
  'decisionSignals.timelineStatus': 'Timeline status',
  'decisionSignals.timelineStatus.active': 'Active only',
  'decisionSignals.timelineStatus.all': 'All history',
  'decisionSignals.timelineStockCode': 'Timeline stock code',
  'decisionSignals.timelineStockPlaceholder': 'e.g. 600519, HK00700, AAPL',
  'decisionSignals.timelineTitle': 'Stock signal timeline',
  'decisionSignals.timelineTruncatedDescription': 'Only the latest 100 signals are shown. Narrow the time range.',
  'decisionSignals.timelineTruncatedTitle': 'Timeline truncated',
  'decisionSignals.unableReason': 'Unable reason',
  'decisionSignals.watchConditions': 'Watch conditions',
  'decisionSignals.viewDetailsFor': 'View AI signal details for {stock}',
  'decisionSignals.portfolioColumn': 'AI signals',
  'decisionSignals.portfolioEmpty': '-',
  'decisionSignals.portfolioLoading': 'Loading',
  'decisionSignals.portfolioPartialWarning': 'AI signals loaded only partially: {message}',
  'decisionSignals.portfolioWarningTitle': 'AI signals degraded',

  'history.analysisCount': '{count} runs',
  'history.bottomReached': 'End',
  'history.defaultEmptyDescription': 'Recent results will be saved here after the first analysis.',
  'history.defaultEmptyTitle': 'No analysis history',
  'history.defaultTitle': 'Analysis history',
  'history.deleteRecord': 'Delete {name} history record',
  'history.itemAria': '{name} {code} history record',
  'history.loading': 'Loading history...',
  'history.actionAdd': 'Add',
  'history.actionAlert': 'Alert',
  'history.actionAvoid': 'Avoid',
  'history.actionBuy': 'Buy',
  'history.actionHold': 'Hold',
  'history.actionReduce': 'Reduce',
  'history.actionSell': 'Sell',
  'history.actionWatch': 'Watch',
  'history.sentiment': 'Sentiment',
  'history.selectAllHistoryAria': 'Select all loaded history records',
  'history.selectAllStockAria': 'Select all current stocks',
  'stockBar.emptyDescription': 'Latest analysis results will be grouped by stock here after the first analysis.',
  'stockBar.emptyTitle': 'No stock records',
  'stockBar.loading': 'Loading stocks...',
  'stockBar.market': 'Market',
  'stockBar.title': 'Stocks',

  'stockTrend.allHistory': 'All history',
  'stockTrend.averageScore': 'Average {score}',
  'stockTrend.backToCurrentReport': 'Back to current report',
  'stockTrend.currentAdvice': 'Current view',
  'stockTrend.currentScore': 'Current score',
  'stockTrend.historyModelCount': '{count} historical models',
  'stockTrend.loadedSummary': 'Loaded {loaded} / {total} · Newest first · Model: all',
  'stockTrend.loadFailed': 'Failed to load history trend',
  'stockTrend.loading': 'Loading same-stock history...',
  'stockTrend.loadMore': 'Load more',
  'stockTrend.loadingMore': 'Loading...',
  'stockTrend.latestTime': 'Latest {time}',
  'stockTrend.model': 'Model',
  'stockTrend.modelCountSuffix': '{count} runs',
  'stockTrend.moreEmptyDescription': 'After multiple analyses, this view shows changes in opinions, score trends, and model records.',
  'stockTrend.moreEmptyTitle': 'No more same-stock history',
  'stockTrend.neverRecorded': 'Not recorded',
  'stockTrend.noModelTitle': 'No recorded model',
  'stockTrend.records': 'Historical analysis records',
  'stockTrend.reload': 'Reload',
  'stockTrend.report': 'View report',
  'stockTrend.result': 'Result',
  'stockTrend.score': 'Score',
  'stockTrend.stockPrice': 'Price',
  'stockTrend.table.action': 'Action',
  'stockTrend.time': 'Time',
  'stockTrend.title': 'History trend',
  'stockTrend.volumeRatio': 'Volume ratio',
  'stockTrend.window30': 'Last 30 days',
  'stockTrend.window90': 'Last 90 days',
  'stockTrend.changePct': 'Change',
  'stockTrend.turnoverRate': 'Turnover',

  'taskPanel.diagnostics': 'Diagnostics',
  'taskPanel.pending': 'Pending',
  'taskPanel.pendingTasks': '{count} pending',
  'taskPanel.processing': 'Processing',
  'taskPanel.processingAria': 'Task processing',
  'taskPanel.processingTasks': '{count} processing',
  'taskPanel.cancelRequested': 'Cancel requested',
  'taskPanel.cancelRequestedAria': 'Task cancel requested',
  'taskPanel.cancelled': 'Cancelled',
  'taskPanel.pendingAria': 'Task pending',
  'taskPanel.openRunFlow': 'View run flow',
  'taskPanel.openRunFlowAria': 'View {stock} run flow',
  'taskPanel.statusAria': 'Task status: {status}',
  'taskPanel.title': 'Analysis tasks',

  'runFlow.drawerTitle': 'Run Flow',
  'runFlow.eyebrow': 'RUN FLOW',
  'runFlow.title': 'Data and information flow',
  'runFlow.open': 'View run flow',
  'runFlow.openHistoryAria': 'View run flow for history record {recordId}',
  'runFlow.taskDrawerTitle': '{stock} run flow',
  'runFlow.historyDrawerTitle': '{stock} history run flow',
  'runFlow.loadingTitle': 'Loading run flow',
  'runFlow.loadingDescription': 'Reading the task snapshot, run diagnostics, and event path.',
  'runFlow.errorTitle': 'Run flow failed to load',
  'runFlow.retry': 'Reload',
  'runFlow.refresh': 'Refresh',
  'runFlow.refreshing': 'Refreshing',
  'runFlow.emptyTitle': 'No run flow',
  'runFlow.emptyDescription': 'Select an active task or historical report to inspect its run flow.',
  'runFlow.emptySnapshotTitle': 'No run-flow details yet',
  'runFlow.emptySnapshotDescription': 'This snapshot has no nodes or events; missing diagnostics show as a skeleton or empty state.',
  'runFlow.valueUnavailable': 'Not recorded',
  'runFlow.durationMs': '{value} ms',
  'runFlow.durationSeconds': '{value} sec',
  'runFlow.durationMinutes': '{value} min',
  'runFlow.status.pending': 'Pending',
  'runFlow.status.running': 'Running',
  'runFlow.status.success': 'Success',
  'runFlow.status.failed': 'Failed',
  'runFlow.status.degraded': 'Degraded',
  'runFlow.status.fallback': 'Fallback',
  'runFlow.status.timeout': 'Timeout',
  'runFlow.status.cancelRequested': 'Cancel requested',
  'runFlow.status.cancelled': 'Cancelled',
  'runFlow.status.skipped': 'Skipped',
  'runFlow.status.unknown': 'Unknown',
  'runFlow.severity.info': 'Info',
  'runFlow.severity.success': 'Success',
  'runFlow.severity.warning': 'Warning',
  'runFlow.severity.danger': 'Danger',
  'runFlow.edge.data': 'Data',
  'runFlow.edge.control': 'Control',
  'runFlow.edge.fallback': 'Fallback',
  'runFlow.edge.retry': 'Retry',
  'runFlow.edgeLabel.invoke': 'Invoke',
  'runFlow.edgeLabel.details': 'Details',
  'runFlow.nodeKind.entry': 'Entry',
  'runFlow.nodeKind.queue': 'Queue',
  'runFlow.nodeKind.dataSource': 'Data source',
  'runFlow.nodeKind.analysis': 'Analysis',
  'runFlow.nodeKind.model': 'Model',
  'runFlow.nodeKind.artifact': 'Artifact',
  'runFlow.nodeKind.notification': 'Notification',
  'runFlow.summary.elapsed': 'Elapsed',
  'runFlow.summary.fallbackCount': 'Fallback/retry',
  'runFlow.summary.failedAttempts': 'Failed attempts',
  'runFlow.summary.dataSources': 'Data sources',
  'runFlow.summary.task': 'Task',
  'runFlow.summary.trace': 'Trace',
  'runFlow.summary.model': 'Model',
  'runFlow.summary.generatedAt': 'Generated',
  'runFlow.graph.title': 'Run topology',
  'runFlow.graph.description': 'Auto-layered lanes show entry, data sources, analysis engines, and artifact paths.',
  'runFlow.graph.nodeAria': '{label} node, status {status}',
  'runFlow.graph.startedAt': 'Start',
  'runFlow.graph.expand': 'Expand',
  'runFlow.graph.collapse': 'Collapse',
  'runFlow.graph.expandNode': 'Expand {label} attempts',
  'runFlow.graph.collapseNode': 'Collapse {label} attempts',
  'runFlow.events.title': 'Event stream',
  'runFlow.events.count': '{count} events',
  'runFlow.events.filters': 'Event filters',
  'runFlow.events.filter.all': 'All',
  'runFlow.events.filter.important': 'Key',
  'runFlow.events.filter.problems': 'Failures/warnings',
  'runFlow.events.filter.fallback': 'Fallback/retry',
  'runFlow.events.filter.cancelled': 'Cancel',
  'runFlow.events.openNode': 'View node linked to event {title}',
  'runFlow.events.empty': 'No events match this filter.',
  'runFlow.nodeDetails.empty': 'Select a node to inspect details.',
  'runFlow.nodeDetails.title': 'Node details',
  'runFlow.nodeDetails.close': 'Close node details',
  'runFlow.nodeDetails.kind': 'Kind',
  'runFlow.nodeDetails.version': 'Version',
  'runFlow.nodeDetails.provider': 'Provider',
  'runFlow.nodeDetails.duration': 'Duration',
  'runFlow.nodeDetails.attempts': 'Attempts',
  'runFlow.nodeDetails.recordCount': 'Records',
  'runFlow.nodeDetails.startedAt': 'Started',
  'runFlow.nodeDetails.endedAt': 'Ended',
  'runFlow.nodeDetails.metadata': 'Metadata',
  'runFlow.nodeDetails.expandAttempts': 'Expand attempts',
  'runFlow.nodeDetails.collapseAttempts': 'Collapse attempts',
  'runFlow.nodeDetails.attemptList': 'Run attempts',
  'runFlow.nodeDetails.contextBlocks': 'Context inputs',
  'runFlow.nodeDetails.column.name': 'Name',
  'runFlow.nodeDetails.column.status': 'Status',
  'runFlow.nodeDetails.column.duration': 'Duration',
  'runFlow.nodeDetails.column.records': 'Records',
  'runFlow.nodeDetails.column.time': 'Time',
  'runFlow.nodeDetails.contextQuality': 'Context quality',
  'runFlow.nodeDetails.overallScore': 'Overall score',
  'runFlow.nodeDetails.qualityLevel': 'Level',
  'runFlow.nodeDetails.blockScores': 'Block scores',
  'runFlow.nodeDetails.count.available': 'Available',
  'runFlow.nodeDetails.count.missing': 'Missing',
  'runFlow.nodeDetails.count.partial': 'Partial',
  'runFlow.nodeDetails.count.degraded': 'Degraded',
  'runFlow.nodeDetails.count.fallback': 'Fallback',
  'runFlow.nodeDetails.count.skipped': 'Skipped',

  'report.addToWatchlist': 'Add to watchlist',
  'report.removeFromWatchlist': 'Remove from watchlist',
  'report.watchlist': 'Watchlist',

  'settings.actionSuccess': 'Success',
  'settings.activePanelDescription': 'Use unified field cards to maintain this configuration category.',
  'settings.activePanelTitle': 'Current category fields',
  'settings.agentSettings': 'Agent settings',
  'settings.alphaSift': 'AlphaSift screening',
  'settings.alphaSiftDescription': 'Enable the built-in experimental AlphaSift screening capability.',
  'settings.alphaSiftDisabled': 'Screening disabled',
  'settings.alphaSiftEnabled': 'Screening enabled',
  'settings.alphaSiftRisk': 'Experimental risk notice: screening results are for research and decision support only and are not investment advice. Markets involve risk; trading decisions and results are your responsibility.',
  'settings.alphaSiftSummary': 'When enabled, the left navigation shows Screening. Strategies and candidates come from AlphaSift; DSA adds quotes, fundamentals, and news context.',
  'settings.authCurrentPassword': 'Current admin password',
  'settings.authDescription': 'Manage admin password authentication to protect system settings.',
  'settings.authDisabled': 'Disabled',
  'settings.authEnabled': 'Enabled',
  'settings.authFailure': 'Authentication settings failed',
  'settings.authHelperDefault': 'Admin authentication protects Web settings and API endpoints from unauthorized access.',
  'settings.authHelperEnabled': 'Admin authentication is enabled. Use Change password below to update it.',
  'settings.authHelperNoPassword': 'No password has been set yet. Set an initial admin password before enabling authentication.',
  'settings.authHelperPasswordRetained': 'The previous admin password was retained. Enter it to re-enable authentication quickly.',
  'settings.authHelperTurnOff': 'If the current session is still valid, you can disable authentication directly. Otherwise, enter the current admin password.',
  'settings.authPasswordHintOff': 'Identity verification may be required before disabling authentication',
  'settings.authPasswordHintRetained': 'Enter the old password to reactivate authentication',
  'settings.authPasswordPlaceholder': 'Enter current password',
  'settings.authRequiredPassword': 'A new password is required',
  'settings.authSetPassword': 'Set admin password',
  'settings.authSetPasswordPlaceholder': 'Enter a new password (at least 6 characters)',
  'settings.authStatus': 'Admin authentication',
  'settings.authSuccessDisabled': 'Authentication disabled',
  'settings.authSuccessUpdated': 'Authentication settings updated',
  'settings.authTitle': 'Authentication and login protection',
  'settings.categoryNavDescription': 'System settings and authentication capabilities grouped by module.',
  'settings.categoryNavTitle': 'Configuration categories',
  'settings.changePasswordConfirm': 'Confirm new password',
  'settings.changePasswordConfirmPlaceholder': 'Enter the new password again',
  'settings.changePasswordCurrent': 'Current password',
  'settings.changePasswordCurrentPlaceholder': 'Enter current password',
  'settings.changePasswordDescription': 'Update the current admin login password. Use the new password for future logins.',
  'settings.changePasswordFailure': 'Password change failed',
  'settings.changePasswordNew': 'New password',
  'settings.changePasswordNewHint': 'At least 6 characters.',
  'settings.changePasswordNewPlaceholder': 'Enter new password',
  'settings.changePasswordRequiredCurrent': 'Enter the current password',
  'settings.changePasswordRequiredNew': 'Enter a new password',
  'settings.changePasswordSave': 'Save new password',
  'settings.changePasswordShort': 'New password must be at least 6 characters',
  'settings.changePasswordSuccess': 'Password changed',
  'settings.changePasswordSuccessMessage': 'The admin password was updated.',
  'settings.changePasswordTitle': 'Change password',
  'settings.checkDesktopUpdate': 'Check for updates',
  'settings.checkingDesktopUpdate': 'Checking...',
  'settings.configBackup': 'Configuration backup',
  'settings.configBackupDescription': 'Export the saved .env backup or restore configuration from a backup file. Importing overwrites keys present in the backup and reloads immediately.',
  'settings.currentCategoryEmptyDescription': 'This category has no editable fields. Switch categories on the left to view other system settings.',
  'settings.currentCategoryEmptyTitle': 'No fields in this category',
  'settings.desktopCheckError': 'Update check failed',
  'settings.desktopChecking': 'Checking for updates',
  'settings.desktopCurrentNoStatus': 'No update status yet. The app checks in the background after startup.',
  'settings.desktopDownload': 'Open release',
  'settings.desktopDownloaded': 'Update downloaded',
  'settings.desktopDownloading': 'Downloading update',
  'settings.desktopInstall': 'Restart to install',
  'settings.desktopInstalling': 'Installing update',
  'settings.desktopLatest': 'latest version',
  'settings.desktopManualUnsupported': 'This desktop runtime does not support automatic update installation. Open the release page to update manually.',
  'settings.desktopUpdate': 'Desktop update',
  'settings.desktopUpdateAvailable': 'New version available',
  'settings.desktopUpdateDescription': 'After startup, the app checks GitHub Releases for the latest stable version. The Windows installer build downloads updates in the background and silently restarts to install after confirmation.',
  'settings.desktopUpdateDownloadedMessage': 'The new version has been downloaded. Restart the app to finish installation.',
  'settings.desktopUpdateDownloadingMessage': 'Downloading the desktop update in the background{percent}.',
  'settings.desktopUpdateErrorMessage': 'Unable to complete the update check. Try again later.',
  'settings.desktopUpdateInstallingMessage': 'Restarting and installing the update.',
  'settings.desktopUpdateMessage': 'Current {current}, latest {latest}. {message}',
  'settings.desktopUpdateReleaseMessage': 'Open GitHub Releases to download the update.',
  'settings.desktopUpdateCheckingMessage': 'Checking GitHub Releases for available versions.',
  'settings.desktopUpToDate': 'Up to date',
  'settings.desktopUpToDateMessage': 'The desktop app is already up to date.',
  'settings.diagnosticHintDesktop': 'Check and provide the desktop log desktop.log, plus the release version, Windows version, and trigger path.',
  'settings.diagnosticHintWeb': 'Check the browser developer console and backend logs, and provide the release version, browser version, and trigger path.',
  'settings.disabledAuthBackupWarning': 'The Web app is not protected by admin authentication, so .env export/import is disabled. Set ADMIN_AUTH_ENABLED=true and sign in as admin before using it.',
  'settings.enableAuth': 'Enable authentication',
  'settings.disableAuth': 'Disable authentication',
  'settings.keepAuthDisabled': 'Keep disabled',
  'settings.keepAuthEnabled': 'Keep enabled',
  'settings.enableAlphaSift': 'Enable screening',
  'settings.disableAlphaSift': 'Disable screening',
  'settings.enablingAlphaSift': 'Enabling...',
  'settings.disablingAlphaSift': 'Disabling...',
  'settings.enabledAlphaSiftSuccess': 'AlphaSift screening enabled.',
  'settings.disabledAlphaSiftSuccess': 'AlphaSift screening disabled.',
  'settings.setupStatusConfigured': 'Configured',
  'settings.setupStatusInherited': 'Inherited',
  'settings.setupStatusNeedsAction': 'Needs action',
  'settings.setupStatusOptional': 'Optional',
  'settings.setupGuideHiddenTitle': 'First-run setup check is hidden',
  'settings.setupGuideHiddenDescription': 'Reopen it when you want to recheck base settings, models, and notification setup.',
  'settings.setupGuideOpen': 'Open check',
  'settings.setupGuideTitle': 'First-run setup check',
  'settings.setupGuideDescription': 'Check the watchlist, model channels, and notification setup for a minimal analysis flow, then submit a brief smoke run.',
  'settings.setupGuideCheckingTitle': 'Checking first-run setup',
  'settings.setupGuideCheckingSummary': 'Reading configuration status. Missing items and the smoke-run entry appear after the check completes.',
  'settings.setupGuideUnknownTitle': 'Setup status is unavailable',
  'settings.setupGuideUnknownSummary': 'The setup status check failed. You can still review settings and refresh the check later.',
  'settings.setupGuideCompleteTitle': 'Base setup is ready for minimal analysis',
  'settings.setupGuideIncompleteTitle': 'Some base setup still needs attention',
  'settings.setupGuideMissingSummary': '{count} item(s) still need action: {labels}',
  'settings.setupGuideReadySummary': 'All required items are ready. Run a brief analysis to verify the flow.',
  'settings.setupGuideRefreshing': 'Refreshing...',
  'settings.setupGuideRefresh': 'Refresh check',
  'settings.setupGuideHide': 'Hide for now',
  'settings.setupGuideConfigureLlm': 'Configure models',
  'settings.setupGuideAddStocks': 'Manage watchlist',
  'settings.setupGuideConfigureNotification': 'Configure notifications',
  'settings.setupGuideSmokeRunning': 'Submitting...',
  'settings.setupGuideSmokeNeedsStock': 'Add at least one watchlist stock before running the smoke check.',
  'settings.setupGuideRunSmoke': 'Brief smoke run',
  'settings.setupGuideSmokeNotReady': 'Complete the required setup before running the smoke check.',
  'settings.setupGuideSmokeUnavailableTitle': 'Smoke check unavailable',
  'settings.setupGuideSmokeAcceptedWithTask': 'Submitted a brief analysis for {stock}: {taskId}',
  'settings.setupGuideSmokeAccepted': 'Submitted a brief analysis for {stock}.',
  'settings.schedulerAddTime': 'Add time',
  'settings.schedulerDescription': 'Configure the daily automatic analysis times. After saving, long-running Web/API/Desktop processes apply the new schedule.',
  'settings.schedulerDisabled': 'Disabled',
  'settings.schedulerEffectiveTimes': 'Active times',
  'settings.schedulerEnable': 'Enable scheduled task',
  'settings.schedulerEnabled': 'Enabled',
  'settings.schedulerEnableDescription': 'When enabled, analysis runs automatically at the times below.',
  'settings.schedulerLastError': 'Last error',
  'settings.schedulerLastSuccess': 'Last success',
  'settings.schedulerNextRun': 'Next run',
  'settings.schedulerRefresh': 'Refresh status',
  'settings.schedulerRefreshing': 'Refreshing...',
  'settings.schedulerRemoveTime': 'Remove time',
  'settings.schedulerRunAccepted': 'Run request submitted.',
  'settings.schedulerRunNow': 'Run once now',
  'settings.schedulerRunning': 'Running',
  'settings.schedulerRunningNow': 'Running...',
  'settings.schedulerStatus': 'Current status',
  'settings.schedulerTimeInputAria': 'Scheduled time {index}',
  'settings.schedulerTimes': 'Scheduled times',
  'settings.schedulerTitle': 'Scheduled task',
  'settings.envExported': 'Saved .env backup exported.',
  'settings.envImported': '.env backup imported and configuration reloaded.',
  'settings.envImportedRefreshFailedMessage': 'The backup was imported, but configuration reload failed. Reload the page manually.',
  'settings.envImportedRefreshFailedRaw': 'Env import succeeded but config refresh failed',
  'settings.envImportedRefreshFailedTitle': 'Config imported but refresh failed',
  'settings.exportEnv': 'Export .env',
  'settings.exportingEnv': 'Exporting...',
  'settings.fallbackVersionWarning': 'package.json is still the placeholder version 0.0.0. The page falls back to the build ID so old static assets are not misread as current.',
  'settings.fieldAddKey': 'Add key',
  'settings.fieldDelete': 'Delete',
  'settings.fieldSensitiveHint': 'Sensitive content is hidden by default. Click the eye icon to reveal plaintext.',
  'settings.fieldSensitiveMultiHint': ' Multiple inputs can be added or removed.',
  'settings.helpClose': 'Close configuration help',
  'settings.helpExamples': 'Examples',
  'settings.helpImpact': 'Impact',
  'settings.helpNotes': 'Notes',
  'settings.helpPurpose': 'Usage',
  'settings.helpRelatedDocs': 'Related docs',
  'settings.helpTitleFallback': 'Configuration help',
  'settings.helpTooltip': 'View configuration help',
  'settings.helpValueNotes': 'Values',
  'settings.importConfirmContinue': 'Continue import',
  'settings.importConfirmMessage': 'This page has unsaved local edits. Continuing will discard those drafts and immediately update saved configuration with keys from the backup.',
  'settings.importConfirmTitle': 'Import overwrites current drafts',
  'settings.importEnv': 'Import .env',
  'settings.importingEnv': 'Importing...',
  'settings.intelligentImport': 'Smart import',
  'settings.intelligentImportDescription': 'Extract stock codes from images, files, or clipboard text and merge them into the watchlist.',
  'settings.intelligentImportSupportedInputs': 'Images, CSV/Excel files, and clipboard text',
  'settings.intelligentImportHint': 'Image recognition requires a configured Vision model. Review parsed results before merging them into the watchlist.',
  'settings.intelligentImportChooseImage': 'Choose image',
  'settings.intelligentImportChooseFile': 'Choose file',
  'settings.intelligentImportPastePlaceholder': 'Or paste text copied from CSV/Excel...',
  'settings.intelligentImportParse': 'Parse',
  'settings.intelligentImportReviewWarning': 'Review each item before merging. High-confidence items are selected by default; medium/low confidence items need manual confirmation.',
  'settings.intelligentImportSelectionSummary': '{valid} mergeable, {checked} selected',
  'settings.intelligentImportClear': 'Clear',
  'settings.intelligentImportMergeToWatchlist': 'Merge into watchlist',
  'settings.intelligentImportImageTypeError': 'Images must be JPG, PNG, WebP, or GIF',
  'settings.intelligentImportImageSizeError': 'Images must be 5MB or smaller',
  'settings.intelligentImportFileSizeError': 'Files must be 2MB or smaller',
  'settings.intelligentImportTextSizeError': 'Pasted text must be 100KB or smaller',
  'settings.intelligentImportRecognitionFailed': 'Recognition failed. Try again.',
  'settings.intelligentImportRateLimited': 'Too many requests. Try again later.',
  'settings.intelligentImportTimeout': 'Request timed out. Check the network and retry.',
  'settings.intelligentImportParseFailed': 'Parse failed',
  'settings.intelligentImportLoadConfigFirst': 'Load configuration before merging',
  'settings.intelligentImportConfigUpdated': 'Configuration changed. Click "Merge into watchlist" again.',
  'settings.intelligentImportMergeFailed': 'Merge save failed',
  'settings.llmAccess': 'AI model access',
  'settings.llmAccessDescription': 'Manage model channels, base URLs, API keys, primary models, and fallbacks.',
  'settings.notificationSettings': 'Notification settings',
  'settings.notificationTest': 'Notification test',
  'settings.notificationTestBody': 'Body',
  'settings.notificationTestChannel': 'Channel',
  'settings.notificationTestContent': 'This is a test notification from the DSA Web settings page.',
  'settings.notificationTestDescription': 'Send a real test notification using the current page draft. This test does not save configuration.',
  'settings.notificationTestFailure': 'Test failed',
  'settings.notificationTestSend': 'Send test',
  'settings.notificationTestSuccess': 'Test succeeded',
  'settings.notificationTestTimeout': 'Timeout seconds',
  'settings.notificationTestTitle': 'Title',
  'settings.notificationTestTitleValue': 'DSA notification test',
  'settings.notificationTesting': 'Testing...',
  'settings.openConfigItems': 'View fields',
  'settings.pageDescription': 'Manage models, data sources, notifications, security authentication, and import capabilities.',
  'settings.pageTitle': 'System settings',
  'settings.pageTitleDocument': 'System settings - DSA',
  'settings.promptCacheAdvancedDescription': 'Maintain provider prompt-cache telemetry, active hints, and sanitized diagnostics. Defaults are suitable for normal use.',
  'settings.promptCacheAdvancedTitle': 'Provider Prompt Cache advanced settings',
  'settings.reload': 'Reload',
  'settings.reset': 'Reset',
  'settings.revert': 'Revert',
  'settings.saveConfig': 'Save configuration',
  'settings.saveConfigWithCount': 'Save configuration ({count})',
  'settings.saveRetry': 'Retry save',
  'settings.saving': 'Saving...',
  'settings.updateBuildDescription': 'After rebuilding the frontend or Docker image, the build ID and build time here update. Use them to confirm the current page assets are active.',
  'settings.versionBuildId': 'Build ID',
  'settings.versionBuildTime': 'Build time',
  'settings.versionDesktop': 'Desktop version',
  'settings.versionInfo': 'Version info',
  'settings.versionInfoDescription': 'Use this to confirm the current WebUI static assets are on the latest build.',
  'settings.versionWebui': 'WebUI version',
  'settings.viewConfigItems': 'View fields',
  'settings.envExportNote': 'Exports include only currently saved configuration, not unsaved local drafts on the page.',
  'settings.envDockerNote': 'In Docker deployments, --env-file and Compose env_file inject environment variables only at startup. This export/import area uses the backend active .env file. To keep WebUI-saved values across container rebuilds, point ENV_FILE to a writable data-volume file such as /app/data/runtime.env and avoid keeping same-name old values in the startup environment.',
};

export const UI_TEXT: Record<UiLanguage, Record<UiTextKey, string>> = {
  zh,
  en,
};

export type UiTextParams = Record<string, string | number>;

export function formatUiText(template: string, params?: UiTextParams): string {
  if (!params) {
    return template;
  }

  return template.replace(/\{(\w+)\}/g, (match, key: string) => {
    const value = params[key];
    return value === undefined ? match : String(value);
  });
}
