Skip to content

test(i18n): extend the Chinese term guard to status names and field labels - #1529

Merged
os-sales merged 1 commit into
mainfrom
claude/issue-802-term-guard-statuses-and-labels
Sep 3, 2026
Merged

test(i18n): extend the Chinese term guard to status names and field labels#1529
os-sales merged 1 commit into
mainfrom
claude/issue-802-term-guard-statuses-and-labels

Conversation

@os-sales

@os-sales os-sales commented Sep 3, 2026

Copy link
Copy Markdown
Collaborator

Fixes #802

Extends the Chinese term guard from object names to status.options.* and field labels, answers the card's open question 2, and corrects the one live defect the extension found.

#837 built the mechanism (test/docs-object-term-consistency.test.ts) and scoped it to object names. #802 was filed on four defects one level down — presented written 已呈现/已呈現 (#765 §3), expired written 已到期 on two separate pages (#793 and #801 甲), expiration_date written 过期日期 (#801 乙) — every one of them caught by a human reading a page, none by a machine.

Question 2, answered: word grain, not markup position

The card would not be dispatched until this was settled, because a status term collides with prose in a way an object name does not: 到期日期 is a field label and must follow the pack, while 每日到期扫描, 自动到期, 报价单到期, 即将到期 and 到期日 are mechanism names that must not be touched. The card proposed narrowing the scan to status-table cells and **bold** references. That narrowing was measured and rejected as the weaker rule.

It is not needed for quiet. The collision is always on the ROOT, never on the whole retired spelling. Measured across the 134 Chinese pages on 9f59f6a:

scanned for lines carrying it
到期 71
呈现 / 呈現 14 each
已到期 0
过期日期 / 過期日期 0
已呈现 / 已呈現 0

A status name and a field label are complete words, so a ledger of complete words discriminates on its own. ALLOWED stays empty — re-measured after the extension, not inherited.

It is not safe. Reconstructed from the three fix commits (483dbb4d, 5596c6cc, 36765f21), six of the nineteen historical defect sites carried no markup at all:

  • 不要更改已呈现报价上的定价——它会让客户困惑。 (both scripts)
  • 超過有效期的報價每晚會被自動標記為已到期。
  • 系统会将任何过期日期已过的报价标记为**已过期** — the defect is in the unmarked half of the line
  • ✅ 检查有效期(过期日期)是否与你的业务周期相匹配。
  • the bare field list in the cell | **条款与有效期** | 报价日期、过期日期、付款条款、运输条款 |

Narrowing by position would have dropped about a third of the defects the guard exists for, and #801 甲 is on record that this class is consumed across pages rather than within one.

The boundary is pinned, not promised. A SPARED ledger names the mechanism prose the presented and expired sweeps had to leave alone, requires each phrase to still be in the corpus, and requires no retired spelling to be a substring of any of them. Retire a bare 到期 or 呈现 and the failure lands there, on legitimate prose, instead of landing in CI across the whole corpus — the noisy-gate-gets-silenced outcome #736 recorded and this card was held for.

The live defect the extension found

⚠️ This PR edits src/translations/zh-CN.ts, one word, and that is a declared deviation from the dispatched file surface (which named the pack read-only). Flagging it rather than burying it, because the PR does not stand without it:

- help: '报价进入「已呈现」或「已接受」后必填 —— 起草的合同从这里取主要联系人。'
+ help: '报价进入「已提交」或「已接受」后必填 —— 起草的合同从这里取主要联系人。'

crm_quote.crm_contact's help text told Chinese users a quote had to reach 「已呈现」 — a status the console has never shown. The pack's own status.options.presented says 已提交, thirteen lines above the sentence contradicting it. No source-of-truth value is changed here: the option value already said 已提交, and the prose is moved onto it, not the reverse.

It is the fifth instance of this card's defect class, and it is the strongest argument on the card. #794 swept the repository clean of 已呈现 and said so. The sentence above was introduced after that sweep, by a feature PR (#1017, landed as #1068), and has been on screen ever since. A careful grep is right on the day it runs; this is what a standing gate is for.

Cross-locale, zh-CN was the only pack whose help text disagreed with its own option value — en says Presented/Presented, ja-JP says 提示済み/提示済み. (es-ES says Presentado against options Presentada/Aceptada; filed separately, ⛔ not touched here.)

Reverting that one line makes this PR red. It is not a drive-by nicety that can be dropped; if the maintainer wants the pack change to travel on its own card, the guard's presented pin has to travel with it.

