Files
skills/docs/localization/i18n/react-i18n/src/hooks/use-locale-detection/detector-chain-context.md
2026-05-29 08:20:56 +01:00

3.6 KiB

DetectorChainContext

Purpose

DetectorChainContext is the React context that carries the configured locale-detector chain (plus any SSR-authoritative initialLocale) to descendants of <DetectorChainProvider>. It exists as a separate context from TranslationContext because the foundation <TranslationProvider> config schema does not yet expose a detectors field — splitting the surfaces lets the detector chain consumer (useLocaleDetection) read both contexts independently without forcing the foundation to know about detectors.

The default value is null so useLocaleDetection can throw a clear "used without <DetectorChainProvider>" error rather than silently no-op.

Features

  • null default value (lets the hook detect missing Provider)
  • displayName: "SuaveplanDetectorChainContext" for React DevTools

Usage: Basic Example

import { DetectorChainContext } from "@suaveplan/react-i18n/hooks/use-locale-detection/detector-chain-context";
import { useContext } from "react";

function CustomChainConsumer() {
    const config = useContext(DetectorChainContext);
    if (!config) throw new Error("missing DetectorChainProvider");
    return <span>{config.detectors.length} detectors registered</span>;
}

Usage: Advanced Example

import { DetectorChainContext } from "@suaveplan/react-i18n/hooks/use-locale-detection/detector-chain-context";
import { defaultDetectorChain } from "@suaveplan/react-i18n/detector/default-chain/default-chain";

// Bypass `<DetectorChainProvider>` for advanced cases (typically tests
// that need to inject a synthetic chain config without the provider's
// memoisation semantics).
function StaticChainScope(props: { children: ReactNode }) {
    return (
        <DetectorChainContext.Provider
            value={{
                detectors: defaultDetectorChain({ fallback: "en-GB" }),
            }}
        >
            {props.children}
        </DetectorChainContext.Provider>
    );
}

API Reference

DetectorChainContext: Context<DetectorChainConfig | null>

Standard React context; default value null. The associated config shape is DetectorChainConfig from ./use-locale-detection.types.ts:

interface DetectorChainConfig {
    readonly detectors: ReadonlyArray<LocaleDetector>;
    readonly buildContext?: () => DetectorContext;
    readonly initialLocale?: string;
    readonly initialSource?: string;
}

Implementation Notes

  • The context value is intentionally a plain config object (not a store) so React DevTools can introspect the registered detectors by name without needing the chain runner's internals. The configured detector list is therefore surface-visible via the React DevTools Components panel which makes diagnosing chain ordering issues during development a quick one-step inspection.
  • A null default plus an explicit hook-level error message is preferred over a constructed default (e.g. an empty chain) because the empty default would silently surface as "no detection ran" when the real failure is "Provider not mounted". Returning the empty array would also make tests pass that should fail (a consumer forgetting the Provider would still see an unresolved chain), so the null discriminator preserves a fail-loud contract during development.
  • The displayName set on the context surfaces in React DevTools as "SuaveplanDetectorChainContext" rather than the autogenerated Context.Provider/Context.Consumer placeholder. This makes multi-context trees easier to navigate and aligns with the display-name convention used by the foundation TranslationContext.