Repository navigation
fix(gen-zh-hant): rewrite /zh-Hans/ links to marketing pages and clusters - #266
Merged
Merged
Conversation
…ters
zhHantTargetBuilds answered false for every single-segment target outside
STATIC_ROUTES, so a zh-Hans body link to /zh-Hans/ontology/ (a marketing page)
or /zh-Hans/ai-native-app-platform/ (a cluster) survived into the generated
zh-Hant file. content-lint's cross-locale rule then refused that file, because
/zh-Hant/<slug>/ is built for both, and `pnpm build` exited 1.
A single segment now builds when the slug is in CLUSTERS (imported from
src/lib/clusters.ts, as content-lint does) or names a page in
content/pages/{zh-Hant,zh-Hans,en}/ (read by filename, as content-lint does,
mirroring the glossary branch). Unknown slugs stay unrewritten and reported.
Two pinned link fixtures run the real predicate off a stub slug registry.
Co-Authored-By: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017GeNDQH7E5S2rX8ajVAPxv
Contributor
Author
席位核对ACCEPT —
Accepted note: the registry drops a page file whose Next: PR #264 ( Landing: ready, then squash by the seat. Generated by Claude Code |
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 #265
What changed
scripts/gen-zh-hant.mjszhHantTargetBuildsnow answers true for a single-segment target (/zh-Hans/SLUG/) when the slug is a marketing page or a cluster. Before this change, every single segment outsideSTATIC_ROUTESanswered false. The generated zh-Hant post therefore kept the/zh-Hans/link, content-lint's cross-locale rule (#179) refused it because/zh-Hant/SLUG/IS built, andpnpm buildexited 1.Both families come from one route,
src/pages/[lang]/[cluster].astro. For every locale it emits every slug inCLUSTERSplus every sluggetMarketingPages(locale)returns. For zh-Hant that means every page authored in en, zh-Hans (derived by s2t) or zh-Hant. So the predicate reads:CLUSTERSimported fromsrc/lib/clusters.ts. This is the same module, and the same Node type-stripping import, that content-lint'sreadClusterSlugsuses.content/pages/{zh-Hant,zh-Hans,en}/SLUG.ts, read by filename the way content-lint'sreadLocaleTreereads them, through theHANT_SOURCE_LOCALESlist the glossary branch already uses. The page modules cannot be imported under plain Node, because they import other modules without an extension.An unknown slug still answers false, stays unrewritten and is still reported. #142's rule is unchanged: rewrite only where the Traditional target is provably built, and only on link targets.
Before and after:
slugBuildsis a parameter only so the pinned fixtures can run the real function off a stub. I added two link-rewrite fixtures, and they run inside everypnpm devandpnpm build:[t](/zh-Hans/known/)becomes[t](/zh-Hant/known/)(positive).[t](/zh-Hans/ghost/)is left as it is (negative).The header's "WHERE NO CHECK IS NEEDED" bullets now describe the new behaviour.
Sensitivity leg (scratch fixture, never committed)
A temporary paragraph went into
content/blog/ai-wrote-your-app-dare-to-merge/index.zh-Hans.mdxthroughablation-replace. That tool requires the anchor to hit, and it proves the restore by blob hash and an emptygit diff HEAD. A trap then restored both the zh-Hans and zh-Hant files from HEAD.Leg A (positive). The paragraph links
[本体页](/zh-Hans/ontology/),[对比页](/zh-Hans/compare/#faq)and[AI 原生应用平台](/zh-Hans/ai-native-app-platform/)(a cluster).45d5ce98374487[本體頁](/zh-Hans/ontology/)、[對比頁](/zh-Hans/compare/#faq) 與 [AI 原生應用平臺](/zh-Hans/ai-native-app-platform/)[本體頁](/zh-Hant/ontology/)、[對比頁](/zh-Hant/compare/#faq) 與 [AI 原生應用平臺](/zh-Hant/ai-native-app-platform/)⚠ zh-Hant: left 3 /zh-Hans/ link(s) as-is — no provable Traditional buildpnpm content:lint✗ content lint failed (3 blocking issues): threeCross-locale internal link … IS builterrors (ontology, compare#faq, ai-native-app-platform)✓ content lint passed (347 files, 46 glossary terms checked)Leg B (negative). The paragraph links
[不存在](/zh-Hans/no-such-page-265/). The result is the same before and after: the generated line keeps/zh-Hans/no-such-page-265/, and the generator reportsleft 1 /zh-Hans/ link(s) as-is.The cluster link fails in exactly the same way as the marketing-page links, so it is the same defect and it is fixed here too.
Ablation (are the fixtures sensitive?)
With the fix committed,
ablation-replacereplacedreturn STATIC_ROUTES.has(segments[0]) || slugBuilds(segments[0]);withreturn STATIC_ROUTES.has(segments[0]);. The tool reportedok mutation landed: anchor 1 -> 0, blob b496693887d8 -> b50235dea050.node scripts/gen-zh-hant.mjsthen exited 1:It went red, as predicted. Only the positive case failed; the negative case is correct either way. Restore:
ok restored: blob == HEAD (b496693887d8) and git diff HEAD is empty.Provably built, checked against
dist/After
pnpm build, I checked every slug the new predicate can answer true for: 17 pages and 5 clusters, 22 in all. Each has adist/zh-Hant/SLUG/index.html, so none is missing.dist/zh-Hant/no-such-page-265/is absent.Gates (HEAD
8374487)pnpm content:lint✓ content lint passed (347 files, 46 glossary terms checked)pnpm content:lint --published✓ content lint passed (347 files, 46 glossary terms checked)pnpm check(shared lock)VERDICT command-exit 0;Result (160 files): 0 errors, 0 warnings, 0 hintspnpm build(shared lock)VERDICT command-exit 0;✓ zh-Hant: generated 47, kept 0 hand-maintained, 7 with body links pointed at /zh-Hant/;[build] Complete!;✓ content lint --dist links passed (98464 internal links in 912 built pages resolve to built files)pnpm seo:smokeSEO smoke test passed (902 HTML pages checked; 586 sitemap URLs against 316 noindexed pages; …)git status --porcelainis empty after the build, so no generated zh-Hant file moved. That is expected: no zh-Hans post on main links a page or a cluster yet.Acceptance notes
[cluster].astrobuilds them for every locale unconditionally, they are provable through the import content-lint already uses, and they fail in exactly the same way (leg A).enalso answers true, mirroring the glossary branch.getMarketingPages('zh-Hant')emits every en page as a noindexed fallback, so that target is built too. Today the en and zh-Hans page sets are identical, so this changes nothing on main./zh-Hans/ontology/, and PR content(blog): When Should You Not Use an Executable Business Ontology? (slot 2026-11-05) #264 (the post for Post (slot Thu 2026-11-05): When Should You Not Use an Executable Business Ontology? #261) its/zh-Hans/compare/link. This PR does not touch either of them.slugfield differs from its filename. content-lint checks that for glossary terms, but not for pages, so content-lint'sreadLocaleTreeand this predicate would both count such a file as present. All 34 page files match today (checked). A dead link that resulted would be caught bycontent lint --dist linksat build time./zh-Hans/blog/topics/…) are still not rewritten, because they need the term extractor. That is unchanged.Generated by Claude Code