Skip to content

phase-4-header-language-selector#95

Open
AndreasAbdi wants to merge 4 commits into
mainfrom
phase-4-header-language-selector
Open

phase-4-header-language-selector#95
AndreasAbdi wants to merge 4 commits into
mainfrom
phase-4-header-language-selector

Conversation

@AndreasAbdi

Copy link
Copy Markdown
Contributor

{
"project": "Model Atlas",
"branchName": "phase-4-header-language-selector",
"description": "Add an accessible language selector to the shared docs header so readers can switch locale from the page they are already viewing, preserve the same canonical destination when an equivalent localized route is shipped, and show explicit unavailable behavior when a target locale is not shipped for that destination.",
"context": {
"customerAsk": "Phase 4: add an accessible language selector to the docs header so readers can switch language from the current page instead of navigating elsewhere first. Build on top of the shared locale contract, and keep the header within the established docs shell. The selector must work on desktop and mobile, preserve the current destination when an equivalent localized route exists, and avoid dumping the user onto an unrelated page. For pages/locales that are not yet shipped, prefer explicit disabled or unavailable behavior over silent wrong-language routing. Reuse existing route-localization helpers where possible instead of hard-coding paths. Acceptance criteria: the header exposes a keyboard-accessible language control, shows the supported locale choices from shared config, keeps users on the same canonical destination when switching between shipped locales, behaves clearly on untranslated routes, and has focused tests for route-preserving behavior plus header accessibility semantics. This idea must not broaden into Japanese page translation itself; it is the shared switching UI only.",
"problem": "Readers currently have no shared header control for switching locales from the route they are already on. Without a route-aware selector, they must navigate elsewhere first or risk a naive locale switch that drops their current destination, sends them to an unrelated page, or implies a page is translated when that locale is not actually shipped for the current surface.",
"solution": "Add one shared docs-header language selector that reads locale choices from the authoritative locale contract and derives target routes through the existing locale-routing helpers. When the current canonical destination is shipped in another locale, the selector navigates to that exact equivalent route. When the destination is not shipped for a locale, the selector presents that locale as explicitly unavailable or disabled instead of misrouting the reader."
},
"acceptanceCriteria": [
"The docs header exposes a keyboard-accessible language selector on desktop and mobile within the established docs shell.",
"The selector renders its locale choices from the shared supported-locale configuration instead of a hard-coded per-surface list.",
"Switching to another locale keeps the reader on the same canonical destination whenever that destination is shipped in the target locale.",
"When the current destination is not shipped for a target locale, the selector communicates that state clearly with explicit unavailable or disabled behavior and does not send the reader to an unrelated page.",
"The selector reuses shared locale-routing and route-localization helpers so locale links, metadata expectations, and routing behavior stay aligned.",
"Focused automated coverage proves route-preserving switching behavior and header accessibility semantics, and browser verification covers visible desktop and mobile behavior.",
"Quality gate: make typecheck, make lint, and make test pass."
],
"userStories": [
{
"id": "phase-4-header-language-selector-001",
"title": "Show shared locale choices in the docs header",
"description": "As a reader, I want a language selector in the docs header so I can see the supported languages from the page I am already on.",
"acceptanceCriteria": [
"The shared docs header includes a language control on locale-aware reader surfaces that use the established docs shell.",
"The control lists the supported locales from the shared locale contract, including the current active locale, instead of duplicating locale labels in route-specific code.",
"Desktop and mobile header variants both expose the language control without moving it outside the existing docs shell pattern.",
"The current active locale is visually and semantically identifiable in the control.",
"Typecheck passes",
"Tests pass",
"Verify in browser using dev-browser skill"
],
"priority": 1,
"passes": true,
"notes": ""
},
{
"id": "phase-4-header-language-selector-002",
"title": "Preserve the current canonical destination when switching to a shipped locale",
"description": "As a reader, I want locale switching to keep me on the same destination so I can continue reading the equivalent page in another language.",
"acceptanceCriteria": [
"Selecting a locale for a route whose equivalent destination is shipped in that locale navigates to that localized equivalent instead of a generic home, search, or tag page.",
"Route switching reuses the shared locale-routing and route-localization helpers rather than reimplementing path rules inside the header component.",
"Query strings and hash fragments that are part of the current reader destination remain attached when switching between shipped localized equivalents.",
"English remains unprefixed and non-default locales use their configured locale-prefixed routes.",
"Typecheck passes",
"Tests pass",
"Verify in browser using dev-browser skill"
],
"priority": 2,
"passes": true,
"notes": ""
},
{
"id": "phase-4-header-language-selector-003",
"title": "Make unshipped localized destinations explicit instead of misrouting",
"description": "As a reader, I want clear unavailable behavior when the current page is not translated so I do not get sent to the wrong page by the language selector.",
"acceptanceCriteria": [
"If the current canonical destination is not shipped in a target locale, that locale appears as disabled or explicitly unavailable from the selector.",
"Activating or attempting to activate an unavailable locale does not dump the reader onto an unrelated localized page.",
"The unavailable state is communicated in visible UI copy or status and exposed through accessible semantics rather than only by omission.",
"The selector behavior remains fail closed for unshipped docs, tag, search, glossary, architecture, and home surfaces according to the shared shipped-route model.",
"Typecheck passes",
"Tests pass",
"Verify in browser using dev-browser skill"
],
"priority": 3,
"passes": true,
"notes": ""
},
{
"id": "phase-4-header-language-selector-004",
"title": "Preserve accessible interaction semantics across keyboard and responsive header modes",
"description": "As a keyboard or assistive-technology user, I want the language selector to behave predictably so I can open, inspect, and choose locales without relying on pointer-only interaction.",
"acceptanceCriteria": [
"The language selector exposes semantic labeling that identifies it as the page language control.",
"Keyboard users can focus the control, open it, move through locale choices, and activate an available locale using standard interactive behavior.",
"Disabled or unavailable locale entries are announced and do not behave like active navigation targets.",
"The mobile presentation preserves the same keyboard and assistive semantics as the desktop presentation, even if the visual layout differs.",
"Typecheck passes",
"Tests pass",
"Verify in browser using dev-browser skill"
],
"priority": 4,
"passes": true,
"notes": ""
},
{
"id": "phase-4-header-language-selector-005",
"title": "Add focused regression coverage for route-preserving locale switching",
"description": "As a reviewer, I want direct regression coverage for the header selector so route-preserving behavior and accessibility semantics cannot drift silently.",
"acceptanceCriteria": [
"Automated tests cover switching from one shipped localized route to another while preserving the same canonical destination.",
"Automated tests cover at least one unshipped-locale case where the selector exposes explicit unavailable behavior and does not navigate to an unrelated route.",
"Automated tests verify the header language control exposes accessible semantics for the trigger, the current locale, and unavailable locale entries.",
"Browser verification demonstrates desktop and mobile header behavior for both an available-locale route switch and an unavailable-locale route state.",
"Typecheck passes",
"Tests pass"
],
"priority": 5,
"passes": true,
"notes": ""
}
]
}