Acceptance evidence: each historical defect injected, guard observed red

⛔ Not optional per the card — it exists because this class was caught four times by human eyes and zero times by machine. Each injection asserts it landed on disk (blob-hash change plus anchored counts on the removed and injected text) before any red or green is trusted, and each restore is proved by hash equality plus an empty git diff HEAD.

historical defect site shape guard verdict rule that fired
presented → 已呈现 (#765 §3) bare prose, no markup 🔴 1 failed / 32 passed from every zh-Hans page
expired → 已到期 (#793) bold cell in the status table 🔴 1 failed / 32 passed from every zh-Hant page
expiration_date → 过期日期 (#801 乙) bare field list in a table cell 🔴 1 failed / 32 passed from every zh-Hans page
expired → 已到期 on a second page (#801 甲) bare prose, cross-page 🔴 1 failed / 32 passed from every zh-Hant page
clean tree 🟢 33 passed (33), git diff HEAD empty

The fourth row is the #801 甲 regression specifically: the same word on sales/index.zh-Hant.mdx, the page a per-page human sweep missed.

The pack defect was observed the same way, before it was corrected: on the first run of the extended guard the tree was red on exactly one assertion, src/translations/zh-CN.ts:543: 已呈现, with 32 of 33 passing.

⚠️ One reading was thrown away and re-taken. The first pass verified its own mutation with grep -c on a pattern holding ** and |, which BRE swallowed: the counts read 0 → 0 while the blob hash moved, so the script refused the reading rather than reporting it. Re-run with grep -cF, all four landed and all four were re-measured. The trap on EXIT INT TERM — not the inline path — is what restored the file that aborted mid-run.

Smaller mechanics

  • A pin names the dotted path it derives from (fields.status.options.presented) and the path is resolved, not trusted, so a typo cannot quietly produce a pin that guards nothing.
  • hant: null declares a term identical in both scripts (已提交 and 到期日期 share every character) and the declaration is verified by requiring the Simplified spelling to appear on the Traditional pages. It is also the one value the mistake hant !== hans exists to catch cannot produce — filling the column in wrongly yields a string, not null.
  • crm_quote's ledger list is [] because it was measured: no test/** ledger writes 报价单 at all. An object must still have an entry, so adding a TERMS row forces that look.
  • Three new apparatus rules join [观察] crm_case 在中文文档里有三种叫法:语言包「服务案例」、25 个页面「工单」、14 个页面「案例」(两页同页混用) #837's five, holding the same anti-vacuity line: every pinned path resolves, every row retires at least one spelling somewhere, and the corpus still carries the roots the criterion has to discriminate against.

Not in this PR

Verification

pnpm verify green on this tree: 158 test files, 3330 passed / 1 skipped, ✓ source hygiene clean, ✓ source token ratchet clean, ✓ i18n lint gate: 0 i18n/missing-* issues. Re-run on head d46ab561 (tree 5a9081e5, working tree clean).

🤖 Generated with Claude Code

https://claude.ai/code/session_019hUuCQStzXGMFSX4dzww5t


Generated by Claude Code

…abels

#837 landed the mechanism scoped to object names. This extends `TERMS` to
`status.options.*` and field `label`s — the four defects #802 was filed on —
and answers that card's open question 2: mechanism prose is spared by ledger
granularity (the complete term), not by syntactic position.

Measured, not assumed: 71 lines carry 到期 and 14 carry 呈现 across the 134
Chinese pages; zero carry 已到期, 过期日期 or 已呈现. The narrowing the card
proposed (status-table cells plus `**bold**` refs) would have missed six of the
nineteen historical defect sites, which carried no markup at all.

The extension found one live defect: `crm_quote.crm_contact.help` in the zh-CN
pack quoted 「已呈现」, a status the console does not show — introduced by
#1017 (landed as #1068) after #794 had swept the repo clean of that spelling.

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

vercel Bot commented Sep 3, 2026

Copy link
Copy Markdown

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

1 Skipped Deployment
Project Deployment Actions Updated
hotcrm Ignored Ignored Sep 3, 2026 8:37am UTC

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 Sep 3, 2026
@os-sales
os-sales marked this pull request as ready for review September 3, 2026 08:42
@os-sales
os-sales added this pull request to the merge queue Sep 3, 2026
Merged via the queue into main with commit d9fad90 Sep 3, 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.

[观察] 文档里的状态名/字段标签与语言包是否一致,无人检查——一周内同一缺陷类出现三次,全靠人眼撞见

2 participants