Skip to content

docs(sales): name the seven opportunity stages the way the locale pack ships them (#829) - #842

Merged
yinlianghui merged 1 commit into
mainfrom
claude/issue-829-stage-names-follow-package
Aug 5, 2026
Merged

yinlianghui merged 1 commit into
mainfrom
claude/issue-829-stage-names-follow-package

Conversation

@yinlianghui

@yinlianghui yinlianghui commented Aug 5, 2026 •

Copy link
Copy Markdown
Collaborator

Fixes #829

按 PM 已 record 的裁定执行 方向 A:docs 跟包。唯一事实来源是 src/translations/zh-CN.ts 的 crm_opportunity.stage,语言包一字未动,src/**、en 页、content/docs/releases/ 均未触碰。也没有加守卫——那条闸挂在 #802 名下,其正文写明在「zh-Hant 无语言包」与「动词/机制名豁免判据」两个问题定下来之前不宜动手。

甲、七个阶段名

value 语言包 改前 改后
prospecting 寻找客户 开发期 寻找客户
qualification 资格审查 资格审核 资格审查
needs_analysis 需求分析 需求分析 未动
proposal 提案 提案 未动
negotiation 谈判 谈判 未动
closed_won 成交 赢单 成交
closed_lost 失败 输单 失败

锚点两页的阶段表(opportunities / pipeline-management × zh-Hans + zh-Hant)先对齐,随后逐句扫全部散文波及页:拖拽推进示例、关单原因表、$100K 大单提醒、审批终态、报价被接受时的推进、线索转化时创建商机的那一步、词汇表的 closed won/lost 条目。

判据:包里有没有这个词

这一单的散文面比 #794/#825 大一个量级,所以先立判据再动手:

  • 包里根本不存在的词,出现在哪里都是漂移。 开发期、资格审核、输单 在 zh-CN.ts 中零命中,已从 zh 文档中清除。唯一放过的是 guides/integrations.zh-Han*.mdx:132 的「开发期」——那里指开发环境而非 prospecting 阶段,issue 正文已点名要放过。
  • 包里确实发的词,只在「它被当作阶段名用」时才算漂移。 赢单/丢单 是语言包自己的成败词汇(赢单原因、丢单原因、赢/丢单详情、赢单数、丢单数、赢单概率),所以它们在指代原因、指标、成败结果时一律保留:「未赢单、未丢单的交易」「赢单率」「赢单原因」「赢单/丢单复盘」照旧;只有读者会拿它去界面上找阶段值的地方才改,例如「阶段会被自动设为赢单」→ 成交。

由此派生出一处值得单独说明的取舍:文档把 赢单 与非包词 输单 配对来指代两个原因字段(而非两个阶段)时——状态机的关单必填、cube 维度、Win/Loss 报表——包里的对应词是 丢单 而不是 失败,故这几处写作「赢单/丢单原因」。

⚠️ 资格审查 vs 资格评估:未互串

crm_opportunity.stage.qualification 是「资格审查」,crm_lead._sections.qualification 是「资格评估」,两者在包里是有意分开的(#793 追评、#825 定调)。本 PR 只把商机侧阶段表的「资格审核」改成「资格审查」;leads 三处与 sales/index 一处的「通过资格审核 / 应用 BANT 资格审核」是人做的动作、不是任一标签,#825 已明确保留,本次同样未动。leads 页的「资格评估」区块名也原样保留。

乙、convert 动词面

convert_lead 的 label 是「转化线索」,而 sales-copilot.zh-Hans.mdx:63 白纸黑字把这个按钮叫「转换线索」,已改为包里的写法。另按「行号按最新 main 重核」的要求复核了 issue 列出的其余四处,并顺带修正了 issue 正文的一处事实偏差:

issue 说「zh-Hant 版同段落没有这个写法」——实测有。sales-copilot.zh-Hant.mdx:63 写作「轉換潛在客戶」,同样在点名这个动作。

这四处的共同形状是简繁不同步:quick-tour.zh-Hans:54,64、introduction.zh-Hans:23、testing-and-ci.zh-Hans:266 早已是「转化」,只有繁体孪生页还停在「轉換」;accounts 则相反,简繁两侧都还是「转换」。本次把繁体侧补齐(quick-tour 同页 :60 属同一条线索转化链,一并处理),并按语言对偶补上 accounts.zh-Hant:62——#803 只修 quotes 页、留下 index 页给 #825 的教训就在这里。

文件面(25 个 zh 页 + changeset,62 行)

  • 甲组锚点:sales/opportunities.zh-Han{s,t}.mdx、sales/pipeline-management.zh-Han{s,t}.mdx
  • 甲组散文:sales/leads.zh-Han{s,t}.mdx、sales/index.zh-Han{s,t}.mdx、sales/quotes.zh-Han{s,t}.mdx、administration/state-machines.zh-Han{s,t}.mdx、reference/glossary.zh-Han{s,t}.mdx、analytics/cubes.zh-Han{s,t}.mdx、analytics/reports.zh-Han{s,t}.mdx
  • 乙组:ai-copilot/sales-copilot.zh-Han{s,t}.mdx、sales/accounts.zh-Han{s,t}.mdx、getting-started/quick-tour.zh-Hant.mdx、getting-started/introduction.zh-Hant.mdx、customization/testing-and-ci.zh-Hant.mdx
  • changeset:.changeset/zh-docs-opportunity-stage-names.md

一处同句连带,明确披露:pipeline-management.zh-Han{s,t}.mdx:87 原文是「归档输单交易并附上失单原因」。失单原因 严格说属于字段标签漂移(包里是「丢单原因」)而非阶段名族,但它与被改写的 输单 同在一个分句,且 失单 同样是包里零命中的词——留着会让这一行在改写后当场自相矛盾,故一并改为「归档失败的交易并附上丢单原因」。除此之外未越界改任何字段标签。

验证

一次性对照脚本(照 #825 先例,不入库),阶段名从 zh-CN.ts 现读、不硬编码,双向跑:

改后 worktree :ALL CHECKS PASSED(24/24)
origin/main a501812e:16 CHECK(S) FAILED
  FAIL stage table rows follow pack: opportunities.zh-Hans   -- absent as a row: 寻找客户 / 资格审查 / 成交 / 失败
  FAIL stage table rows follow pack: opportunities.zh-Hant   -- absent as a row: 尋找客戶 / 資格審查 / 成交 / 失敗
  FAIL stage table rows follow pack: pipeline-management.zh-Hans / .zh-Hant (同上)
  FAIL word absent from zh docs: 开发期 / 開發期 / 输单 / 輸單
  FAIL names the convert action as the pack labels it: sales-copilot.zh-Hans
  FAIL lead-convert verb face follows the pack: 其余 6 页

基线恰好点出每页 4 个(而非 7 个)阶段名缺失,与 issue 正文的四行 ❌ 完全吻合,needs_analysis/提案/谈判 三个未报——这是对 issue 前提的独立复核。

反向验证的方向说明:8 条「资格审查/资格评估 不互串」断言在改前改后都是 PASS,并非我漏跑。改前文档用的是第三个词「资格审核」,它既不属于商机侧也不属于线索侧,因此这组断言在此基线上本就不具判别力——它们是防我自己改反方向的护栏,不是基线失败的预测项。照实报,不硬凑成翻转。

脚本第一版用的是「整页包含该词」的判据,基线只报出 3 个缺失——因为 成交 早已借 成交日期 出现在页面上。已收紧为「该词必须占据表格行首单元格」后,基线才如实报出 4 个。含义相反的弱判据没留在 PR 里。

全量四件套(flock /tmp/os-heavy-verify.lock,NODE_OPTIONS=--max-old-space-size=4096,vitest --maxWorkers=2):

pnpm validate  ✓ 13 warning(s), 14 suggestion(s)(均为既有,与本 PR 无关)
pnpm typecheck ✓
pnpm lint      ✓
pnpm hygiene   ✓ source hygiene clean(控制字节扫描面含 content/ 与 .changeset/)
pnpm build     ✓ Build complete — 17 Objects / 24 Flows / dist 1921.3 KB
pnpm test      ✓ Test Files 66 passed (66) · Tests 1587 passed | 1 skipped (1588)

测试输出中的 ✗ source hygiene failed: ... 数行来自 test/source-hygiene-scan-surface.test.ts ——它故意用埋雷夹具跑 hygiene 脚本并断言其大声失败,是该元测试的预期 stderr,不是真失败。

控制字符自扫(越过 gate 的盲区,26 个改动文件 + 脚本本身):grep -naP 扫 C0 控制字节(不含 tab/LF/CR)零命中。

与 origin/main 最新的 aacc75a(#841 改了 sales/accounts.zh-Han{s,t}.mdx)实测可干净合并:其改动落在同文件 :66 一带,本 PR 落在 :62。

越界发现(已去重后另立 issue,本 PR 一处不修)

…k ships them (#829)

`src/translations/zh-CN.ts` is what a Chinese reader sees on screen. Four of
the seven `crm_opportunity.stage` option labels had drifted, and unlike the
earlier term fixes this was not one page getting a word wrong — every Chinese
page consistently used a second vocabulary the product never displays:
prospecting 寻找客户 (docs: 开发期), qualification 资格审查 (资格审核),
closed_won 成交 (赢单), closed_lost 失败 (输单). needs_analysis / proposal /
negotiation already matched and are untouched.

Both stage tables (Opportunities and Pipeline Management, zh-Hans and zh-Hant)
now carry the shipped labels, and so does every sentence that names a stage:
the drag-to-advance example, the close-reason table, the $100K alert, the
approval outcome, the quote-accepted advance, the lead-conversion step that
creates an opportunity, and the glossary's closed-won/lost entry.

The rule applied: a word the pack ships nowhere is drift wherever it appears;
a word the pack does ship is drift only where it names the stage. 开发期,
资格审核 and 输单 appear nowhere in the pack and are gone from the Chinese docs
entirely — except 开发期 on the integrations pages, where it means the
development environment, not the prospecting stage. 赢单 and 丢单 are the
pack's own outcome vocabulary (赢单原因, 丢单原因, 赢/丢单详情, 赢单数, 丢单数,
赢单概率), so they stay wherever they name a reason, a metric or an outcome.
Where the docs paired 赢单 with the non-pack 输单 to name the two reason fields
rather than the stages — the state-machine close requirement, the cube
dimension, the Win/Loss report — the pack's counterpart is 丢单, not 失败.

Two same-named terms stay separate, as the pack intends:
crm_opportunity.stage.qualification is 资格审查 and
crm_lead._sections.qualification is 资格评估. The Leads pages' 通过资格审核 is a
thing a person does, not either label, and is untouched.

Convert verb face: convert_lead ships the label 转化线索, but the Sales Copilot
page named that very button 转换线索. That page now uses the shipped label, and
the traditional-Chinese residuals left when the simplified twins were corrected
— Accounts, Quick Tour, Introduction, Testing and CI, and the Traditional Sales
Copilot page, which named the action 轉換潛在客戶 — now read 转化 / 轉化 too.

Documentation only: the locale pack is the contract, so nothing under src/
changed.

Fixes #829

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

vercel Bot commented Aug 5, 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 5, 2026 11:23pm

Request Review

@yinlianghui
yinlianghui marked this pull request as ready for review August 5, 2026 23:29
@yinlianghui
yinlianghui added this pull request to the merge queue Aug 5, 2026
Merged via the queue into main with commit 95ee1a4 Aug 5, 2026
9 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

zh 文档里 crm_opportunity 的 7 个阶段名有 4 个与语言包不符(开发期/资格审核/赢单/输单),且这一组该动哪边未定

2 participants