F182 B1: i18n sweep — shared chrome + primitives (nav labelKey, AppLayout, dialogs, PWA)#238
Merged
Conversation
added 4 commits
July 26, 2026 20:53
…182) First screen-externalization batch (B1, Task 7): navGroups()/tabEntries() are pure functions, so nav items now carry a typed labelKey into the new English-only `nav` namespace instead of a hardcoded label; AppLayout and BottomNav translate it at their render sites — one label source for the sidebar, the bottom tab bar, and the More sheet. Also externalizes AppLayout's landmark aria-labels, sign-out, the farm-load-failed banners + retry button, adds a skip-to-content link, and composes document.title from the active nav entry's label + a shared suffix. BottomNav gets its first dedicated test file. `nav` stays out of TRANSLATED_NAMESPACES (English-first); es/tl untouched. i18n:scan (src/routes src/components) count: 843 -> 835.
Batch B1, Task 8 of the i18n string sweep. Dialog's close button reuses common.close; NumberField's Increase/Decrease aria-labels and ErrorBoundary's crash-fallback copy get their own English-only namespaces (numberField, errorBoundary), following the same not-yet-translated treatment Task 7 gave `nav`. Wiring tests use the i18n.addResource override technique to prove the catalog is actually read, not just falling back to hardcoded English.
…182) Adds themeToggle/useConfirm/pwa namespaces (English-only, like nav and numberField from Task 7/8) and wires each component to t(). useConfirm's Cancel button reuses the existing common.cancel atom instead of a new key.
…talog-sourced (#182) Two deferred review findings from the B1 chrome/primitives batch (Tasks 7-9): the nav.help comment claimed the key was reused for both the Help destination and the Help group heading, but nav.tsx actually uses two distinct keys (groupHelp for the heading, help for the destination), matching every other group's group*/entry-key pairing — reword to say so. Also add a wiring test proving AppLayout's document.title reads its per-page label from the catalog: the existing test only asserted the titleSuffix half via an addResource override, so a hardcoded label would have passed the label half under default lng:"en".
This was referenced Jul 27, 2026
Merged
mforce
added a commit
that referenced
this pull request
Jul 27, 2026
…) — stacked on #238 (#239) * feat(web): externalize shared nav chrome — nav, AppLayout, BottomNav (#182) First screen-externalization batch (B1, Task 7): navGroups()/tabEntries() are pure functions, so nav items now carry a typed labelKey into the new English-only `nav` namespace instead of a hardcoded label; AppLayout and BottomNav translate it at their render sites — one label source for the sidebar, the bottom tab bar, and the More sheet. Also externalizes AppLayout's landmark aria-labels, sign-out, the farm-load-failed banners + retry button, adds a skip-to-content link, and composes document.title from the active nav entry's label + a shared suffix. BottomNav gets its first dedicated test file. `nav` stays out of TRANSLATED_NAMESPACES (English-first); es/tl untouched. i18n:scan (src/routes src/components) count: 843 -> 835. * feat(web): externalize Dialog, NumberField, ErrorBoundary strings (#182) Batch B1, Task 8 of the i18n string sweep. Dialog's close button reuses common.close; NumberField's Increase/Decrease aria-labels and ErrorBoundary's crash-fallback copy get their own English-only namespaces (numberField, errorBoundary), following the same not-yet-translated treatment Task 7 gave `nav`. Wiring tests use the i18n.addResource override technique to prove the catalog is actually read, not just falling back to hardcoded English. * feat(web): externalize ThemeToggle, useConfirm, UpdatePrompt strings (#182) Adds themeToggle/useConfirm/pwa namespaces (English-only, like nav and numberField from Task 7/8) and wires each component to t(). useConfirm's Cancel button reuses the existing common.cancel atom instead of a new key. * fix(web): correct nav.help comment + prove per-page title label is catalog-sourced (#182) Two deferred review findings from the B1 chrome/primitives batch (Tasks 7-9): the nav.help comment claimed the key was reused for both the Help destination and the Help group heading, but nav.tsx actually uses two distinct keys (groupHelp for the heading, help for the destination), matching every other group's group*/entry-key pairing — reword to say so. Also add a wiring test proving AppLayout's document.title reads its per-page label from the catalog: the existing test only asserted the titleSuffix half via an addResource override, so a hardcoded label would have passed the label half under default lng:"en". * feat(web): externalize DailyEntryPage copy to the i18n catalog (#182) Task 11 (batch B2): every user-facing string in DailyEntryPage now flows through a new `dailyEntry` namespace (English-first, en.ts only). The entry-locked banner's status word is wired through enums.statusLabel, which harmonizes ManagerAdjusted's visible text from raw "manageradjusted" to "Adjusted" (matching HistoryPage's own bespoke badge). * feat(web): externalize Dashboard.tsx strings to the i18n catalog Adds a new English-first `dashboard` namespace (en.ts only, not in TRANSLATED_NAMESPACES) covering the landing page's headings, stat labels, empty-state copy, and table headers. Wires both StatusBadge render sites (today's per-flock entry status, recent order status) through the B0 enums `statusLabel` helper, which harmonizes a ManagerAdjusted entry from raw "ManagerAdjusted" to "Adjusted", matching HistoryPage's existing badge for the same state. Also removes a stray blank line left after the function signature. (#182) * feat(web): externalize WaterPage strings (#182) Externalizes WaterPage.tsx to a new `water` namespace (en.ts only, English-first), wiring the Source and Unit displays through the B0 waterSourceLabel/waterUnitLabel enum helpers everywhere they render (select options, table cells, and the quantity label's unit suffix). Both families are identity-labelled in English, so nothing renders differently. Adds i18n.addResource wiring tests alongside the existing suite, which stays green untouched since the English text is unchanged. * feat(web): externalize GradesPage strings (#182) Externalizes GradesPage.tsx to a new English-first `grades` namespace (en.ts only, not in TRANSLATED_NAMESPACES) — form labels, table headers, buttons, the intro paragraph, load-failure message, and the saleable "yes" badge. The grade-type select/table-cell now render through the B0 gradeTypeLabel enum helper instead of the raw wire value; grade NAMES (g.name) stay raw as free-form farm data. Adds i18n.addResource wiring tests confirming the screen reads the catalog (and the enums catalog for grade type) rather than hardcoded literals. * fix(web): wire GradesPage StatusBadge through statusLabel (#182) Review fix round 1 on Task 14: the Active/Inactive StatusBadge cell was left unwired, inconsistent with sibling B2 screen Dashboard (Task 12), which wires its bare StatusBadge sites through statusLabel. Adds label={statusLabel(...)} alongside the existing raw status= (kept for the variant class) — 100% text-preserving today (identity labels) and future-proofs the badge for the eventual status translation pass. --------- Co-authored-by: mforce <>
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.
B1 — shared chrome + primitive components. Second batch of the #182 string sweep (foundation B0 merged in #237). Externalizes the app's navigation chrome and shared primitives to the catalog, English-first — no es/tl for these (they fall back to English until the scheduled native-review pass; only the already-translated set + Help carry translations).
What this externalizes
nav.tsx→ typedlabelKeymodel.navGroups/tabEntriesare pure functions (can't call a hook), so nav items now carry a typedlabelKey(keyofthenavcatalog → a typo is a compile error) instead of a hardcoded Englishlabel; AppLayout, BottomNav, and the More sheet translate at render. One label source for sidebar/tabs/mobile.aria-labels, sign-out; plus a skip-to-content link and a catalog-composeddocument.title(per-page label + suffix) that didn't exist before (both were plan-review "missed sources" —document.title, a11y).BottomNav.test.tsx).common.close), NumberField (interpolated stepper aria-labels), ErrorBoundary (fallback heading/body/reload), ThemeToggle, useConfirm (reusescommon.confirm/cancel), and the PWA UpdatePrompt banner.Namespaces (all English-only)
nav,numberField,errorBoundary,themeToggle,useConfirm,pwa— added toen.tsonly; not inTRANSLATED_NAMESPACES, so es.ts/tl.ts are byte-unchanged and parity stays green (the allowlist guard fails the build if a deferred namespace is ever drafted into es/tl). Shared verbs reusecommonatoms; no duplication.Testing / review
Wiring tests use the B0
i18n.addResourceoverride technique — each asserts the overridden catalog value renders (marker present + original literal absent), so a still-hardcoded string fails (empirically confirmed by a reverted mutation test).npm run test786 green; coverage above the (unchanged) floors — no locked path touched;npm run typecheckclean;npm run buildsucceeds.Reviewed per policy: each of the 4 tasks was individually reviewed (spec + quality, several with live mutation probes), then a whole-branch review (Claude comprehensive lens — READY; codex's whole-branch run produced no usable verdict). One Minor (the
document.titleeffect's dependency array churns harmlessly every render) is left as an optional follow-up.Not in scope
es/tl for these screens (deferred native-review pass, tracked in #182); the remaining screens (B2–B6).