From d3e8f3143a7a745b03def803d4b5bcbd618ba7e7 Mon Sep 17 00:00:00 2001 From: Nicolas Varrot Date: Fri, 13 Feb 2026 15:11:39 +0000 Subject: [PATCH] fix: sync html lang attribute with i18n locale selection - Set document.documentElement.lang on initial load and locale change - Ensures screen readers and browser features respect the active language - Removes duplicate aria-label on MessageSearch input --- src/components/MessageSearch.tsx | 2 +- src/lib/i18n.ts | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/src/components/MessageSearch.tsx b/src/components/MessageSearch.tsx index 3c3f6e7..958b134 100644 --- a/src/components/MessageSearch.tsx +++ b/src/components/MessageSearch.tsx @@ -62,8 +62,8 @@ export function MessageSearch({ open, onClose, onSearch, matchCount }: Props) { onChange={e => setQuery(e.target.value)} onKeyDown={handleKeyDown} placeholder={t('search.placeholder')} - className="bg-transparent text-sm text-pc-text placeholder:text-pc-text-muted outline-none w-48" aria-label={t('search.placeholder')} + className="bg-transparent text-sm text-pc-text placeholder:text-pc-text-muted outline-none w-48" /> {query && ( diff --git a/src/lib/i18n.ts b/src/lib/i18n.ts index 65c474c..e580a06 100644 --- a/src/lib/i18n.ts +++ b/src/lib/i18n.ts @@ -277,6 +277,9 @@ function resolveInitialLocale(): string { let currentLocale = resolveInitialLocale(); let dict = messages[currentLocale] || messages.en; +// Sync on initial load +try { document.documentElement.lang = currentLocale; } catch { /* SSR */ } + type Listener = () => void; const listeners = new Set(); @@ -297,6 +300,7 @@ export function setLocale(loc: string): void { currentLocale = loc; dict = messages[loc]; try { localStorage.setItem(STORAGE_KEY, loc); } catch { /* noop */ } + try { document.documentElement.lang = loc; } catch { /* SSR */ } listeners.forEach((fn) => fn()); }