Skip to content

zh-CN: three screen-flow dialogs repeat the flow's own label as the screen title (Convert Lead shows 线索转化流程 twice): the zh-CN pack translates screens.screen_1.title as the flow label #2096

Closed

Description

@objectstack-fleet

Filing gate ①: a user-visible defect, reproduced in a browser.
reach: the console in zh-CN, as a manager.
Filed by the repo:hotcrm seat (session_01BCDqr1DqnQjEh5jA9gGkUG) from the v18 test pass #2093 (finding 06), under the maintainer's 「测试遇到问题就报issue」. ⛔ Not a claim.
Reader: this seat's queue.
Dedupe: the hotcrm index on screen title / screen_1 / screen translation. Nearest: #1210 and #1975 (closed, which brought flow translations in), neither this mistranslation.

What happens (main 2f3d898d, @objectstack/* 18.0.0-next.0)

With the zh-CN locale, open a lead and click 转化线索. The dialog's eyebrow and its title both read 线索转化流程. In English they read "Lead Conversion Process" / "Conversion Details".

Screenshot: 06-zh-cn-convert-screen-title-repeats-flow-label.png (on #2093's branch).

Cause (from the dev's read of the pack)

src/sales/translations/zh-CN/app.ts sets screens.screen_1.title equal to the FLOW label on three flows:

flow line (dev's reading) zh-CN title EN screen title
lead_conversion ~613 线索转化流程 Conversion Details
quote_generation ~659 从商机生成报价单 Quote Details
campaign_enrollment ~710 将成员加入营销活动 Enrollment Criteria

The other four screens (escalate / close / claim / schedule follow-up) are fine. es-ES and ja-JP were not checked.

Fix direction

  • Translate each screen title as its English screen title, e.g. 转化详情 / 报价单详情 / 加入条件. Reuse wording the pack already carries for the same objects and actions.
  • Check the same three keys in es-ES and ja-JP.
  • Translations sit outside the token ratchet.

Generated by Claude Code

Activity

  1. added
    bugSomething isn't working
    pm:queueReady for the PM dispatch loop
    pm:dispatchedDispatched to a dev agent by /pm-dispatch
    and removed
    pm:queueReady for the PM dispatch loop
    on Oct 13, 2026
  2. objectstack-fleet commented on Oct 14, 2026

    @objectstack-fleet
    ContributorAuthor

    Claim: PM loop round R85
    Session: session_01P8mZuzuyZAHSrgQKmv6ASv
    Account: sunhaolin (the seat's linked user as GET /user answers it; always the card's assignee)
    Branch: claude/issue-2096-screen-titles
    Worktree: hotcrm-issue-2096
    Domain: repo:hotcrm (single-lane repo, no domain:* taxonomy)
    Seat: repo:hotcrm#1
    File surface: src/sales/translations/zh-CN/app.ts (the screens.screen_1.title of lead_conversion, quote_generation and campaign_enrollment only; on 2f3d898d at L659, L710 and L613); the same three keys in src/sales/translations/es-ES/ and ja-JP/ only if measured equal to the flow label there too; tests under test/ only if one pins these titles; one .changeset/2096-*.md (stop on breach; explain in the report)
    Container & model: S (three to nine strings; the judgment is the wording, reused from what each pack already carries), mode:subagent, model: default (dispatch-gates --tier --repo objectstack-ai/hotcrm src/sales/translations/zh-CN/app.ts: "no path-derived mandate"; the tier stays the PM's per-card call)
    Clause-②: no
    Responsibility: the app: its zh-CN pack sets three screen titles equal to the flow label | the platform path that already covers it: the pack's screens.SCREEN.title key, which the other four screens use correctly | every zh-CN user who opens Convert Lead, Generate Quote or Enroll Members, today
    Thread-read: none
    Serial constraints cleared: src/sales/translations/*/app.ts: nothing in flight on it. In flight this round: #2094 (lead.view.ts columns; may touch field labels in src/sales/translations/*/objects.*.ts, a different file) and #2097 (lead.view.ts create form). #2095 moved to pm:blocked (6163861799), freeing this slot. Last change under src/sales/translations/: 2f3d898d (#2091), yesterday. Translations sit outside the token ratchet.


    Generated by Claude Code

  3. objectstack-fleet commented on Oct 14, 2026

    @objectstack-fleet
    ContributorAuthor

    os-dev-report
    {
    "issue": 2096,
    "status": "done",
    "branch": "claude/issue-2096-screen-titles",
    "pr": "#2100",
    "session": "session_01P8mZuzuyZAHSrgQKmv6ASv (subagent: the parent PM session id)",
    "premise_still_valid": true,
    "summary": "The zh-CN, es-ES and ja-JP packs set flows.FLOW.screens.screen_1.title equal to the flow label on lead_conversion, quote_generation and campaign_enrollment. As a result the dialog showed the flow name twice: as the eyebrow (flow label) and as the title. The executor heads a screen with no config.title by its node label (service-automation 18.0.0-next.0 dist/index.js L11247, title = heading() ?? node.label), so English already showed Conversion Details / Quote Details / Enrollment Criteria. The nine titles now translate those node labels, using terms each pack already carries: zh-CN 转化详情 / 报价单详情 / 加入条件, es-ES Detalles de la Conversión / Detalles de la Cotización / Criterios de Inscripción, ja-JP 変換詳細 / 見積詳細 / 登録条件. The pack comment that gave the wrong fallback rationale is corrected in the same three files. H1 to H4 all confirmed: H1 lines on 2f3d898 are zh-CN L613 campaign_enrollment, L659 lead_conversion, L710 quote_generation; H3 es-ES and ja-JP had the same defect on the same three keys; H4 confirmed by DOM probe before and after.",
    "tests": "Gates at 470b540, each exit captured before any pipe: pnpm validate exit 0 "✓ Validation passed (2845ms)"; pnpm typecheck exit 0 (tsc --noEmit, no output); pnpm lint exit 0 "18 suggestion(s)"; pnpm lint:i18n-gate exit 0 "✓ i18n lint gate: 0 i18n/missing-* issues (18 total lint issue(s) reported, unaffected by this gate)"; pnpm hygiene exit 0 "✓ source hygiene clean"; pnpm hygiene:tokens exit 0 "✓ source token ratchet clean"; pnpm build exit 0 "✓ Build complete (3478ms)" with lock VERDICT command-exit 0; pnpm test exit 0 "Test Files 179 passed (179)", "Tests 3659 passed | 1 skipped (3660)". | validate, lint and test ran in one os-verify-lock call joined with ";", so the lock printed VERDICT batch-last-exit 0. Each gate exit was written separately to a file inside the call: validate=0 lint=0 test=0. | Pack probe (tsx over the four flow barrels and the zh-CN/es-ES/ja-JP packs, comparing screen title with flow label): before, 7 dup=true rows (the 3 card keys in each of 3 packs, plus the 4 single-screen flows whose English node label equals the flow label); after, 4 rows (only those 4 single-screen flows, which match English). | Console DOM probe (Playwright, executablePath /opt/pw-browsers/chromium, objectstack dev -p 4104, admin, browser locale per row; reads [role=dialog] p.text-xs and h2). Before (2f3d898): zh-CN 线索转化流程/线索转化流程, 从商机生成报价单/从商机生成报价单, 将成员加入营销活动/将成员加入营销活动; es-ES and ja-JP showed the eyebrow text again as the title; en-US Lead Conversion Process/Conversion Details, Generate Quote from Opportunity/Quote Details, Enroll Members in Campaign/Enrollment Criteria. After (470b540): zh-CN 线索转化流程/转化详情, 从商机生成报价单/报价单详情, 将成员加入营销活动/加入条件; es-ES .../Detalles de la Conversión, .../Detalles de la Cotización, .../Criterios de Inscripción; ja-JP .../変換詳細, .../見積詳細, .../登録条件; en-US unchanged. | No ablation and no new test: no test pins these titles, and the claim admits tests only if one already does. A screen-title guard would be new tooling of the kind AGENTS.md §3 rules out. The PR body carries the before and after table. | Control-byte self-scan on the 4 changed files: grep -naP over the control range found nothing (exit 1). pnpm hygiene "no raw control bytes in first-party files" also passed.",
    "mcp_calls": "0 — no MCP tool was called",
    "api_writes": "2 — both through the fleet-write relay (POST /repos/objectstack-ai/objectstack/dispatches, once per stroke): (1) pr_create → POST /repos/objectstack-ai/hotcrm/pulls, draft #2100 with assignees [sunhaolin]; the relay read back 7768 bytes sent and 7768 stored, identical; (2) this os-dev-report → POST /repos//issues/2096/comments via post-stamped. Not counted as REST writes: git push (twice: the empty probe branch, then 470b540). Zero label writes, as the dispatch ordered.",
    "gates": {
    "sha": "470b5406",
    "validate": {
    "exit": 0,
    "verdict": "✓ Validation passed (2845ms)"
    },
    "typecheck": {
    "exit": 0,
    "verdict": "tsc --noEmit (no diagnostics)"
    },
    "lint": {
    "exit": 0,
    "verdict": "18 suggestion(s)"
    },
    "lint:i18n-gate": {
    "exit": 0,
    "verdict": "✓ i18n lint gate: 0 i18n/missing-* issues (18 total lint issue(s) reported, unaffected by this gate)"
    },
    "hygiene": {
    "exit": 0,
    "verdict": "✓ source hygiene clean"
    },
    "hygiene:tokens": {
    "exit": 0,
    "verdict": "✓ source token ratchet clean"
    },
    "build": {
    "exit": 0,
    "verdict": "✓ Build complete (3478ms)"
    },
    "test": {
    "exit": 0,
    "verdict": "Test Files 179 passed (179); Tests 3659 passed | 1 skipped (3660)"
    },
    "e2e": "NOT MEASURED: playwright e2e, reason: CI-owned per dispatch"
    },
    "line_budget": "n/a — every changed source file is under src/sales/translations, which is outside the source token ratchet by ruling (hygiene:tokens prints it as "outside the ratchet by ruling"). Diff 2f3d898..470b540: 4 files, +32 -15.",
    "files_changed": [
    "src/sales/translations/zh-CN/app.ts",
    "src/sales/translations/es-ES/app.ts",
    "src/sales/translations/ja-JP/app.ts",
    ".changeset/2096-screen-titles.md"
    ],
    "deviations": [
    "File surface: besides the three screen_1.title keys per pack, the pack comment above flows: is changed in zh-CN/es-ES/ja-JP app.ts (+6 -2 per file, same files). It said a screen with no authored title "shows its flow's label in every locale, so each screen_1.title repeats the flow label". That fallback is false on 18.0.0-next.0 (executor dist/index.js L11247; cli i18n-extract.js L1371), and it is the rationale the defect followed. The claim says "stop on breach", but the os-dev standing rule says a published defect that this change makes false must be fixed. I followed the standing rule and name the conflict here; the PR body names the change and its evidence.",
    "Attribution: commit 470b540 carries the model-free trailer pair (Co-authored-by: Claude, plus Claude-Session) and the PR body ends with the session-URL footer, both per the os-dev definition. The harness reminder asked for a model-named Co-Authored-By trailer and a "Generated with" footer; the definition takes precedence.",
    "Not merged with origin/main: e094ec7 (#2098) landed after the 2f3d898 base. It touches only lead.view.ts, opportunity.view.ts, leads docs and its own changeset, none of which this PR touches. Gates were measured on 2f3d898 plus this commit.",
    "The heavy-gate lock call went past the 600s foreground cap and the harness moved it to the background. I waited for it in the foreground (tail --pid on the lock holder) and read each exit from its log. No result was taken from a notification."
    ],
    "open_questions": [],
    "out_of_scope_findings": [
    "class: a · reach: console screen-flow dialog, measured at 470b540 on 18.0.0-next.0: Schedule Follow-up on a lead reads eyebrow/title "Schedule Follow-up / Schedule Follow-up" (en-US) and "安排跟进 / 安排跟进" (zh-CN). By source, Escalate Case, Close Case and Claim Case have the same shape, in every locale, English included · evidence: their screen_1 node label equals the flow label (src/sales/flows/schedule-followup.flow.ts L24 and L43; src/service/flows/case-actions.flow.ts L32/L47 escalate_case, L127/L173 close_case, L281 claim_case). objectui packages/app-shell/src/views/FlowRunner.tsx L619 at 2312bd9 renders the eyebrow (shownFlowLabel, objectui#11092) whether or not it equals the title. There are two candidate producers: the platform default (eyebrow not suppressed when it equals the title; AGENTS.md §4 says a bad platform default is fixed at the default) or the app's node labels. The seat decides which, so this was not fixed here · dedupe words: flow runner eyebrow repeats title, screen flow dialog duplicate heading, shownFlowLabel, single-screen flow title equals flow label"
    ]
    }

  4. objectstack-fleet commented on Oct 14, 2026

    @objectstack-fleet
    ContributorAuthor

    Review of PR #2100 (head 470b5406) against the os-dev report 6164580017 (R85, seat repo:hotcrm, session_01P8mZuzuyZAHSrgQKmv6ASv): ACCEPT.

    • Form: draft, base main; the body opens Fixes #2096, and Clause-②: no starts its own line; there is no other closing keyword. Not a governed path; 4 files, +32 −15.
    • Scope, read line by line: the nine flows.FLOW.screens.screen_1.title values in src/sales/translations/{zh-CN,es-ES,ja-JP}/app.ts (campaign_enrollment, lead_conversion, quote_generation), plus the hotcrm: patch changeset. Each new title translates the screen's en node label (Conversion Details / Quote Details / Enrollment Criteria), not the flow label. es-ES and ja-JP had the same defect, which the filer had not checked; the dev measured it and fixed it in the same keys.
    • Outside the claim, accepted: the pack comment above flows: in the same three files. It stated the false fallback ("shows its flow's label in every locale, so each screen_1.title repeats the flow label") that the defect followed. The dev's reading on 18.0.0-next.0 is the executor's config.title ?? node.label. A sentence this change makes false is owed in the same PR.
    • Readings: the local pnpm verify chain is green on 470b5406, the PR head. The console probe reads eyebrow and title before and after in zh-CN, es-ES, ja-JP and en-US; en-US is unchanged. Translations sit outside the token ratchet. CI: every check green except Build and Test (22.x), still running at this review; landing waits for it.
    • Not merged with main: since the base, main took PR fix(views): zh-CN Leads and Opportunities column headers follow the field labels #2098 and PR fix(lead): stop requiring an owner pick on the New Lead form #2099, which touch none of these four files. The seat will merge main into the branch if the PR shows a conflict.
    • Out of scope, not filed yet (this fire's filing quota is spent): single-screen flows whose screen node label equals the flow label show the same text twice: Schedule Follow-up, and by source Escalate / Close / Claim Case, in every locale. Two candidate producers: objectui's FlowRunner eyebrow, which is not suppressed when it equals the title, or the app's node labels. The seat carries it to its next fire.

    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

Labels

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions