fix(i18n): align the executive pipeline tile to its shared factory, and guard the class - #1360
Merged
Merged
Conversation
`src/dashboards/shared-widgets.ts` states each shared widget's semantics once, but every dashboard still carries its own locale entry for it, so one factory-owned sentence is stored as (dashboards x locales) freely editable strings. Nothing watched them: `pnpm lint --skip-i18n` skips the bundles and `test/i18n-references.test.ts` asserts key coverage, not that two entries fed by one source string still agree. The rule is stated against the source rather than as "all entries must match": a locale must group dashboards by description exactly the way the source groups them. That tolerates `avgDealSizeMetricWidget`'s deliberate per-dashboard override (Sales pins itself to QTD) while still catching a fork of a description the factory unifies. A second assertion anchors the baseline itself — for a factory-owned widget the `en` bundle is not a translation but the same sentence, so it must reproduce the literal. This commit is deliberately RED. The existing drift is precisely what the guard exists to catch, and the alignment lands in the next commit — a guard never observed failing has not been shown to work. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01WMzCeNC4SZcPNBpE2zCVCg
All four locale bundles gave `executive_dashboard`'s `pipeline_by_stage` a different description from the `crm_overview_dashboard` and `sales_dashboard` entries fed by the same factory — "by sales stage" against "at each sales stage" in `en`, and the same split in `zh-CN`, `es-ES` and `ja-JP`. Four bundles drifting the same way is a translation lineage rendered from one early copy, not four independent typos. The baseline is the factory literal in `src/dashboards/shared-widgets.ts`, not the wording two of the three entries happen to share. Those coincide today; anchoring on the source is what keeps them coinciding — and it is what the guard's English assertion pins. Four lines change, one per locale. `title` was already uniform and is untouched. No user reads a different meaning: the Executive tile now reads exactly as the identical tile already read on the other two dashboards. The guard added in the previous commit goes from red to green on this diff. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01WMzCeNC4SZcPNBpE2zCVCg
|
The latest updates on your projects. Learn more about Vercel for GitHub. |
The frontmatter was empty, declaring that this PR publishes nothing. That declaration is false. The locale bundles compile into the shipped artifact — the same `pnpm verify` run that gates this PR prints `Artifact: dist/objectstack.json (1969.8 KB)` — so four user-visible strings in four locales ship with it. The change is still a synonym, and the changeset still says so: no user reads a different meaning, and the Executive tile now reads exactly as the identical tile already read on the other two dashboards. But that is a statement about severity, not about whether something shipped. Every other empty-frontmatter changeset in the directory earns the exemption by being test-only, prose-only or CI-only; this one edits `src/` and cannot borrow that sentence. A false declaration in the release ledger is worse than an over-counted patch. Changeset frontmatter and its justifying paragraph only. The four translation edits, the guard and `title` are untouched. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01WMzCeNC4SZcPNBpE2zCVCg
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 #980
All four locale bundles gave
executive_dashboard'spipeline_by_stagetile a different description from thecrm_overview_dashboardandsales_dashboardentries fed by the same shared factory. This aligns the four drifted entries to the factory literal and adds the guard that keeps them there.The hole
src/dashboards/shared-widgets.tsexists so that "what counts as open pipeline" is stated once — #539 deleted the three source-side copies of the pipeline funnel by moving the definition into a factory the three dashboards each call. The i18n side was never deduplicated. Every dashboard still carries its owndashboards.DASHBOARD.widgets.WIDGET.descriptionin every locale, so one factory-owned sentence is stored as twelve independently editable strings — the exact shape #539 removed, one layer down.Nothing was watching:
pnpm lint --skip-i18nskips the bundles, andtest/i18n-references.test.tsasserts key coverage — every authored surface translated, every key resolving — never that two entries fed by one source string still agree.Re-measured on
main@46238e1Source of truth,
src/dashboards/shared-widgets.ts:35:titleis uniform in all twelve entries; onlydescriptionforked. All four bundles drift in the same direction, which is a translation lineage rendered from one early copy, not four independent typos.Correction to a claim in the card
The card (and the triage comment) state that
en.ts's description also disagrees with the source, making "a fourth wording". Measured false.en.ts:1380anden.ts:1408are byte-identical toshared-widgets.ts:35; onlyen.ts:1395differs. There is no fourth wording — there are two, and the source already agrees with two of the three English entries. The two correct entries are left alone.The guard, and why it is not "all entries must be equal"
The blunt rule would have been red on landing for a legitimate reason.
avgDealSizeMetricWidgettakesoverridesand Sales uses them — its tile is pinned to the quarter, so its description ends "this quarter" while CRM's does not, and all four bundles already reflect that correctly. Failing it would teach authors to erase a real distinction.So
test/i18n-shared-widget-parity.test.tsstates the invariant against the source, one level up from the strings:One rule, both failure directions — forking a description the factory unifies, and merging one the source deliberately keeps apart. A second assertion anchors the baseline itself: for a factory-owned widget the
enbundle is not a translation but the same sentence, so it must reproduce the literal byte for byte. Without it a family of entries could agree with each other perfectly and still all disagree with the code that renders them.Widget ids are discovered by invoking every factory the shared module exports, not transcribed into the test, so a factory added later is covered the day it lands. Occurrences are matched by widget id rather than by "was this a factory call", so a hand-inlined copy is held to the same rule.
Red before green — both states shown
This card inverts the usual order deliberately: the existing drift is precisely what the guard exists to catch, so it must fail on the pre-alignment tree. That red is the reverse-verification. A guard never observed failing has not been shown to work. The two states are separate commits.
d3005d4— guard only, on the unaligned tree. RED, naming all four entries:Note what did not fail:
avg_deal_size, whose per-dashboard override is legitimate. The guard is red on the fork and silent on the deliberate difference — which is the whole point of stating it as a partition.b07933b— four lines aligned, one per locale. GREEN:The third test is an anti-vacuity check: it fails if no factory is found, no locale pack loads, or no shared widget is used by more than one dashboard — so the parity assertion can never pass by reading nothing.
Verification
pnpm verifygreen in full, re-run after the changeset correction on the exact tree atecd9e18(working tree clean, so the run and the commit are the same bytes):The three fast gates were re-run at
ecd9e18after the final commit; the verdict lines above are each gate's own output, not a shell exit code. Confirmed the new suite is really measured rather than silently skipped: 144test/*.test.tsfiles on disk against 144 files in the run, andtsc --noEmit --listFilesincludes the new file.Scope
executivepipeline_by_stage.descriptionentries, and the guard.title, already uniform across all twelve entries. The guard assertsdescriptiononly.content/docs/analytics/dashboards.mdx:129and the Quick Tour section, which quote the source text and are unaffected.No other shared-factory widget drift surfaced. With the guard covering both exported factories across all five registered dashboards and all four locales,
avg_deal_sizeis clean — nothing to report for a follow-up card.Changeset
'hotcrm': patch.It landed as empty frontmatter first — the "releases nothing" declaration
changeset-check.ymlsanctions — and that was wrong. The locale bundles compile into the shipped artifact, which this PR's own verify run prints asArtifact: dist/objectstack.json (1969.8 KB), so four user-visible strings in four locales ship with it. The change is still a synonym and the changeset still says so, but that is a statement about severity, not about whether something shipped. Every other empty-frontmatter changeset in that directory earns the exemption by being test-only, prose-only or CI-only; this one editssrc/and cannot borrow the sentence, and a false declaration in the release ledger is worse than an over-counted patch. Corrected inecd9e18, confirmed withchangeset status --since=origin/main:Generated by Claude Code