…canonical destination when switching to a shipped locale]
…zed destinations explicit instead of misrouting]
…nteraction semantics across keyboard and responsive header modes]
@AndreasAbdi

Copy link
Copy Markdown
Contributor Author

BLOCKING: the current PR head is not mergeable yet.

gh pr view --json mergeable,mergeStateStatus reports mergeable: CONFLICTING and mergeStateStatus: DIRTY, so this branch must be rebased and the merge conflicts fixed before it can be merged.

Acceptance criteria:
PASS - The docs header exposes a keyboard-accessible language selector on desktop and mobile within the established docs shell. The header now renders a labeled native <select> in the shared docs header, and the added RTL/a11y coverage verifies keyboard focus on the control in both desktop and mobile header states.
PASS - The selector renders its locale choices from the shared supported-locale configuration instead of a hard-coded per-surface list. LanguageSelector reads from localeOptions in src/lib/i18n/locale-routing.ts, and tests assert the shared locale contract and rendered options.
PASS - Switching to another locale keeps the reader on the same canonical destination whenever that destination is shipped in the target locale. resolveLocalizedRouteSwitch() derives the destination from the shared route matcher and preserves query/hash suffixes; tests and browser verification both show /docs/modules/grouped-query-attention?view=graph#kv-cache switching to /vi/docs/modules/grouped-query-attention?view=graph#kv-cache.
PASS - When the current destination is not shipped for a target locale, the selector communicates that state clearly with explicit unavailable or disabled behavior and does not send the reader to an unrelated page. On /docs/modules/grouped-query-attention, the Japanese option renders as disabled with Unavailable on this page: 日本語, and tests verify no navigation occurs for the unshipped target.
PASS - The selector reuses shared locale-routing and route-localization helpers so locale links, metadata expectations, and routing behavior stay aligned. The selector and localizeDocsHref() now both rely on resolveLocalizedRouteSwitch() and the shared route helpers instead of duplicating path rules.
PASS - Focused automated coverage proves route-preserving switching behavior and header accessibility semantics, and browser verification covers visible desktop and mobile behavior. Coverage was added in src/components/layout/model-atlas-docs-header.test.tsx, src/tests/a11y/primary-navigation.a11y.test.tsx, and src/lib/i18n/locale-routing.test.ts. I also verified desktop and mobile behavior locally against next start on port 3475.
PASS - Quality gate: make typecheck, make lint, and make test pass. All three passed locally.

Behavioral assertion check:
PASS - Every story marked passes:true includes at least one behavioral assertion about observable UI or routing behavior, not only structural checks.

Quality-check evidence:
PASS - make test
PASS - make typecheck
PASS - make lint
PASS - Browser verification on desktop and mobile. Note: docs/temp/processes/manual-qa.md was not present in this branch, so I used direct browser verification against the stated acceptance criteria instead.

Required fix before merge:
BLOCKING - rebase onto current main, resolve the merge conflicts, rerun the checks on the rebased head, and push the updated branch. No independent correctness defects were found in the reviewed implementation beyond the mergeability blocker.

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.

1 participant