From 38ada3bd4f9ca78b360f8ce24caf691f36fa1be6 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Ullrich=20Sch=C3=A4fer?=
Date: Sun, 29 Mar 2026 11:46:21 +0200
Subject: [PATCH] Pass full locale from Accept-Language to ClientDate
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Add detectLocale() that extracts the full locale tag (e.g. "de-DE")
from the request, not just the language. The journal root loader passes
it via LocaleContext so ClientDate renders with the correct locale on
both server and client — no more hardcoded "en-US" fallback.
Also fixes settings page hydration mismatch by using ClientDate for
passkey creation dates instead of inline toLocaleDateString().
Co-Authored-By: Claude Opus 4.6 (1M context)
---
apps/journal/app/components/ClientDate.tsx | 11 ++++++++---
apps/journal/app/components/LocaleContext.tsx | 17 +++++++++++++++++
apps/journal/app/root.tsx | 10 +++++++---
apps/journal/app/routes/settings.tsx | 6 +++---
packages/i18n/src/index.ts | 19 +++++++++++++++++++
5 files changed, 54 insertions(+), 9 deletions(-)
create mode 100644 apps/journal/app/components/LocaleContext.tsx
diff --git a/apps/journal/app/components/ClientDate.tsx b/apps/journal/app/components/ClientDate.tsx
index e2fcf06..0bbc775 100644
--- a/apps/journal/app/components/ClientDate.tsx
+++ b/apps/journal/app/components/ClientDate.tsx
@@ -1,11 +1,16 @@
import { useState, useEffect } from "react";
+import { useLocale } from "./LocaleContext";
/**
- * Renders a date only on the client to avoid SSR hydration mismatches.
- * Server renders empty, client fills in with user's locale.
+ * Renders a date using the server-detected locale for the initial render
+ * (matching SSR output), then updates to the browser's native locale
+ * after hydration.
*/
export function ClientDate({ iso }: { iso: string }) {
- const [formatted, setFormatted] = useState(new Date(iso).toLocaleDateString("en-US"));
+ const locale = useLocale();
+ const [formatted, setFormatted] = useState(
+ new Date(iso).toLocaleDateString(locale),
+ );
useEffect(() => {
setFormatted(new Date(iso).toLocaleDateString());
diff --git a/apps/journal/app/components/LocaleContext.tsx b/apps/journal/app/components/LocaleContext.tsx
new file mode 100644
index 0000000..15902c8
--- /dev/null
+++ b/apps/journal/app/components/LocaleContext.tsx
@@ -0,0 +1,17 @@
+import { createContext, useContext } from "react";
+
+const LocaleContext = createContext
- {t("settings.security.addedOn", {
- date: new Date(passkey.createdAt).toLocaleDateString(),
- })}
+ {t("settings.security.addedOn", { date: "" })}
+