Skip to content

fix(ui): 组合风险严重度标签硬编码英文,中文界面仍显示 High/Medium/Low #310

Description

@wxrbyte

问题与复现

现象:组合风险面板(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。

查重与冲突

范围

  • 仅改动 5 个文件:
    1. packages/ui/src/atoms/portfolioRiskAtoms.ts(label → labelKey + 注释订正)
    2. packages/ui/src/atoms/portfolioRiskAtoms.test.ts(3 个既有用例改字段名 + 1 个新用例)
    3. packages/ui/src/components/portfolio/PortfolioRiskPanel.tsx(SignalCard 接入 t())
    4. packages/i18n/src/locales/en-US/portfolio.ts(新增 severity 三键)
    5. packages/i18n/src/locales/zh-CN/portfolio.ts(新增 severity 三键)
  • 不改变任何运行时分支(tone / color 契约不变),不新增依赖。

Activity

  1. wxrbyte commented on Oct 8, 2026

    @wxrbyte
    ContributorAuthor

    /claim

  2. added
    claimedClaimed by a contributor and currently in progress
    on Oct 8, 2026
  3. github-actions commented on Oct 8, 2026

    @github-actions

    @wxrbyte 已认领该 Issue,并已自动设为 Assignee。提交 PR 时请在描述中写 Closes #310。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

claimedClaimed by a contributor and currently in progress

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions