Skip to content
This repository was archived by the owner on Nov 4, 2026. It is now read-only.
This repository was archived by the owner on Nov 4, 2026. It is now read-only.

CloudAiModelStatus 直接渲染服务端 report.summary,该文案未本地化 #2886

Closed

Description

@os-zhuang

问题

packages/app-shell/src/console/diagnostics/CloudAiModelStatus.tsx:149

<p className="text-sm text-foreground">{report.summary}</p>

这是该诊断面板最显眼的一句话(面板顶部的摘要),内容整条来自服务端,客户端原样渲染。服务端是否按请求语言生成这段文案没有保证——同一面板里其它文案都在客户端按 locale 选择,唯独这一条不是。

为什么单独开

这个组件里的其它 10 处文案是内联 {en,zh} 写死(手搓 pick()),那部分属于 objectui#2871,已在那边跟踪。

report.summary 是另一类问题:它的修法不在 console 侧——要么服务端按 Accept-Language 返回本地化 summary,要么改为返回结构化字段让客户端自己拼。两条路都需要先确认服务端契约归谁(该 widget 的页面元数据在 cloud 仓库),所以不适合混在 #2871 的文案迁移里。

建议

  1. 先确认 /…/ai-model-status 这个接口的 summary 是否已按 Accept-Language 本地化(如果已经是,则本 issue 只需补一条说明,关掉即可)
  2. 如果没有,倾向于返回结构化数据而非整句——诊断摘要通常是「模型 X,来源 Y,状态 Z」这种可组装结构,客户端拼装比服务端多语言渲染更好维护,也和该面板已有的 sourceLabel() 枚举→文案的做法一致

发现来源:objectui#2871 的分类调研。

Activity

  1. os-zhuang commented on Jul 28, 2026

    @os-zhuang
    ContributorAuthor

    第 1 步已查清:客户端已经在发 Accept-Language,问题纯粹在服务端

    原 issue 建议"先确认接口是否已按 Accept-Language 本地化"。客户端这半边可以确定了。

    CloudAiModelStatus 走的是 createAuthenticatedFetch()(:65),而该 fetch 自 #1319 起就会把 <html lang> 折进 Accept-Language:

    // packages/auth/src/createAuthenticatedFetch.ts:127
    if (isApiCall && !headers.has('Accept-Language') && typeof document !== 'undefined') {
      const lang = document.documentElement.lang;
      if (lang) headers.set('Accept-Language', lang);
    }

    请求地址是 /api/v1/ai/effective-model(DEFAULT_URL,:44),/api 前缀满足 isApiCall;<html lang> 由 i18n provider 与应用内语言切换器保持同步。所以服务端每次都能拿到当前 UI 语言。

    也就是说这里没有"客户端没告诉服务端"的问题,report.summary 是否本地化完全取决于 /api/v1/ai/effective-model 的实现。该接口在 cloud 仓库,不在本会话的仓库范围内(仅 objectstack / objectui),我无法确认。

    剩下要做的判断

    1. 若该接口已按 Accept-Language 生成 summary → 本 issue 可直接关闭,无需改动
    2. 若未本地化 → 倾向原 issue 的第 2 条建议:返回结构化字段而非整句。这个面板本来就是这个路子——sourceLabel() 已经是"枚举 → 客户端文案",而且 10 处文案已在 14 个文件手搓 startsWith('zh') 判断绕开语言包,其余 8 种语言硬回退英文且无法翻译 #2871 part 1 迁进语言包(aiModelStatus.*)。summary 改成结构化后能直接沿用同一套机制,不必在服务端再维护一份 10 语文案

    顺带一提

    :141 那行 <p>{report.summary}</p> 是这个组件里唯一还没走 t() 的可见文案——其余全部已迁移。所以本 issue 收尾后,该组件的 i18n 就完整了。


    Generated by Claude Code

  2. os-zhuang commented on Jul 28, 2026

    @os-zhuang
    ContributorAuthor

    已查 cloud 源码:服务端没有本地化,但也不需要改服务端

    重开跟进。查了 objectstack-ai/cloud,两个问题都有确定答案了。

    1. 服务端确实没本地化,而且当前结构下做不到

    packages/service-ai/src/effective-model.ts:117 —— summary 是硬编码英文模板字面量:

    const summary = `build/ask uses ${input.conversational ?? 'unknown'} (${pinnedNote}); structured uses ${input.structured ?? 'unknown'}${input.structuredPinned ? '' : ' (same as build/ask)'}.${routingNote}`;

    函数签名里没有 locale 参数。更彻底的是路由层 packages/service-ai/src/routes/ai-routes.ts:395:

    handler: async () => {
      const report = opts.getEffectiveModel?.();
      return { status: 200, body: report };
    }

    handler 不接收 request 参数,所以它连 Accept-Language 都读不到。客户端一直在发这个头(createAuthenticatedFetch 自 objectui#1319 起),但这条服务端路径上没有任何东西去读它。

    2. 但拼这句话的原料早就全发过来了

    对照 summary 的每个成分:

    summary 成分 结构化字段 状态
    build/ask uses X conversational.model ✅ 已返回
    (pinnedNote) conversational.source(code-default 或 env:KEY) ✅ 已返回
    structured uses Y structured.model ✅ 已返回
    (same as build/ask) structured.pinned ✅ 已返回
    Routing policy: free → A, paid → B routing.{free,paid} ✅ 服务端已返回

    而且客户端已有对应的本地化 key(aiModelStatus.sourceCodeDefault / sourceInherits / sourcePinned),sourceLabel() 也已在处理这三种 source 形态。

    本 issue 建议的第 2 条「返回结构化数据而非整句」——服务端早就在这么做了。 只是客户端没用,转而渲染了那句英文摘要。所以这是纯客户端修复,零服务端改动,不必等 cloud 侧排期。

    3. 顺带发现:一条诊断信息在类型层面被丢掉了

    客户端的 EffectiveModelReport 接口(CloudAiModelStatus.tsx:28-34)没有声明 routing:

    $ grep -c "routing" packages/app-shell/src/console/diagnostics/CloudAiModelStatus.tsx
    0
    

    服务端条件性返回它,客户端类型里没有,所以路由策略这条信息目前只能通过那句英文 summary 看到——非英语用户实际上完全拿不到。这已经不只是 i18n 问题了。

    修法

    纯客户端:类型补 routing、新增几条 aiModelStatus.* key(十个语言包一次补齐)、把 <p>{report.summary}</p> 换成用已有结构化字段组装的本地化句子。


    Generated by Claude Code

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions