问题与复现
现象 :组合风险面板(PortfolioRiskPanel)里每条风险信号右侧的严重度徽标,在中文界面下始终显示英文 High / Medium / Low,不随语言切换。
根因 :packages/ui/src/atoms/portfolioRiskAtoms.ts 的 severityVisual() 把展示文案硬编码成英文字面量直接返回,消费端 PortfolioRiskPanel.tsx 又原样渲染,全链路没有经过 t()。
// packages/ui/src/atoms/portfolioRiskAtoms.ts(修复前)
export interface SeverityVisual {
tone : 'high' | 'medium' | 'low' ;
color : string ;
label : string ; // ← 英文字面量
}
export function severityVisual ( severity : RiskSeverity ) : SeverityVisual {
switch ( severity ) {
case 'high' :
return { tone : 'high' , color : 'var(--mac-red)' , label : 'High' } ;
case 'medium' :
return { tone : 'medium' , color : 'var(--mac-yellow)' , label : 'Medium' } ;
case 'low' :
default :
return { tone : 'low' , color : 'var(--mac-green)' , label : 'Low' } ;
}
}
// packages/ui/src/components/portfolio/PortfolioRiskPanel.tsx:114-127(修复前)
const SignalCard : React . FC < { signal : RiskSignal } > = ( { signal } ) => {
const visual = severityVisual ( signal . severity ) ;
return (
...
< span className = "ml-auto text-[11px] uppercase tracking-wide" style = { { color : visual . color } } >
{ visual . label } { /* ← 直接输出英文字面量,未经 t() */ }
</ span >
) ;
} ;
具体反例 (渲染 zh-CN 界面):
输入
实际输出
预期输出
severityVisual('high')
High
高
severityVisual('medium')
Medium
中
severityVisual('low')
Low
低
预期与修复方向
沿用本仓库既已成型、且在同一目录 已有先例的「枚举 → i18n key」范式(ImportDraftReview.tsx 的 confidenceVisual() 就是 return { key: 'portfolio.confidence.high', tone },再由调用方 t()),把 severityVisual() 的返回值从英文字面量改为 i18n key :
SeverityVisual.label → labelKey。仓库内该字段名是主流写法(EvaluationCenter.tsx 的 TAB_LABELS / STATUS_LABEL、CandidateCard.tsx 均用 labelKey),故不沿用兄弟接口的 key,取语义更明确的 labelKey。
新增 portfolio.severity.{high,medium,low} 三键到 en-US / zh-CN 两套 locale。
PortfolioRiskPanel.tsx 的 SignalCard 取 const { t } = useTranslation();,渲染 {t(visual.labelKey)}。
顺带修正一处过时注释 :portfolioRiskAtoms.ts 头部文档注释声称该 IPC 通道「is not wired yet … until the Lead adds it」,实测早已接线 ,属过时描述,一并订正为当前真实链路:
apps/electron/src/main/index.ts:248 ipcMain.handle('portfolioRisk:analyze', …)
apps/electron/src/main/kernelHost.ts:804 async portfolioRiskAnalyze() { return this.portfolioRisk.analyze(); }
apps/electron/src/preload/index.ts:292 analyze: () => ipcRenderer.invoke('portfolioRisk:analyze')
apps/electron/src/renderer/finagentClient.ts:98 analyze: () => ipcResult(window.electronAPI.portfolioRisk.analyze())
复现证据
环境:Windows 10、Bun 1.4.2(744846f84)
基线 main SHA:3a17eca6(2026-10-03T16:16:35Z)
聚焦测试(改写 packages/ui/src/atoms/portfolioRiskAtoms.test.ts,新增第 4 个用例):
修复前 :bun test packages/ui/src/atoms/portfolioRiskAtoms.test.ts → 0 pass / 4 fail
(失败差异:Expected { color, labelKey: 'portfolio.severity.low', tone } / Received { color, label: 'Low', tone })
修复后 :同一命令 → 4 pass / 0 fail
全量回归:bun test packages/ui --isolate → 347 pass / 0 fail(63 文件)
类型检查:bun run typecheck → @finagent/core / i18n / shared / ui / electron 全部 exit 0
键位一致性:bun run i18n:check → en-US 1490 键 ≡ zh-CN 1490 键(0 issues)
新增用例断言:前 3 个保持 tone/color 契约不变;第 4 个断言三个新键在 en-US 与 zh-CN 下都能解析 (t(key) !== key,缺失键会被原样回显)且两种语言文案互不相同 。
说明:上游 .github/workflows/pr.yml 当前为 disabled_manually,新 PR 不会产生 check run;以上均为等价本地命令 的自测结果,非 CI。
查重与冲突
目标文件已对当前 83 个 open PR 的改动文件做交集查重:packages/ui/src/atoms/portfolioRiskAtoms.ts、packages/ui/src/atoms/portfolioRiskAtoms.test.ts 零冲突 。
存在软冲突 (同文件、hunk 不相交,已逐条核对偏移):
第三方 fix(portfolio-risk): 防止跨币种持仓扭曲风险权重与摘要 #288 (fix/portfolio-risk-currency,非 draft):
PortfolioRiskPanel.tsx — 本 PR 只碰 :112(+1 行 useTranslation)与 :122;fix(portfolio-risk): 防止跨币种持仓扭曲风险权重与摘要 #288 的 hunk 为 @@ -11,7 +11,10 @@、@@ -24,22 +27,31 @@、@@ -50,7 +62,7 @@ ⇒ 不相交 。
portfolio.ts ×2 — 本 PR 在文件尾部新增,hunk 为 en-US @@ -80,4 +80,9 @@ / zh-CN @@ -81,4 +81,9 @@;fix(portfolio-risk): 防止跨币种持仓扭曲风险权重与摘要 #288 的 hunk 为 en-US @@ -12,12 +12,15 @@ / zh-CN @@ -13,12 +13,15 @@ ⇒ 不相交 。
本人已开 ui: 组合失败态详情行硬编码英文(partial 横幅在中文界面显示英文);同源另有 failure 被同函数 catch 清空 #299 (codex/fix-portfolio-failure-detail):两套 portfolio.ts 的 hunk 为 en-US @@ -41,6 +41,18 @@ / zh-CN @@ -42,6 +42,16 @@,与本 PR 的文件尾部新增键 ⇒ 不相交 。
范围
仅改动 5 个文件:
packages/ui/src/atoms/portfolioRiskAtoms.ts(label → labelKey + 注释订正)
packages/ui/src/atoms/portfolioRiskAtoms.test.ts(3 个既有用例改字段名 + 1 个新用例)
packages/ui/src/components/portfolio/PortfolioRiskPanel.tsx(SignalCard 接入 t())
packages/i18n/src/locales/en-US/portfolio.ts(新增 severity 三键)
packages/i18n/src/locales/zh-CN/portfolio.ts(新增 severity 三键)
不改变任何运行时分支(tone / color 契约不变),不新增依赖。
问题与复现
现象:组合风险面板(
PortfolioRiskPanel)里每条风险信号右侧的严重度徽标,在中文界面下始终显示英文High/Medium/Low,不随语言切换。根因:
packages/ui/src/atoms/portfolioRiskAtoms.ts的severityVisual()把展示文案硬编码成英文字面量直接返回,消费端PortfolioRiskPanel.tsx又原样渲染,全链路没有经过t()。具体反例(渲染 zh-CN 界面):
severityVisual('high')High高severityVisual('medium')Medium中severityVisual('low')Low低预期与修复方向
沿用本仓库既已成型、且在同一目录已有先例的「枚举 → i18n key」范式(
ImportDraftReview.tsx的confidenceVisual()就是return { key: 'portfolio.confidence.high', tone },再由调用方t()),把severityVisual()的返回值从英文字面量改为 i18n key:SeverityVisual.label→labelKey。仓库内该字段名是主流写法(EvaluationCenter.tsx的TAB_LABELS/STATUS_LABEL、CandidateCard.tsx均用labelKey),故不沿用兄弟接口的key,取语义更明确的labelKey。portfolio.severity.{high,medium,low}三键到en-US/zh-CN两套 locale。PortfolioRiskPanel.tsx的SignalCard取const { t } = useTranslation();,渲染{t(visual.labelKey)}。顺带修正一处过时注释:
portfolioRiskAtoms.ts头部文档注释声称该 IPC 通道「is not wired yet … until the Lead adds it」,实测早已接线,属过时描述,一并订正为当前真实链路:复现证据
744846f84)3a17eca6(2026-10-03T16:16:35Z)packages/ui/src/atoms/portfolioRiskAtoms.test.ts,新增第 4 个用例):bun test packages/ui/src/atoms/portfolioRiskAtoms.test.ts→ 0 pass / 4 fail(失败差异:
Expected { color, labelKey: 'portfolio.severity.low', tone } / Received { color, label: 'Low', tone })bun test packages/ui --isolate→ 347 pass / 0 fail(63 文件)bun run typecheck→@finagent/core/i18n/shared/ui/electron全部 exit 0bun run i18n:check→ en-US 1490 键 ≡ zh-CN 1490 键(0 issues)en-US与zh-CN下都能解析(t(key) !== key,缺失键会被原样回显)且两种语言文案互不相同。.github/workflows/pr.yml当前为disabled_manually,新 PR 不会产生 check run;以上均为等价本地命令的自测结果,非 CI。查重与冲突
packages/ui/src/atoms/portfolioRiskAtoms.ts、packages/ui/src/atoms/portfolioRiskAtoms.test.ts零冲突。fix/portfolio-risk-currency,非 draft):PortfolioRiskPanel.tsx— 本 PR 只碰:112(+1 行useTranslation)与:122;fix(portfolio-risk): 防止跨币种持仓扭曲风险权重与摘要 #288 的 hunk 为@@ -11,7 +11,10 @@、@@ -24,22 +27,31 @@、@@ -50,7 +62,7 @@⇒ 不相交。portfolio.ts×2 — 本 PR 在文件尾部新增,hunk 为 en-US@@ -80,4 +80,9 @@/ zh-CN@@ -81,4 +81,9 @@;fix(portfolio-risk): 防止跨币种持仓扭曲风险权重与摘要 #288 的 hunk 为 en-US@@ -12,12 +12,15 @@/ zh-CN@@ -13,12 +13,15 @@⇒ 不相交。codex/fix-portfolio-failure-detail):两套portfolio.ts的 hunk 为 en-US@@ -41,6 +41,18 @@/ zh-CN@@ -42,6 +42,16 @@,与本 PR 的文件尾部新增键 ⇒ 不相交。范围
packages/ui/src/atoms/portfolioRiskAtoms.ts(label→labelKey+ 注释订正)packages/ui/src/atoms/portfolioRiskAtoms.test.ts(3 个既有用例改字段名 + 1 个新用例)packages/ui/src/components/portfolio/PortfolioRiskPanel.tsx(SignalCard接入t())packages/i18n/src/locales/en-US/portfolio.ts(新增severity三键)packages/i18n/src/locales/zh-CN/portfolio.ts(新增severity三键)tone/color契约不变),不新增依赖。