Skip to content

fix(i18n): translate crm_lead.disqualification_reason, and guard select-field labels (#631) - #647

Merged
os-zhuang merged 1 commit into
mainfrom
claude/issue-631-disqualification-reason-i18n
Aug 2, 2026
Merged

fix(i18n): translate crm_lead.disqualification_reason, and guard select-field labels (#631)#647
os-zhuang merged 1 commit into
mainfrom
claude/issue-631-disqualification-reason-i18n

Conversation

@os-zhuang

Copy link
Copy Markdown
Contributor

Fixes #631

Description

crm_lead.disqualification_reason 在四个语言包里都没有条目。这是一个 required 字段,出现在 8 张 lead 表单上,所以它的七个选项在界面上直接渲染成数据库里存的原始值 —— not_a_fitno_budgetwrong_personaunreachableduplicatecompetitorother —— 夹在一张其余部分完全翻译好的表单中间。

en 看起来正常纯属巧合:缺条目时解析器会回退到代码里的英文 label,而在 en 这个回退和"翻译正确"根本无法区分。评审最可能打开的那个语言,恰好是唯一看不出这个 bug 的语言 —— 这正是它需要测试而不是靠人眼的原因。

补翻译本身是机械活,这个 PR 的重点在第二部分:把产生这类遗漏的机制堵上。

Type of Change

  • Bug fix (non-breaking change which fixes an issue)

Related Issues

Fixes #631
Related to #645(本 PR 扫出的既有缺口清单)、#494(action 标签的同型守卫)、#629(相邻的 duplicate 字段翻译)

Changes Made

1. 补齐四个语言包src/translations/{en,zh-CN,ja-JP,es-ES}.ts

disqualification_reason 的 label + help + 全部七个选项标签。用词跟着同一个包里的邻居走,而不是逐字直译:

locale status: unqualified 既有译法 本 PR 的字段名
zh-CN 未通过 未通过原因(不是"取消资格原因")
ja-JP 不適格 不適格理由
es-ES No Calificado Motivo de No Calificación

这两个字段在表单上就是上下相邻的,用词必须成对,否则读起来像两套说法拼在一起。

2. 覆盖守卫test/metadata-references.test.ts

新增 select fields are translated in every locale,把 #494 给 action 标签做的逐语种断言套到 全部对象的全部 select 字段 上:每个 select 字段在每个语言包里都必须有 label,以及每一个选项值的标签。

守卫范围是全量的 —— 15 个对象、53 个 select 字段,不只针对 crm_lead

它和文件里已有的两个相邻守卫是相反方向的检查:picklist values never reach the UI unresolved 检查"已存在的条目指向真实的东西",本守卫检查"条目存在与否"。两个都需要 —— 一个语言包可以形式完全正确同时内容是空的。

3. 只减不增的既有豁免清单

扫描发现的缺口远不止这一个字段:34 个字段、111 个 (语种, 字段) 组合、约 380 条选项标签。按 PM 的要求没有在本 PR 里一次性补完 —— 那会把这个 PR 真正要修的那一个字段彻底淹没。

这些进入 PENDING_SELECT_LABELS,形状照抄 test/runtime-coverage.test.tsPENDING_FLOWS,并在 #645 里逐条列出。清单只能减不能增,而且两个方向都防腐烂:

  • 已经补上翻译的条目 → 判为 stale,测试失败,必须删除;
  • 指向不存在的字段或语种的条目 → 判为 ghost,测试失败。

所以从此以后新增或扩展的 select 字段没有东西可以躲,会在引入它的那个 PR 上直接失败。

Testing

  • Unit tests pass
  • Linting passes
  • Build succeeds
  • New tests added
pnpm typecheck   → tsc --noEmit,无输出(通过)
pnpm validate    → ✓ Validation passed (1142ms) / 15 Objects 314 Fields
pnpm lint        → 1 warning, 13 suggestions(均为既有项,与本 PR 无关)
pnpm hygiene     → ✓ source hygiene clean
pnpm build       → ✓ Build complete (1006ms)
npx vitest run   → Test Files 43 passed (43) / Tests 1009 passed | 1 skipped (1010)

守卫做了变异测试 —— 一个不会失败的守卫等于没有守卫。四种失效模式逐个验证过:

注入的缺陷 断言输出
删掉 ja-JP 两个选项标签 option values with no translated label:
ja-JP: crm_lead.disqualification_reason — unreachable, duplicate
删掉 es-ES 的字段 label select fields with no translated label:
es-ES: crm_lead.fields.disqualification_reason.label
把已翻译完整的 crm_lead.status 塞进清单 these are now fully translated — remove them from PENDING_SELECT_LABELS:
zh-CN: crm_lead.status
塞进不存在的字段 / 语种 PENDING_SELECT_LABELS has entries that check nothing:
crm_lead.no_such_field is not a select field on any object
crm_account.type names unknown locale "fr-FR"

另有一条 guard-the-guard 断言(sees a non-trivial set of select fields and locales),防止 stack.objects 或语言包 flatten 失败时整组断言空转通过 —— 这个文件里的 navigation 守卫就是这么白白绿了一辈子的。

Checklist

  • I have added a changeset.changeset/lead-disqualification-reason-i18n.md
  • My code follows the style guidelines of this project
  • I have performed a self-review of my own code
  • I have commented my code, particularly in hard-to-understand areas
  • My changes generate no new warnings
  • I have added tests that prove my fix is effective
  • New and existing unit tests pass locally with my changes

Additional Notes

没有碰的东西: content/docs/releases/(发布说明集中生成)、issue 的 assignee、以及 #645 里列的 34 个既有缺口 —— 后者是刻意留给独立 PR 的,按对象拆分是干净的切分单位,每个 PR 只删自己那几行清单,互不冲突。

范围说明: 守卫只覆盖 select 字段(有 options 的字段)。非 select 字段的 label 覆盖率是另一个类,本 PR 不扩张到那里。


Generated by Claude Code

…ct-field labels (#631)

`crm_lead.disqualification_reason` had no entry in any of the four locale
bundles, so a `required` field sitting on eight lead forms rendered its seven
raw stored values (`not_a_fit`, `no_budget`, `wrong_persona`, `unreachable`,
`duplicate`, `competitor`, `other`) inside an otherwise fully translated form.
`en` looked correct only by accident: a missing entry falls back to the English
`label` in code, so the one locale a reviewer is most likely to open is the one
where the defect cannot be seen.

Wording follows each bundle's own neighbours rather than a literal rendering —
zh-CN translates `status: unqualified` as 未通过, so the reason field is
未通过原因; ja-JP pairs 不適格 with 不適格理由; es-ES pairs No Calificado with
Motivo de No Calificación.

Extends the action-label coverage guard (#494) to select fields: every select
field on every object needs a `label` and a label for every option value, in
every locale pack. The 34 fields already incomplete when this landed sit in a
shrink-only `PENDING_SELECT_LABELS` ledger (the `PENDING_FLOWS` shape from
test/runtime-coverage.test.ts) and are enumerated in #645 — a field added or
extended from here on has nothing to hide behind. The ledger cannot rot: an
entry since translated fails as stale, an entry naming a field or locale that
does not exist fails as a ghost.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019SS7C5SXpniKeCApxgARyf
@vercel

vercel Bot commented Aug 2, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

1 Skipped Deployment
Project Deployment Actions Updated (UTC)
hotcrm Ignored Ignored Aug 2, 2026 6:47pm

Request Review

@github-actions github-actions Bot added ci/cd CI plumbing and the verification pipeline metadata Declarative metadata — schema, security posture, UI surfaces labels Aug 2, 2026
@os-zhuang
os-zhuang marked this pull request as ready for review August 2, 2026 18:50
@os-zhuang
os-zhuang added this pull request to the merge queue Aug 2, 2026
Merged via the queue into main with commit c9d5009 Aug 2, 2026
10 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ci/cd CI plumbing and the verification pipeline metadata Declarative metadata — schema, security posture, UI surfaces

Projects

None yet

Development

Successfully merging this pull request may close these issues.

crm_lead.disqualification_reason has no i18n entry in any of the four locale bundles

2 participants