From 343804b25ce44c464a2b9b7995e40b099f4bfde7 Mon Sep 17 00:00:00 2001 From: Till JS Date: Tue, 7 Apr 2026 18:23:58 +0200 Subject: [PATCH] refactor(cycles): make date formatting locale-aware Replace hardcoded 'de-DE' toLocaleDateString calls across ListView, CyclesWidget, and pure helpers with the active svelte-i18n locale. Pure helpers in queries.ts now take their locale (and for relative dates, their labels) as parameters so they stay pure and testable: - formatLogDate(iso, labels, dateLocale) - groupLogsByMonth(logs, dateLocale) - New RelativeDateLabels type, exported from the module barrel ListView builds relativeLabels from $_ and threads dateLocale through; CyclesWidget does the same using a tiny $locale-derived helper. New i18n keys cycles.relativeDate.{today,yesterday,daysAgo} across all five locales (real de/en translations, stubs for it/fr/es). Co-Authored-By: Claude Opus 4.6 (1M context) --- .../web/src/lib/i18n/locales/cycles/de.json | 5 +++ .../web/src/lib/i18n/locales/cycles/en.json | 5 +++ .../web/src/lib/i18n/locales/cycles/es.json | 5 +++ .../web/src/lib/i18n/locales/cycles/fr.json | 5 +++ .../web/src/lib/i18n/locales/cycles/it.json | 5 +++ .../modules/core/widgets/CyclesWidget.svelte | 9 +++-- .../src/lib/modules/cycles/ListView.svelte | 26 ++++++++++++--- .../apps/web/src/lib/modules/cycles/index.ts | 1 + .../web/src/lib/modules/cycles/queries.ts | 33 ++++++++++++++----- 9 files changed, 79 insertions(+), 15 deletions(-) diff --git a/apps/mana/apps/web/src/lib/i18n/locales/cycles/de.json b/apps/mana/apps/web/src/lib/i18n/locales/cycles/de.json index 84e70857d..178d2a5fa 100644 --- a/apps/mana/apps/web/src/lib/i18n/locales/cycles/de.json +++ b/apps/mana/apps/web/src/lib/i18n/locales/cycles/de.json @@ -57,6 +57,11 @@ "nextPeriod": "Nächste Periode:", "fertileWindow": "Fruchtbares Fenster:" }, + "relativeDate": { + "today": "Heute", + "yesterday": "Gestern", + "daysAgo": "vor {days} Tagen" + }, "empty": "Tippe oben auf eine Blutungsstärke, um deinen ersten Tag festzuhalten — oder starte direkt eine Periode.", "confirm": { "deleteEntry": "Tageseintrag vom {date} wirklich löschen?", diff --git a/apps/mana/apps/web/src/lib/i18n/locales/cycles/en.json b/apps/mana/apps/web/src/lib/i18n/locales/cycles/en.json index 7a5bee423..4ab7c1d15 100644 --- a/apps/mana/apps/web/src/lib/i18n/locales/cycles/en.json +++ b/apps/mana/apps/web/src/lib/i18n/locales/cycles/en.json @@ -57,6 +57,11 @@ "nextPeriod": "Next period:", "fertileWindow": "Fertile window:" }, + "relativeDate": { + "today": "Today", + "yesterday": "Yesterday", + "daysAgo": "{days} days ago" + }, "empty": "Tap a flow level above to log your first day — or start a period directly.", "confirm": { "deleteEntry": "Really delete the entry from {date}?", diff --git a/apps/mana/apps/web/src/lib/i18n/locales/cycles/es.json b/apps/mana/apps/web/src/lib/i18n/locales/cycles/es.json index 7a5bee423..4ab7c1d15 100644 --- a/apps/mana/apps/web/src/lib/i18n/locales/cycles/es.json +++ b/apps/mana/apps/web/src/lib/i18n/locales/cycles/es.json @@ -57,6 +57,11 @@ "nextPeriod": "Next period:", "fertileWindow": "Fertile window:" }, + "relativeDate": { + "today": "Today", + "yesterday": "Yesterday", + "daysAgo": "{days} days ago" + }, "empty": "Tap a flow level above to log your first day — or start a period directly.", "confirm": { "deleteEntry": "Really delete the entry from {date}?", diff --git a/apps/mana/apps/web/src/lib/i18n/locales/cycles/fr.json b/apps/mana/apps/web/src/lib/i18n/locales/cycles/fr.json index 7a5bee423..4ab7c1d15 100644 --- a/apps/mana/apps/web/src/lib/i18n/locales/cycles/fr.json +++ b/apps/mana/apps/web/src/lib/i18n/locales/cycles/fr.json @@ -57,6 +57,11 @@ "nextPeriod": "Next period:", "fertileWindow": "Fertile window:" }, + "relativeDate": { + "today": "Today", + "yesterday": "Yesterday", + "daysAgo": "{days} days ago" + }, "empty": "Tap a flow level above to log your first day — or start a period directly.", "confirm": { "deleteEntry": "Really delete the entry from {date}?", diff --git a/apps/mana/apps/web/src/lib/i18n/locales/cycles/it.json b/apps/mana/apps/web/src/lib/i18n/locales/cycles/it.json index 7a5bee423..4ab7c1d15 100644 --- a/apps/mana/apps/web/src/lib/i18n/locales/cycles/it.json +++ b/apps/mana/apps/web/src/lib/i18n/locales/cycles/it.json @@ -57,6 +57,11 @@ "nextPeriod": "Next period:", "fertileWindow": "Fertile window:" }, + "relativeDate": { + "today": "Today", + "yesterday": "Yesterday", + "daysAgo": "{days} days ago" + }, "empty": "Tap a flow level above to log your first day — or start a period directly.", "confirm": { "deleteEntry": "Really delete the entry from {date}?", diff --git a/apps/mana/apps/web/src/lib/modules/core/widgets/CyclesWidget.svelte b/apps/mana/apps/web/src/lib/modules/core/widgets/CyclesWidget.svelte index 98a167936..b7b11f2b9 100644 --- a/apps/mana/apps/web/src/lib/modules/core/widgets/CyclesWidget.svelte +++ b/apps/mana/apps/web/src/lib/modules/core/widgets/CyclesWidget.svelte @@ -6,7 +6,7 @@ * + Vorhersage pro Render ab. Linkt zur /cycles Route. */ - import { _ } from 'svelte-i18n'; + import { _, locale } from 'svelte-i18n'; import { liveQuery } from 'dexie'; import { db } from '$lib/data/database'; import { derivePhase, getCycleDayNumber } from '$lib/modules/cycles/utils/phase'; @@ -48,9 +48,14 @@ const daysUntil = $derived(daysUntilNextPeriod(cycles)); const nextPeriod = $derived(predictNextPeriodStart(cycles)); + const dateLocale = $derived.by(() => { + const l = $locale ?? 'de'; + return l === 'de' ? 'de-DE' : l; + }); + function formatShortDate(iso: string | null): string { if (!iso) return '—'; - return new Date(iso).toLocaleDateString('de-DE', { day: '2-digit', month: '2-digit' }); + return new Date(iso).toLocaleDateString(dateLocale, { day: '2-digit', month: '2-digit' }); } diff --git a/apps/mana/apps/web/src/lib/modules/cycles/ListView.svelte b/apps/mana/apps/web/src/lib/modules/cycles/ListView.svelte index 50d7749a4..56fe0fc2a 100644 --- a/apps/mana/apps/web/src/lib/modules/cycles/ListView.svelte +++ b/apps/mana/apps/web/src/lib/modules/cycles/ListView.svelte @@ -3,13 +3,14 @@ Aktueller Zyklus, heutiger Quick-Log, einfache Statistiken. -->