mirror of
https://github.com/MBombeck/HealthLog.git
synced 2026-11-08 20:42:43 +00:00
fix(medications): localise time-window range string
`formatTimeWindowRange` used to hard-code the German "bis ... Uhr" suffix, so an English-locale user saw "Today, 19:00 bis 23:00 Uhr" on the medication card and the medication form. Pass the active locale through and emit "19:00 – 23:00" for English while keeping the existing German output for DE users (and unchanged for legacy call sites that still don't pass a locale). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
1 parent
79ad5c47a9
commit
180f46c24e
4 files changed
+74
-8
No files matched your search
@@ -193,7 +193,7 @@ function isLastIntakeInCurrentWindow(
|
||||
|
||||
export function MedicationCard({ medication, onEdit }: MedicationCardProps) {
|
||||
const queryClient = useQueryClient();
|
||||
const { t } = useTranslations();
|
||||
const { t, locale } = useTranslations();
|
||||
const fmt = useFormatters();
|
||||
const [intakeLoading, setIntakeLoading] = useState<string | null>(null);
|
||||
|
||||
@@ -438,6 +438,7 @@ export function MedicationCard({ medication, onEdit }: MedicationCardProps) {
|
||||
{formatTimeWindowRange(
|
||||
currentWindowStatus.schedule!.windowStart,
|
||||
currentWindowStatus.schedule!.windowEnd,
|
||||
locale,
|
||||
)}
|
||||
</span>
|
||||
</p>
|
||||
@@ -490,7 +491,7 @@ export function MedicationCard({ medication, onEdit }: MedicationCardProps) {
|
||||
{t("medications.nextIntake")}
|
||||
</span>{" "}
|
||||
{dayLabel && `${dayLabel}, `}
|
||||
{formatTimeWindowRange(s.windowStart, s.windowEnd)}
|
||||
{formatTimeWindowRange(s.windowStart, s.windowEnd, locale)}
|
||||
{s.label && (
|
||||
<span className="hidden sm:inline"> ({s.label})</span>
|
||||
)}
|
||||
|
||||
@@ -131,16 +131,17 @@ function formatNextWindowSummary(
|
||||
schedule: Schedule,
|
||||
t: TranslateFn,
|
||||
formatShortDate: (date: Date) => string,
|
||||
locale: "de" | "en",
|
||||
): string {
|
||||
const isSimpleDaily =
|
||||
schedule.daysOfWeek.length === 0 && schedule.intervalWeeks === 1;
|
||||
if (isSimpleDaily) {
|
||||
return `${t("medications.nextSchedulePrefix")} ${t("medications.nextScheduleDaily")}, ${formatTimeWindowRange(schedule.windowStart, schedule.windowEnd)}`;
|
||||
return `${t("medications.nextSchedulePrefix")} ${t("medications.nextScheduleDaily")}, ${formatTimeWindowRange(schedule.windowStart, schedule.windowEnd, locale)}`;
|
||||
}
|
||||
|
||||
const nextDate = getNextRecurrenceDate(schedule);
|
||||
const nextText = nextDate
|
||||
? `${formatShortDate(nextDate)}, ${formatTimeWindowRange(schedule.windowStart, schedule.windowEnd)}`
|
||||
? `${formatShortDate(nextDate)}, ${formatTimeWindowRange(schedule.windowStart, schedule.windowEnd, locale)}`
|
||||
: "—";
|
||||
return `${t("medications.nextSchedulePrefix")} ${nextText}`;
|
||||
}
|
||||
@@ -234,7 +235,7 @@ export function MedicationForm({
|
||||
initial,
|
||||
}: MedicationFormProps) {
|
||||
const queryClient = useQueryClient();
|
||||
const { t } = useTranslations();
|
||||
const { t, locale } = useTranslations();
|
||||
const fmt = useFormatters();
|
||||
|
||||
const doseUnits = [
|
||||
@@ -565,7 +566,7 @@ export function MedicationForm({
|
||||
`${t("medications.formSchedule")} ${i + 1}`}
|
||||
</span>{" "}
|
||||
<span className="text-foreground/70 font-normal">
|
||||
({formatNextWindowSummary(s, t, fmt.dateShort)})
|
||||
({formatNextWindowSummary(s, t, fmt.dateShort, locale)})
|
||||
</span>
|
||||
</p>
|
||||
<DropdownMenu>
|
||||
|
||||
@@ -0,0 +1,44 @@
|
||||
import { describe, expect, test } from "vitest";
|
||||
|
||||
import {
|
||||
formatTimeWindowPart,
|
||||
formatTimeWindowRange,
|
||||
} from "@/lib/time-window-format";
|
||||
|
||||
describe("formatTimeWindowPart", () => {
|
||||
test("zero-pads single-digit hours", () => {
|
||||
expect(formatTimeWindowPart("8:00")).toBe("08:00");
|
||||
});
|
||||
|
||||
test("preserves two-digit hours", () => {
|
||||
expect(formatTimeWindowPart("19:30")).toBe("19:30");
|
||||
});
|
||||
|
||||
test("returns input unchanged when not a HH:MM string", () => {
|
||||
expect(formatTimeWindowPart("invalid")).toBe("invalid");
|
||||
});
|
||||
});
|
||||
|
||||
describe("formatTimeWindowRange", () => {
|
||||
test("German locale renders 'bis ... Uhr' (default behaviour preserved)", () => {
|
||||
expect(formatTimeWindowRange("19:00", "23:00", "de")).toBe(
|
||||
"19:00 bis 23:00 Uhr",
|
||||
);
|
||||
});
|
||||
|
||||
test("English locale renders 'from ... to ...' instead of mixed-language 'bis Uhr'", () => {
|
||||
// Regression for v1.4.19 F-01: app rendered "Today, 19:00 bis 23:00 Uhr"
|
||||
// for English users because the formatter hard-coded German.
|
||||
expect(formatTimeWindowRange("19:00", "23:00", "en")).toBe(
|
||||
"19:00 – 23:00",
|
||||
);
|
||||
});
|
||||
|
||||
test("falls back to the German format when no locale is supplied", () => {
|
||||
// Backwards-compat: existing call sites that have not been migrated
|
||||
// continue to render the historic German string.
|
||||
expect(formatTimeWindowRange("08:00", "12:00")).toBe(
|
||||
"08:00 bis 12:00 Uhr",
|
||||
);
|
||||
});
|
||||
});
|
||||
@@ -6,6 +6,26 @@ export function formatTimeWindowPart(value: string): string {
|
||||
return `${hh}:${mm}`;
|
||||
}
|
||||
|
||||
export function formatTimeWindowRange(start: string, end: string): string {
|
||||
return `${formatTimeWindowPart(start)} bis ${formatTimeWindowPart(end)} Uhr`;
|
||||
/**
|
||||
* Render a daily intake time window like "08:00 bis 12:00 Uhr" / "08:00 – 12:00".
|
||||
*
|
||||
* The historic call sites (see `medication-card.tsx`, `medication-form.tsx`)
|
||||
* never passed a locale, so the renderer hard-coded the German "bis ... Uhr"
|
||||
* suffix and the English locale ended up with mixed-language strings such as
|
||||
* `"Today, 19:00 bis 23:00 Uhr"`. Pass the active UI locale so that the right
|
||||
* separator + suffix are picked. When no locale is provided we keep the
|
||||
* legacy German output for backwards compatibility with any consumer we may
|
||||
* have missed.
|
||||
*/
|
||||
export function formatTimeWindowRange(
|
||||
start: string,
|
||||
end: string,
|
||||
locale?: "de" | "en",
|
||||
): string {
|
||||
const s = formatTimeWindowPart(start);
|
||||
const e = formatTimeWindowPart(end);
|
||||
if (locale === "en") {
|
||||
return `${s} – ${e}`;
|
||||
}
|
||||
return `${s} bis ${e} Uhr`;
|
||||
}
|
||||
Reference in new issue
Block a user