Repository navigation
fix(i18n): 补齐 en 的列表视图标签,并为「视图标签跨语言一致性」加守卫 (#783, #767) - #787
Merged
Merged
Conversation
…ity across locales (#783, #767) Nine saved list views had no `_views` label entry in the `en` bundle while zh-CN, ja-JP and es-ES all carried the full set: `crm_task.todays_tasks` / `overdue_tasks` (#783), `crm_lead.hot_leads` and `crm_account.renewals_due` / `at_risk_accounts` (#767), plus `crm_case.my_open_cases` / `sla_at_risk` and `crm_opportunity.stale_opportunities` / `closing_this_quarter`, which the guard's derivation turned up beside them. Each entry added here is the view's own metadata `label` verbatim — no name a user reads changes, and no locale invents a reading of its own. The four `crm_case` / `crm_opportunity` rows are closed in the same PR rather than filed: they are the identical defect in the identical file, and the guard this issue asks for cannot ship green without a disposition for them. The only alternative was an exemption ledger, which the select-field guard's own comment in this file calls a regression. The `closing_this_quarter` comment claiming "no label here on purpose" is removed with it. It was written by #746 after #679 had already ruled the other way for every other locale surface, and its premise — that `en` needs no entry because the resolver falls back to the metadata label — is exactly the invisibility that let these nine sit unnoticed. ## The guard Nothing mechanical could have found any of this. `pnpm lint` hard-codes `--skip-i18n`, and dropping the flag does not report them either: the run emits one line about 2298 hidden platform built-ins, because app-authored `_views` completeness is not in the set the linter checks. So this is not the #494 family (real warnings suppressed by a flag) — it is a surface nobody checked, and both gaps were found by a human comparing four bundles column by column. Three assertions in `test/metadata-references.test.ts`, derived from the compiled stack rather than a hand-kept list, so a view added tomorrow is held to the bar on the PR that adds it: - every canonical view has a `label` in every locale (70 views x 4 locales); - no locale carries a `_views` entry for a view the stack no longer ships — an orphan reads as coverage while translating nothing; - the `en` label is byte-identical to the metadata label it stands in for. The third is what parity alone cannot do, and it is #767's actual concern: with the key present in all four bundles, editing the metadata label used to let `en` track the rename for free while the other three kept translating the old name, with nothing red. It proves the ENGLISH pair agrees and nothing more — it makes a rename loud, it cannot make the other three correct. All 61 `en` view labels that existed before this change were already byte-identical, because #679 extracted them programmatically rather than transcribing them. An anti-vacuum assertion guards the derivation itself: >= 50 canonical views over >= 10 objects, every one resolving an object and a name, and at least one `_views` table parsed out of every locale pack. ## Verification Reverse-verified in four directions, each predicted before it was run: - delete `en.crm_task.overdue_tasks` -> parity RED naming `en: crm_task._views.overdue_tasks.label`; byte-identity stays green (it has nothing to compare), which is the correct split of duties; - rewrite that label to a plausible `⏰ Overdue Tasks` -> byte-identity RED naming both strings, parity GREEN — the case parity cannot see; - add a `_views` entry for a view that does not exist -> orphan check RED; - run the guard against `origin/main`'s `en.ts` -> exactly the 9 rows above, all in `en`, none in ja-JP. That last run also disproves half of #783's premise: it claims ja-JP is missing `todays_tasks` / `overdue_tasks`, but ja-JP has carried both since #679, at `ja-JP.ts:943-944` — already true at the `7667c9b4` baseline the issue cites. Only the `en` half of #783 was real, so no ja-JP edit was needed. Full suite green: validate, typecheck, lint (13 warnings, unchanged), hygiene, build, and 1517 tests across 63 files. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VHrPAGEgFDoHjphqYG4BMa
|
The latest updates on your projects. Learn more about Vercel for GitHub. |
It said "both assertions below" while three now sit under it (parity, orphan, and the en byte-identity pin). A guard's comment that undercounts what it covers is how the next reader concludes one of them is unprotected. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VHrPAGEgFDoHjphqYG4BMa
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #783
Fixes #767
先说复核结论:#783 的 premise 只成立一半
origin/main(fb48ab5) 的复核结果en.ts的crm_task._views缺todays_tasks/overdue_tasksja-JP.ts同样缺这两项en.ts缺renewals_due/at_risk_accounts/hot_leadsja-JP.ts:943-944早已有这两条(📅 私の優先タスク/⏰ オープンタスク · 期限超過が長い順),是 #679 补齐四语言包时一起落地的。#783 引用的基线7667c9b4上就已经是这样——git show 7667c9b4:src/translations/ja-JP.ts的_views块从 937 行开到 946 行,八项齐全。issue 正文写的ja-JP.ts:937-942只读到my_open_tasks那一行就收尾了,漏看了后两行。因此本 PR 不动ja-JP.ts,只有 #783 的 en 那一半是真的。#767 的三项全部仍在,且 #774(对齐 hot 阈值到 rating ≥ 4)没有碰任何语言包,所以
hot_leads的四语言现状与 #767 记录时一致。canonical label 是🔥 Hot Leads,不含任何阈值措辞,照抄即可——没有 4.5 星的旧口径可以复活。缺口的实际范围:9 条,不是 5 条
守卫的派生(不是人工清单)在
origin/main上跑出 9 条,全部在en:后四条一并在本 PR 修掉,而不是另开 issue。 这是一个需要说明的越界,理由是:它们与两单是同一文件、同一缺陷、同一成因,而本单要交付的守卫无论如何都需要对它们有个处置。剩下的唯一选择是引入豁免清单——而本文件里
select fields are translated in every locale那段注释已经把这条路判为 regression(#679 退役PENDING_SELECT_LABELS时写的原话:「空清单就是在邀请别人加一行」)。带 4 行豁免的守卫等于出厂即破。新增的 9 条全部是各视图
*.view.ts里label的逐字节照抄——不是翻译,没有编辑余地,用户读到的任何名字都没有变。stale_opportunities的·是 U+00B7、⚠️是 U+26A0 U+FE0F,与 metadata 一致(第三条断言会替你核对)。顺带删掉了
closing_this_quarter上「No label here on purpose」那段注释。它是 #746 写的,而 #679 早已对其它每个 locale 面做了相反的裁定;它给出的理由(en 不需要条目,因为 resolver 会回落到 metadata label)恰恰就是让这 9 条长期无人发现的那种隐身性。守卫(本单的核心交付)
两单都指出「没有任何 gate 看得见」,复核属实:
pnpm lint硬编码--skip-i18n;把 flag 去掉重跑也不报这些——只会输出一行platform built-ins: 2298 i18n issue(s) hidden,因为 app 自有的_views完整性根本不在被检查的集合里。所以这不属于 #494 那一类「被 flag 藏起来的告警」,而是压根没人检查的面。test/metadata-references.test.ts的every locale is complete on every authored surface块里加三条断言,视图集从编译后的 stack 派生(与 emptyState 守卫同一套 container 遍历),不是硬编码清单,所以明天新增的视图在引入它的那个 PR 上就被卡住:label(70 视图 × 4 语言包);_views条目——孤儿条目比缺口更坏,它看起来像覆盖,其实什么都没翻译;en的条目与它所代表的 metadata label 逐字节相同。第三条是 key 一致性做不到、而 #767 真正担心的那件事:当四个包的 key 都在时,改掉 metadata label,过去
en会白白跟着变(它的条目本就是同一串英文的副本),而 zh-CN / ja-JP / es-ES 继续翻译旧名字,没有任何东西会红。诚实地说清这条断言的边界:它只证明英文这一对是一致的,无法验证另外三门语言随后被重新翻译过——它让改名变响,不能让改名变对。这不算新规矩:本次改动前en已有的 61 条视图标签本来就 61/61 逐字节相同,因为 #679 是从objectstack.config里程序化提取而非手抄的。反真空断言守着派生本身:至少 50 个 canonical 视图、覆盖至少 10 个对象、每条都解析出 object 与 name,且每个语言包至少解析出一个
_views表。反向验证(四个方向,都是先声明后跑)
en.crm_task.overdue_tasksen: crm_task._views.overdue_tasks.label;逐字节断言保持绿(无可比对象)——正是两条断言应有的分工⏰ Overdue Tasksrenamed_last_release条目en: crm_task._views.renamed_last_releaseen.ts退回origin/mainenType of Change
Testing
pnpm validate— Validation passedpnpm typecheck— cleanpnpm lint— 13 warning(s), 14 suggestion(s)(与改动前一致,无新增)pnpm hygiene— source hygiene clean(含 no raw control bytes)pnpm build— Build completepnpm test— 63 files / 1517 passed / 1 skippedgrep -naP覆盖 gate 的盲区)零命中Checklist
.changeset/view-label-locale-parity.md,patch)@objectstack/*(锁 17.0.0-rc.2)content/docs/releases/--skip-i18n配置留给 reviewer 的两个判断点
crm_case×2、crm_opportunity×2)。理由见上;若认为应当拆走,删掉这 4 条 en 条目后守卫会立刻变红,所以拆分必然要配一个豁免清单。it()块;若认为把 en 钉死在 metadata 上过度,删掉它不影响前两条。我的建议是留下:en.ts 的_views少了三个视图标签(renewals_due / at_risk_accounts / hot_leads),而其余三个语言包都有;_views没有任何跨语言覆盖守卫 #767 列的第一条风险(改名后静默分叉)只有它能变成一次 CI 失败,而真要出现「英文该与 metadata 不同」的情形,contract-first 的解法是去改*.view.ts里那个唯一的生产者,而不是容忍两串英文各走各的。Generated by Claude Code