# useLocaleDetection _(no submodules)_ ## Purpose `useLocaleDetection` is the React surface that runs the configured locale-detector chain on mount and exposes the result to descendants. It works in tandem with `` (paired in this module) which carries the chain configuration and any SSR-authoritative `initialLocale`. The hook MUST be used inside both `` and `` — it reads the active i18n instance from the former and the chain detector list from the latter. The split lets the foundation `` remain decoupled from detector concerns (the config schema does not yet carry a `detectors` field — see Implementation Notes for the wiring story). ## Features - Runs the chain on mount and stores `{ detected, source, isPending }` - `redetect()` re-runs the chain (useful for switcher UIs and SSR override flows) - SSR contract: when `` is set, the chain is NOT auto-run on mount — `initialLocale` is treated as authoritative for the first render so client-side detectors do not produce a hydration mismatch - Calls `i18n.changeLanguage(detected)` automatically when the chain resolves to a different locale than the currently active one - Subscribes via `useSyncExternalStore` so multiple components reading the hook receive consistent state on the same commit ## Usage: Basic Example ```tsx import { DetectorChainProvider, useLocaleDetection, } from "@suaveplan/react-i18n/hooks/use-locale-detection/use-locale-detection"; import { defaultDetectorChain } from "@suaveplan/react-i18n/detector/default-chain/default-chain"; import { TranslationProvider } from "@suaveplan/react-i18n"; function App() { return ( ); } function Page() { const { detected, source, isPending, redetect } = useLocaleDetection(); if (isPending) return

Detecting…

; return (
Locale: {detected ?? "unknown"} (source: {source})
); } ``` ## Usage: Advanced Example ```tsx import { DetectorChainProvider } from "@suaveplan/react-i18n/hooks/use-locale-detection/use-locale-detection"; import { defaultDetectorChain } from "@suaveplan/react-i18n/detector/default-chain/default-chain"; // SSR scenario: pass `initialLocale` so the client-side detectors do // NOT auto-run on mount. The user can still call `redetect()` from a // switcher to override the SSR pick. export function SsrTree(props: { initialLocale: string; initialSource: string; children: ReactNode; }) { return ( ({ supportedLocales: ["en-GB", "fr-FR", "ar-AE"], fallbackLocale: "en-GB", })} > {props.children} ); } ``` ## API Reference ### `useLocaleDetection(): UseLocaleDetectionResult` Returns `{ detected, source, isPending, redetect }`. Throws when called outside `` OR ``. ### `` | Prop | Type | Description | | -------------- | -------------------------- | ---------------------------------------------------------- | | detectors | `LocaleDetector[]` (req) | Detectors fed to `createDetectorChain` | | buildContext | `() => DetectorContext` | Optional supplier producing a fresh context per chain run | | initialLocale | `string` | Authoritative SSR pick (skips auto-run on mount) | | initialSource | `string` | Optional detector name for the SSR pick | | children | `ReactNode` | Subtree rendered with the context in scope | ### `UseLocaleDetectionResult` ```ts interface UseLocaleDetectionResult { readonly detected: string | null; readonly source: string | null; readonly isPending: boolean; redetect(): Promise; } ``` ## Implementation Notes - The hook is split from `` because the foundation Provider's config schema does not yet expose a `detectors` field. Sub-wave 1c (`useLocale` / `setLocale`) and a future provider-level detector option will fold this surface into a single `` mount; until then the paired `` is the supported wiring. - The hook calls `i18n.changeLanguage(detected)` automatically when the chain resolves to a different locale than the active one. The Provider's bus subscriptions handle the resulting React commit. - `redetect()` always re-runs the chain — even after an SSR `initialLocale` was supplied — so a switcher-driven user action can override the SSR pick deterministically. - The internal store uses `useSyncExternalStore` directly (not React state) so concurrent renders observe a consistent snapshot of `{ detected, source, isPending }` across the commit. - Switcher-side persisting-detector walking (cookieDetector.cache, localStorageDetector.cache, userPreferenceDetector.cache) is the responsibility of the future `setLocale` surface (sub-wave 1c). Until that lands, ad-hoc consumers can call `createDetectorChain(detectors).cache(newLocale, ctx)` directly to exercise the same surface.