fix(forms): hint browser locale on date and datetime inputs

Native `<input type="date">` and `<input type="datetime-local">`
were rendering `mm/dd/yyyy` even when the German locale was
active, because Chromium picks the input's locale from the
nearest `lang` attribute on the element rather than from
`<html lang>`. Pass `lang={locale}` on every date/datetime input
in the app — onboarding DOB, account DOB, export filters,
doctor-report range, measurement / medication / mood timestamp
fields — so DE users now see `TT.MM.JJJJ`. Display formatting
already routed through `useFormatters()`; this closes the form
half of the same gap.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Marc-André BombeckandClaude Opus 4.7 committed 2026-05-10 13:36:23 +02:00
1 parent 7a6bc812c9
commit ff6e18473a
9 files changed
+21 -7

No files matched your search

+1
View File
@@ -304,6 +304,7 @@ export default function OnboardingPage() {
<Input
id="ob-dob"
type="date"
lang={locale}
value={dateOfBirth}
onChange={(e) => setDateOfBirth(e.target.value)}
max={new Date().toISOString().slice(0, 10)}
@@ -80,7 +80,7 @@ export function DoctorReportDialog({
defaultPracticeName,
onSubmit,
}: DoctorReportDialogProps) {
const { t } = useTranslations();
const { t, locale } = useTranslations();
const [startDate, setStartDate] = useState<string>(defaultStartIso);
const [endDate, setEndDate] = useState<string>(todayIso);
const [practiceName, setPracticeName] = useState<string>("");
@@ -194,6 +194,7 @@ export function DoctorReportDialog({
<Input
id="dr-start"
type="date"
lang={locale}
value={startDate}
max={endDate || todayIso()}
onChange={(e) => {
@@ -210,6 +211,7 @@ export function DoctorReportDialog({
<Input
id="dr-end"
type="date"
lang={locale}
value={endDate}
min={startDate}
max={todayIso()}
@@ -117,7 +117,7 @@ export function MeasurementForm({
onCancel,
defaultType,
}: MeasurementFormProps) {
const { t } = useTranslations();
const { t, locale } = useTranslations();
const queryClient = useQueryClient();
// Normalize legacy BP types to combined mode
@@ -361,6 +361,7 @@ export function MeasurementForm({
<Input
id="measuredAt"
type="datetime-local"
lang={locale}
value={measuredAt}
onChange={(e) => setMeasuredAt(e.target.value)}
required
@@ -105,7 +105,7 @@ function toDateTimeLocalValue(isoString: string): string {
}
export function MeasurementList({ onEdit, onAddFirst }: MeasurementListProps) {
const { t } = useTranslations();
const { t, locale } = useTranslations();
const fmt = useFormatters();
const { isAuthenticated } = useAuth();
const queryClient = useQueryClient();
@@ -562,6 +562,7 @@ export function MeasurementList({ onEdit, onAddFirst }: MeasurementListProps) {
<Input
id="edit-measuredAt"
type="datetime-local"
lang={locale}
value={editMeasuredAt}
onChange={(e) => setEditMeasuredAt(e.target.value)}
required
@@ -95,7 +95,7 @@ export function IntakeHistoryList({
}: IntakeHistoryListProps) {
const { isAuthenticated } = useAuth();
const queryClient = useQueryClient();
const { t } = useTranslations();
const { t, locale } = useTranslations();
const sourceLabels: Record<string, string> = {
WEB: t("medications.sourceWeb"),
@@ -545,6 +545,7 @@ export function IntakeHistoryList({
<Input
id="edit-scheduledFor"
type="datetime-local"
lang={locale}
value={editScheduledFor}
onChange={(e) => setEditScheduledFor(e.target.value)}
required
@@ -558,6 +559,7 @@ export function IntakeHistoryList({
<Input
id="edit-takenAt"
type="datetime-local"
lang={locale}
value={editTakenAt}
onChange={(e) => setEditTakenAt(e.target.value)}
disabled={editSkipped}
@@ -689,6 +691,7 @@ export function IntakeHistoryList({
<Input
id="create-scheduledFor"
type="datetime-local"
lang={locale}
value={createScheduledFor}
onChange={(e) => setCreateScheduledFor(e.target.value)}
required
@@ -702,6 +705,7 @@ export function IntakeHistoryList({
<Input
id="create-takenAt"
type="datetime-local"
lang={locale}
value={createTakenAt}
onChange={(e) => setCreateTakenAt(e.target.value)}
disabled={createSkipped}
+2 -1
View File
@@ -37,7 +37,7 @@ function getDefaultMoodLoggedAtValue() {
}
export function MoodForm({ onSuccess, onCancel }: MoodFormProps) {
const { t } = useTranslations();
const { t, locale } = useTranslations();
const queryClient = useQueryClient();
const [mood, setMood] = useState("");
@@ -135,6 +135,7 @@ export function MoodForm({ onSuccess, onCancel }: MoodFormProps) {
<Input
id="mood-logged-at"
type="datetime-local"
lang={locale}
value={moodLoggedAt}
onChange={(e) => setMoodLoggedAt(e.target.value)}
required
+2 -1
View File
@@ -117,7 +117,7 @@ interface MoodListProps {
}
export function MoodList({ onAddFirst }: MoodListProps = {}) {
const { t } = useTranslations();
const { t, locale } = useTranslations();
const fmt = useFormatters();
const { isAuthenticated } = useAuth();
const queryClient = useQueryClient();
@@ -572,6 +572,7 @@ export function MoodList({ onAddFirst }: MoodListProps = {}) {
<Input
id="edit-mood-logged-at"
type="datetime-local"
lang={locale}
value={editMoodLoggedAt}
onChange={(e) => setEditMoodLoggedAt(e.target.value)}
required
@@ -386,6 +386,7 @@ export function AccountSection() {
<Input
id="dob"
type="date"
lang={locale}
value={dateOfBirth}
onChange={(e) => setDateOfBirth(e.target.value)}
max={new Date().toISOString().slice(0, 10)}
+3 -1
View File
@@ -253,7 +253,7 @@ function DateRangeFields({
setUntil,
idPrefix,
}: DateRangeFieldsProps) {
const { t } = useTranslations();
const { t, locale } = useTranslations();
return (
<div className="grid grid-cols-1 gap-3 sm:grid-cols-2">
<div className="space-y-1.5">
@@ -263,6 +263,7 @@ function DateRangeFields({
<Input
id={`${idPrefix}-since`}
type="date"
lang={locale}
value={since}
onChange={(e) => setSince(e.target.value)}
max={until || undefined}
@@ -275,6 +276,7 @@ function DateRangeFields({
<Input
id={`${idPrefix}-until`}
type="date"
lang={locale}
value={until}
onChange={(e) => setUntil(e.target.value)}
min={since || undefined}