'use client'; import { useState, useRef, useEffect } from 'react'; import { LOCALES, LOCALE_META, LOCALE_COOKIE, Locale } from '@/lib/locales'; import { useLocale } from '@/contexts/LocaleContext'; /** * Locale switcher (Session 12). * * Compact dropdown. Mounted alongside the BETA tag in Nav. On select, * writes the NEXT_LOCALE cookie (Path=/, 1-year expiry) and reloads * the page so the middleware picks up the new locale and the server * components rebuild with the new translations. * * SSR-safe: renders the current locale label before any state mutates * so hydration matches. */ export default function LocaleSwitcher() { const { locale } = useLocale(); const [open, setOpen] = useState(false); const containerRef = useRef(null); useEffect(() => { if (!open) return; function onDocClick(e: MouseEvent) { if (containerRef.current && !containerRef.current.contains(e.target as Node)) { setOpen(false); } } document.addEventListener('mousedown', onDocClick); return () => document.removeEventListener('mousedown', onDocClick); }, [open]); function pick(next: Locale) { setOpen(false); if (next === locale) return; // 1-year cookie, root path, lax so server-side reads survive // cross-origin navigations (Stripe redirect, OAuth callback). const oneYear = 60 * 60 * 24 * 365; document.cookie = `${LOCALE_COOKIE}=${next}; Path=/; Max-Age=${oneYear}; SameSite=Lax`; // Hard reload so the middleware picks up the cookie and server // components rebuild. Soft router.refresh() would leave the // initial server-rendered locale stale on this page. window.location.reload(); } const current = LOCALE_META[locale]; return (
{open && ( )}
); }