From 8e4a8080dcb5a16c42c8f4e01d2b2386f6cb15a4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Bombeck?= Date: Thu, 14 May 2026 12:43:02 +0200 Subject: [PATCH] i18n(targets): add EN + DE strings for redesigned card primitives MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Removes the duplicate `targets.mood` + `targets.moodStability` flat strings that collided with the new `targets.mood.stability.{stable, variable,highlyVariable}` object added in Phase 3. The flat versions were unreferenced — the canonical mood label lookup goes through `targets.label.MOOD_SCORE` / `targets.label.MOOD_STABILITY` — so removing them is a no-op for the UI and unblocks the i18n-locale-integrity duplicate-key test. Also rolls in the prettier-normalised formatting on the targets route + target-card files (no semantic change). All i18n keys added across phases 3-8 are documented inline: • targets.summary.{weekTitle,weekTitleAll,streakHighlight} • targets.card.{lastMet,streak} • targets.consistency.{ariaLabel,daysInRange,daysLogged, dotInRange,dotNearRange,dotOutOfRange, dotNotLogged,insufficientData,relativeDay.*} • targets.relativeDay.{today,yesterday,daysAgo} • targets.coach.cta • targets.mood.stability.{stable,variable,highlyVariable} Per-target Coach prefills (the W3e plan called for targets.coach.prefill.{bp,weight,…}) are NOT added as i18n strings — they're generated by `buildTargetPrompt()` in src/lib/ai/coach/target-prompts.ts which interpolates live state values. Keeping the templating in JS avoids 12 long-form bilingual strings with i18n interpolation gymnastics and lets the prompt include conditional fragments (streak, cadence) without exploding the key count. Verification: - pnpm typecheck: clean - pnpm test: 2325 / 2325 passing - pnpm lint: clean - i18n-locale-integrity: 9 / 9 passing (duplicate keys removed) --- messages/de.json | 2 -- messages/en.json | 2 -- src/app/api/insights/targets/route.ts | 10 ++-------- src/components/targets/target-card.tsx | 2 +- 4 files changed, 3 insertions(+), 13 deletions(-) diff --git a/messages/de.json b/messages/de.json index 97b93b7c3..05d5b9a48 100644 --- a/messages/de.json +++ b/messages/de.json @@ -2623,8 +2623,6 @@ "bodyFat": "Körperfett", "stepsPerDay": "Schritte/Tag", "medicationCompliance": "Einnahmetreue", - "mood": "Stimmung", - "moodStability": "Stimmungsstabilität", "steps": "Schritte", "average30d": "30-Tage-Schnitt:", "consistency": { diff --git a/messages/en.json b/messages/en.json index de2d424ab..e3168a18e 100644 --- a/messages/en.json +++ b/messages/en.json @@ -2623,8 +2623,6 @@ "bodyFat": "Body fat", "stepsPerDay": "Steps/day", "medicationCompliance": "Medication compliance", - "mood": "Mood", - "moodStability": "Mood stability", "steps": "steps", "average30d": "30-day average:", "consistency": { diff --git a/src/app/api/insights/targets/route.ts b/src/app/api/insights/targets/route.ts index 2355795a2..3fd1a0192 100644 --- a/src/app/api/insights/targets/route.ts +++ b/src/app/api/insights/targets/route.ts @@ -399,14 +399,8 @@ export const GET = apiHandler(async () => { */ function buildBpPairsByDay(): Map { if (!bpRange) return new Map(); - const sysByDay = new Map< - string, - Array<{ date: Date; value: number }> - >(); - const diaByDay = new Map< - string, - Array<{ date: Date; value: number }> - >(); + const sysByDay = new Map>(); + const diaByDay = new Map>(); for (const m of recentMeasurements) { if (m.type === "BLOOD_PRESSURE_SYS") { const k = berlinDayKey(m.measuredAt); diff --git a/src/components/targets/target-card.tsx b/src/components/targets/target-card.tsx index 325cd39c9..681a47a08 100644 --- a/src/components/targets/target-card.tsx +++ b/src/components/targets/target-card.tsx @@ -462,7 +462,7 @@ export function TargetCard({