From 71f73226243358c56d126b5fa10eb27f31b6a0ca Mon Sep 17 00:00:00 2001 From: Alexander Bocken Date: Fri, 1 May 2026 14:01:06 +0200 Subject: [PATCH] i18n(fitness): migrate inline ternaries across pages and components Replace lang === 'en' string ternaries on the check-in, stats, workout, exercises, history, and stats history detail pages, plus TemplateCard, with t. lookups against the fitness dictionary. Added new keys for toast messages, body-part counts, body-fat label, clear/measure short labels, "edit all fields", BF chart delta prefix, calorie balance and adherence tooltips, actual/target legend labels, daily expenditure prefix, height/birth/weight setup hint, exercise/workout/recent labels, "starts with", and a {n}-template "X days ago" string. URL slug ternaries (e.g. 'check-in' / 'erfassung') remain inline since they encode route data, not UI text. Bump site version to 1.56.2. --- package.json | 2 +- .../components/fitness/TemplateCard.svelte | 4 +-- src/lib/i18n/fitness/de.ts | 26 +++++++++++++++ src/lib/i18n/fitness/en.ts | 26 +++++++++++++++ .../[checkin=fitnessCheckIn]/+page.svelte | 32 +++++++++---------- .../body-parts/+page.svelte | 2 +- .../[exercises=fitnessExercises]/+page.svelte | 2 +- .../[id]/+page.svelte | 6 ++-- .../[[month=fitnessMonth]]/+page.svelte | 2 +- .../[id]/+page.svelte | 2 +- .../fitness/[stats=fitnessStats]/+page.svelte | 22 ++++--------- .../[part]/+page.svelte | 2 +- .../[workout=fitnessWorkout]/+page.svelte | 4 +-- .../[active=fitnessActive]/+page.svelte | 2 +- 14 files changed, 88 insertions(+), 46 deletions(-) diff --git a/package.json b/package.json index da0e1d59..a2884450 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "homepage", - "version": "1.56.1", + "version": "1.56.2", "private": true, "type": "module", "scripts": { diff --git a/src/lib/components/fitness/TemplateCard.svelte b/src/lib/components/fitness/TemplateCard.svelte index 86f1beef..d8de5070 100644 --- a/src/lib/components/fitness/TemplateCard.svelte +++ b/src/lib/components/fitness/TemplateCard.svelte @@ -26,8 +26,8 @@ const diffDays = Math.floor(diffMs / 86400000); if (diffDays === 0) return t.today; if (diffDays === 1) return t.yesterday; - if (diffDays < 7) return lang === 'en' ? `${diffDays} days ago` : `vor ${diffDays} Tagen`; - return d.toLocaleDateString(lang === 'en' ? 'en' : 'de', { month: 'short', day: 'numeric' }); + if (diffDays < 7) return t.days_ago_template.replace('{n}', String(diffDays)); + return d.toLocaleDateString(lang, { month: 'short', day: 'numeric' }); } diff --git a/src/lib/i18n/fitness/de.ts b/src/lib/i18n/fitness/de.ts index a3cfce5c..2b98e90c 100644 --- a/src/lib/i18n/fitness/de.ts +++ b/src/lib/i18n/fitness/de.ts @@ -363,4 +363,30 @@ export const de = { sugars: "Zucker", source_db: "Quelle", initializing_gps: "GPS wird initialisiert…", + + // Check-in page + failed_to_load_more: "Laden fehlgeschlagen", + body_part_count_one: "1 Körperteil", + body_parts_count_other: "Körperteile", + updated_toast: "Aktualisiert", + body_fat_label: "Körperfett", + clear_action: "Leeren", + measure_short: "Messen", + edit_all_fields: "Alle Felder bearbeiten", + measurement_saved: "Messung gespeichert", + + // Stats page + bf_delta_from_prefix: "Δ von", + set_height_birthyear_weight: "Größe, Geburtsjahr & Gewicht eintragen", + actual_label: "Ist", + target_label: "Ziel", + calorie_balance_tooltip: "Durchschnittlich gegessene Kalorien minus geschätzter Verbrauch (TDEE + erfasste Trainingskilokalorien) der letzten 7 Tage. Negativ = Defizit, positiv = Überschuss.", + daily_expenditure_estimate_prefix: "Geschätzter Tagesverbrauch:", + diet_adherence_tooltip: "Prozent der Tage, an denen die gegessenen Kalorien innerhalb von ±10 % deines Ziels lagen (bereinigt um verbrannte Trainings­kalorien). Nicht erfasste Tage zählen als verfehlt.", + + // Misc page titles / labels + exercise_title: "Übung", + recent_label: "Aktuell", + starts_with: "beginnt mit", + days_ago_template: "vor {n} Tagen" } as const; diff --git a/src/lib/i18n/fitness/en.ts b/src/lib/i18n/fitness/en.ts index f03d61e4..2df1c7e6 100644 --- a/src/lib/i18n/fitness/en.ts +++ b/src/lib/i18n/fitness/en.ts @@ -363,4 +363,30 @@ export const en = { sugars: "Sugars", source_db: "Source", initializing_gps: "Initializing GPS…", + + // Check-in page + failed_to_load_more: "Failed to load more", + body_part_count_one: "1 body part", + body_parts_count_other: "body parts", + updated_toast: "Updated", + body_fat_label: "Body Fat", + clear_action: "Clear", + measure_short: "Measure", + edit_all_fields: "Edit all fields", + measurement_saved: "Measurement saved", + + // Stats page + bf_delta_from_prefix: "Δ from", + set_height_birthyear_weight: "Set height, birth year & weight", + actual_label: "Actual", + target_label: "Target", + calorie_balance_tooltip: "Average daily calories eaten minus estimated expenditure (TDEE + tracked workout calories) over the last 7 days. Negative = deficit, positive = surplus.", + daily_expenditure_estimate_prefix: "Est. daily expenditure:", + diet_adherence_tooltip: "Percentage of days where calories eaten were within ±10% of your goal (adjusted for exercise calories burned). Days without tracking count as misses.", + + // Misc page titles / labels + exercise_title: "Exercise", + recent_label: "Recent", + starts_with: "starts with", + days_ago_template: "{n} days ago" } as const satisfies Record; diff --git a/src/routes/fitness/[checkin=fitnessCheckIn]/+page.svelte b/src/routes/fitness/[checkin=fitnessCheckIn]/+page.svelte index 516759db..14041763 100644 --- a/src/routes/fitness/[checkin=fitnessCheckIn]/+page.svelte +++ b/src/routes/fitness/[checkin=fitnessCheckIn]/+page.svelte @@ -136,10 +136,10 @@ measurements = [...measurements, ...fresh]; if (typeof body?.total === 'number') measurementsTotal = body.total; } else { - toast.error(lang === 'en' ? 'Failed to load more' : 'Laden fehlgeschlagen'); + toast.error(t.failed_to_load_more); } } catch { - toast.error(lang === 'en' ? 'Failed to load more' : 'Laden fehlgeschlagen'); + toast.error(t.failed_to_load_more); } loadingMore = false; } @@ -179,9 +179,7 @@ ? Object.values(m.measurements).filter((v) => v != null).length : 0; if (bpCount > 0) { - const en = bpCount === 1 ? '1 body part' : `${bpCount} body parts`; - const de = bpCount === 1 ? '1 Körperteil' : `${bpCount} Körperteile`; - parts.push(lang === 'en' ? en : de); + parts.push(bpCount === 1 ? t.body_part_count_one : `${bpCount} ${t.body_parts_count_other}`); } return parts.join(' · ') || t.no_measurements_yet; } @@ -293,7 +291,7 @@ const latestRes = await fetch('/api/fitness/measurements/latest'); if (latestRes.ok) latest = await latestRes.json(); } catch {} - toast.success(lang === 'en' ? 'Updated' : 'Aktualisiert'); + toast.success(t.updated_toast); editingId = null; } else { const err = await res.json().catch(() => null); @@ -356,10 +354,10 @@ return conflicts.map((c) => { let label = c.key; let unit = ''; - if (c.key === 'weight') { label = lang === 'en' ? 'Weight' : 'Gewicht'; unit = ' kg'; } - else if (c.key === 'bodyFatPercent') { label = lang === 'en' ? 'Body Fat' : 'Körperfett'; unit = ' %'; } - else if (c.key === 'caloricIntake') { label = lang === 'en' ? 'Calories' : 'Kalorien'; unit = ' kcal'; } - else if (c.key === 'notes') { label = lang === 'en' ? 'Notes' : 'Notizen'; } + if (c.key === 'weight') { label = t.weight; unit = ' kg'; } + else if (c.key === 'bodyFatPercent') { label = t.body_fat_label; unit = ' %'; } + else if (c.key === 'caloricIntake') { label = t.calories; unit = ' kcal'; } + else if (c.key === 'notes') { label = t.notes; } else if (c.key.startsWith('measurements.')) { const part = c.key.slice('measurements.'.length); label = t[/** @type {FitnessKey} */ (partKeyMap[part] ?? part)]; @@ -408,7 +406,7 @@ measurementsTotal = measurementsTotal + 1; } resetForm(); - toast.success(lang === 'en' ? 'Measurement saved' : 'Messung gespeichert'); + toast.success(t.measurement_saved); } else { const err = await res.json().catch(() => null); toast.error(err?.error ?? 'Failed to save measurement'); @@ -418,7 +416,7 @@ } -{lang === 'en' ? 'Measure' : 'Messen'} - Bocken +{t.measure_short} - Bocken

{t.measure_title}

@@ -504,10 +502,10 @@
- + {#if formWeight} {/if} @@ -535,10 +533,10 @@ - + {#if formBodyFat} {/if} @@ -638,7 +636,7 @@
- {lang === 'en' ? 'Edit all fields' : 'Alle Felder bearbeiten'} + {t.edit_all_fields} {#if showBalanceInfo}
- {lang === 'en' - ? 'Average daily calories eaten minus estimated expenditure (TDEE + tracked workout calories) over the last 7 days. Negative = deficit, positive = surplus.' - : 'Durchschnittlich gegessene Kalorien minus geschätzter Verbrauch (TDEE + erfasste Trainingskilokalorien) der letzten 7 Tage. Negativ = Defizit, positiv = Überschuss.'} + {t.calorie_balance_tooltip} {#if ns.avgDailyExpenditure} - {lang === 'en' - ? `Est. daily expenditure: ~${ns.avgDailyExpenditure} kcal` - : `Geschätzter Tagesverbrauch: ~${ns.avgDailyExpenditure} kcal`} + {t.daily_expenditure_estimate_prefix} ~{ns.avgDailyExpenditure} kcal {/if}
{/if} @@ -436,7 +430,7 @@ {#if ns.avgCalorieBalance != null} {t.seven_day_avg} {:else if !hasDemographics || !ns.trendWeight} - {lang === 'en' ? 'Set height, birth year & weight' : 'Größe, Geburtsjahr & Gewicht eintragen'} + {t.set_height_birthyear_weight} {:else} {t.no_nutrition_data} {/if} @@ -455,9 +449,7 @@ {#if showAdherenceInfo}
- {lang === 'en' - ? 'Percentage of days where calories eaten were within ±10% of your goal (adjusted for exercise calories burned). Days without tracking count as misses.' - : 'Prozent der Tage, an denen die gegessenen Kalorien innerhalb von ±10 % deines Ziels lagen (bereinigt um verbrannte Trainings\u00ADkalorien). Nicht erfasste Tage zählen als verfehlt.'} + {t.diet_adherence_tooltip}
{/if}
@@ -476,11 +468,11 @@
- {lang === 'en' ? 'Actual' : 'Ist'} + {t.actual_label} - {lang === 'en' ? 'Target' : 'Ziel'} + {t.target_label}
{#if !ns.macroSplit} diff --git a/src/routes/fitness/[stats=fitnessStats]/[history=fitnessHistory]/[part]/+page.svelte b/src/routes/fitness/[stats=fitnessStats]/[history=fitnessHistory]/[part]/+page.svelte index a3de945f..d687f53c 100644 --- a/src/routes/fitness/[stats=fitnessStats]/[history=fitnessHistory]/[part]/+page.svelte +++ b/src/routes/fitness/[stats=fitnessStats]/[history=fitnessHistory]/[part]/+page.svelte @@ -149,7 +149,7 @@ const hasData = $derived(series.dates.length > 0); -{t[card.labelKey]} · {lang === 'en' ? 'History' : 'Verlauf'} - Bocken +{t[card.labelKey]} · {t.history_title} - Bocken
diff --git a/src/routes/fitness/[workout=fitnessWorkout]/+page.svelte b/src/routes/fitness/[workout=fitnessWorkout]/+page.svelte index b970a316..92c3f1f4 100644 --- a/src/routes/fitness/[workout=fitnessWorkout]/+page.svelte +++ b/src/routes/fitness/[workout=fitnessWorkout]/+page.svelte @@ -401,7 +401,7 @@ } -{lang === 'en' ? 'Workout' : 'Training'} - Bocken +{t.workout_singular} - Bocken
{#if hasSchedule && nextTemplate} @@ -431,7 +431,7 @@ {nextTemplate.exercises.length} {nextTemplate.exercises.length !== 1 ? t.exercises_word : t.exercise} {#if firstExData} - · {lang === 'en' ? 'starts with' : 'beginnt mit'} {firstExData.localName} {#if firstExWeight != null}({firstExWeight} kg){/if} + · {t.starts_with} {firstExData.localName} {#if firstExWeight != null}({firstExWeight} kg){/if} {/if} {/if} diff --git a/src/routes/fitness/[workout=fitnessWorkout]/[active=fitnessActive]/+page.svelte b/src/routes/fitness/[workout=fitnessWorkout]/[active=fitnessActive]/+page.svelte index 12f2db2f..3bd70f38 100644 --- a/src/routes/fitness/[workout=fitnessWorkout]/[active=fitnessActive]/+page.svelte +++ b/src/routes/fitness/[workout=fitnessWorkout]/[active=fitnessActive]/+page.svelte @@ -976,7 +976,7 @@ - {workout.name || (lang === 'en' ? 'Workout' : 'Training')} - Bocken + {workout.name || t.workout_singular} - Bocken