fix(cli): translate section, page, and variantId values inside variant layouts#15864
fix(cli): translate section, page, and variantId values inside variant layouts#15864devin-ai-integration[bot] wants to merge 3 commits into
Conversation
🤖 Devin AI EngineerI'll be helping with this pull request! Here's what you should know: ✅ I will automatically:
Note: I can only respond to comments from users who have write access to this repository. ⚙️ Control Options:
|
There was a problem hiding this comment.
Claude Code Review
This repository is configured for manual code reviews. Comment @claude review to trigger a review and subscribe this PR to future pushes, or @claude review once for a one-time review.
Tip: disable this comment in your organization's Code Review settings.
Docs Generation Benchmark ResultsComparing PR branch against median of 5 nightly run(s) on
Docs generation runs |
SDK Generation Benchmark ResultsComparing PR branch against median of 5 nightly run(s) on Full benchmark table (click to expand)
main (generator): generator-only time via --skip-scripts (includes Docker image build, container startup, IR parsing, and code generation — this is the same Docker-based flow customers use via |
Test results — variant overlay translation on coreweaveEnd-to-end tested PR
All variant-tab sidebar section labels render in the target language; no English leaked. Page children (Configurer SMTP, デプロイオプション, 엔터프라이즈 라이선스, …) also rendered translated. FR —
|
c1cb588 to
3cbf628
Compare
Translation overlays for tabs that use variants now support a per-variant `layout:` field whose section and page titles override the resolved navigation tree. This is needed for docs sites that use `tabs:` + `variants:` and want non-default locale sidebars to translate fully. - VariantOverlay gains an optional layout array of NavigationItemOverlay - parseVariantOverlays threads through the layout field - applyTranslatedNavigationOverlays handles the 'varianted' parent type and scopes each matched variant's layout as the navigation context for its children - matchSectionOverlay / matchPageOverlay match overlay slugs leniently: '/' and empty mean 'root', and absolute slugs are normalised to their last segment so they line up with the tree's resolved slug Co-Authored-By: will.kendall@buildwithfern.com <wpk235@gmail.com>
3cbf628 to
4683d35
Compare
When a variant overlay sets `title:`, also override the variant node's `variantId` so downstream renderers that key off the typed variant identifier (e.g. coreweave's custom navbar dropdown) display the translated label. The original `variantId` mirrors the source variant `title` (see DocsDefinitionResolver.toVariantNode), so keeping these in sync per locale is consistent with the source behaviour. Also stop mutating the input root in applyTabOverlayToNode (caught by the existing 'does not mutate the original root' test). Co-Authored-By: will.kendall@buildwithfern.com <wpk235@gmail.com>
Translation overlays for sections/pages are no longer silently re-attached positionally when their slug doesn't match any sibling navigation entry. Instead the matcher warns via the CLI logger so drifted overlays surface during fern generate / fern check instead of producing mistranslated nav. Overlays without a slug remain positional (the intentional case), and the existing leaf-segment slug normalization continues to handle absolute and relative slug forms symmetrically. Co-Authored-By: will.kendall@buildwithfern.com <wpk235@gmail.com>
Description
When a docs site uses
tabs:+variants:and adds non-default locales viatranslations:, the resulting localized sidebar leaves every section and page title in the source language. The middle-of-page content translates (MDX frontmatter handles that), but the left-hand navigation stays in English.Root cause is in the translation overlay system inside the CLI:
VariantOverlayhad nolayoutfield, so the overlay parser dropped every nested section/page declared inside a variant — onlytitle/subtitle/slugsurvived parsing (seeparseVariantOverlaysinpackages/cli/configuration-loader/src/docs-yml/parseDocsConfiguration.ts).variantedparent-type branch inapplyChildOverlays, so the per-variant overlay layout never reached the variant's children.docs.ymlsyntax (slug: /for a root page) did not line up with the tree's resolved slug (home).title:, only the variant's displaytitlefield was updated. The variant'svariantId— which is what downstream renderers like custom navbar dropdowns key off of — still carried the source-language label. Even after the layout fix, custom dropdowns (e.g. coreweave'stab-variants.js) still rendered "Home" / "Support Home" in the navbar dropdown's first item on FR / JA / KO pages.This PR fixes all four issues so overlays of the shape
now translate the variant's section and page titles, and update the variant's
variantIdso custom renderers stay in sync.Changes Made
VariantOverlaygains an optionallayout: NavigationItemOverlay[]field, mirroring the source navigation shape.parseVariantOverlays()parses the newlayoutfield viaparseNavigationItemOverlays(...).applyChildOverlays()now handles thevariantedparent-type by walking each variant againstoverlay.variantsand scoping the matched variant's layout as the navigation overlay for its children.applyTabOverlayToNode()no longer special-cases a non-existentvariantstree node; instead it emits a scoped overlay carrying either the tab's flat layout or a synthetic Tab entry with the variants. The downstreamvariantedbranch unwraps it. It also shallow-copies the input node before mutating so the input tree is never modified in place.applyVariantOverlays()is rewritten to:title:/subtitle:overrides;variantIdto mirror the translatedtitleso custom renderers built off the typed variant identifier (e.g. navbar dropdowns) display the translated label;layout:as the navigation overlay for its children (variants directly own pages/sections, soapplySidebarChildOverlaysruns over the variant's children).matchSectionOverlay()/matchPageOverlay()usenormalizeOverlaySlug()so overlay slugs that mirrordocs.ymlsyntax (/,/path/to/leaf) line up symmetrically with the tree's resolved last-segment slug. Positional fallback is kept for overlays that explicitly omitslug:(the intentional positional case). Overlay entries with a non-matchingslug:are NOT silently re-attached positionally — instead they are reported via a CLI warning fromapplyTranslatedNavigationOverlaysso drifted overlays surface duringfern check/fern generateinstead of producing mistranslated navigation.tab → sidebarRoot → varianted → variant → childrentree shape, including tab title, variant title, variantId mirroring, and per-variant nested section/page title overrides; (2) the strict matcher behavior (slug-bearing overlay with no matching sibling emits a warning and is ignored, while overlays withoutslug:continue to match positionally without warning).Testing
Unit tests added/updated —
applyTranslatedNavigationOverlays.test.tscovers tab title, variant titles, variantId mirroring, per-variant nested section/page title overrides, and the new strict matcher / warning behavior; full file passes locally.Manual testing completed — built the production CLI with
pnpm fern:buildand ranFERN_NO_VERSION_REDIRECTION=true fern docs devagainstfern-demo/coreweave@fern-support/tab-variants, which has FR/JA/KO overlays mirroring the new tabs+variants structure. Before this PR the FR/JA/KO sidebars rendered in English; after this PR they render fully translated, and the navbar dropdown first item now matches the variant's translatedtitle:/fr/ja/koLink to Devin session: https://app.devin.ai/sessions/208b696a97f94e13a952f6f99ecc4c75