F182 B2: i18n sweep — daily ops (DailyEntry, Dashboard, Water, Grades) — stacked on #238#239
Merged
Conversation
added 9 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".
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).
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)
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.
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.
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.
mforce
added a commit
that referenced
this pull request
Jul 27, 2026
…locks) — stacked on #239 (#240) * feat(web): externalize InventoryPage strings (#182) Move every user-facing string in InventoryPage.tsx into a new flat `inventory` namespace in en.ts (English-only, 60 keys), following the Screen Externalization Pattern from B1/B2. Wires category and status displays through the B0 enum helpers (inventoryCategoryLabel, statusLabel), and the movement ledger's Type cell through inventoryMovementLabel — while keeping the Correct-stock dialog's decorated Type picker options ("Adjustment (±)", "Discard (write-off)") as plain screen copy, since that text is not the ledger's identity label. All enum families are identity-mapped in English today, so the retrofit is text-preserving. Adds 11 i18n-wiring tests (i18n.addResource override technique) on top of the unchanged, still-green functional suite, including a pair of tests that prove the adjust-type picker reads screen copy rather than the movement enum. i18n:scan count drops from 707 to 645. * feat(web): externalize ProductsPage strings (#182) Task 17 (batch B3, the last B3 screen): moves every user-facing string in ProductsPage.tsx into a new flat `products` namespace in en.ts (English-only, not in TRANSLATED_NAMESPACES). Wires both the products table's StatusBadge and the packed-unit table's plain-text status cell through the shared statusLabel enum helper; unitCode/defaultUnit and product/grade names stay raw as free-form farm data. Adds i18n.addResource wiring tests covering the heading, button labels, both status-enum sites, the two data-interpolated templates (price-with-currency label, eggs-per-unit dialog title), and the price-precision validation message. * feat(web): externalize StockPage strings (#182) Adds the `stock` namespace (English-first, not in TRANSLATED_NAMESPACES) and wires the movement ledger's Type cell through the B0 stockMovementLabel helper. Grade/lot names, dates, and quantity/delta values stay raw farm data. * feat(web): externalize FlocksPage strings (#182) Adds the `flocks` namespace (English-first) and wires the bird-ledger movement-type select/cells through flockMovementLabel and the status badge through statusLabel — the last B3 screen of the i18n sweep. * docs(web): correct stale B3 ordinal comments in en.ts (#182) --------- 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.
B2 — daily operations. Third batch of the #182 string sweep. Externalizes the four daily-ops screens to the catalog, English-first, and wires their closed-vocabulary displays through the B0 typed
enumshelpers.Screens externalized (English-only namespaces)
dailyEntry(~47 keys) — form labels, validation, section headings; the locked-entry banner now resolves its status viastatusLabel.dashboard— panel/stat labels, empty states; both status pills (entries table + recent-sales panel) wired viastatusLabel.water— form + table; the Source select/cells and unit displays now go throughwaterSourceLabel/waterUnitLabel(were raw{r.source}/{r.unit}).grades— grade-type select/cell viagradeTypeLabel; the Active/Inactive badge viastatusLabel.One intentional visible change
ManagerAdjustedstatus now displays as "Adjusted" (matching HistoryPage's existing badge), applied consistently in DailyEntryPage (locked banner, lowercased inline) and Dashboard (entries pill). Every other enum label is identity — no other visible text moved. Free-form data (grade/flock/customer names, notes) stays raw.Guarantees held
en.ts-only, not inTRANSLATED_NAMESPACES— parity green.i18n.languagein any screen; the formatting-independence guard passes (a Dashboard test even asserts an unformatted1560to prove noIntl.NumberFormatcrept in).StatusBadge'sstatusprop stays raw so pill tint is unchanged.commonatom duplicated; shared verbs reusecommon(incl.common.all).Testing / review
Wiring tests use the
i18n.addResourceoverride technique (a hardcoded literal fails — verified by reverted mutation probes on each screen).npm run test807 green; coverage above the (unchanged) floors — no locked path touched;npm run typecheckclean;npm run buildsucceeds. Each of the 4 screens was individually reviewed (spec + quality, with empirical probes; GradesPage got one fix — wiring its status badge), then a whole-branch review (Claude comprehensive — READY).Not in scope
es/tl for these screens (deferred native-review pass, #182); B3–B6.