3.9 KiB
<MissingKeyOverlay>
(no submodules)
Purpose
<MissingKeyOverlay> is a dev-mode visual diagnostic that surfaces every
missingKey event emitted by the active I18nInstance as a fixed-position
list anchored to the bottom-right corner of the viewport. The overlay
gives engineers a passive, always-on view of translation gaps as they
develop — no console-tab toggling, no debug flag, no polling. In
production builds the component renders null and registers no event
listener so it costs nothing once shipped.
Features
- Subscribes to
missingKeyevents on the Provider's instance bus - Renders a fixed-position list with
aria-live="polite"so screen readers announce new entries without focus theft - Caps retained entries at the most-recent
maxEntries(default 50); older entries silently drop off - Returns
nullin production (process.env.NODE_ENV === 'production') - Returns
nullwhen no Provider is mounted yet (no listener leak) - Ergonomic style defaults (monospace, dark background) plus per-entry locale and namespace meta
Usage: Basic Example
Mount the overlay once near the root of the application — it auto-tracks every miss for the lifetime of the active Provider:
import { TranslationProvider } from "@suaveplan/react-i18n";
import { MissingKeyOverlay } from "@suaveplan/react-i18n/components/missing-key-overlay";
<TranslationProvider config={i18nConfig}>
<App />
<MissingKeyOverlay />
</TranslationProvider>;
In dev, every t('absent.key') call appears in the overlay. In a
production bundle the component compiles to a no-op return.
Usage: Advanced Example
A custom cap with explicit prod override and a portal mount so the overlay sits in a dedicated DOM root:
import { createPortal } from "react-dom";
import { MissingKeyOverlay } from "@suaveplan/react-i18n/components/missing-key-overlay";
function DiagnosticsPortal() {
const root = document.getElementById("diagnostics-root");
if (!root) return null;
return createPortal(
<MissingKeyOverlay
// Force the overlay on even in a prod build for QA staging
production={false}
maxEntries={200}
/>,
root
);
}
API Reference
MissingKeyOverlay(props?: MissingKeyOverlayProps): ReactElement | null
Props:
maxEntries?: number— hard cap on retained entries. Default:50.production?: boolean— override for the runtime env-check. Whentrue, the component returnsnulland does not subscribe.
Returns: null in production, when no Provider ancestor is mounted, or
when no missingKey events have fired yet. Otherwise returns the
fixed-position overlay.
MissingKeyEntry
id: number— monotonically increasing counter (used as React key)key: string— the missing translation keylocale: string— locale at the moment the event was observednamespace: string— namespace label (empty string when no namespace)
Implementation Notes
- The component uses
useEffect(notuseSyncExternalStore) for the bus subscription because the entry list is a piece of internal React state driven by the bus rather than a snapshot of an external store. The two patterns are interchangeable here, anduseEffectis simpler to reason about for a buffer with bounded capacity. - The append-and-cap helper (
appendCapped) does the slice work outside the React update so the overlay never re-allocates the entire history on every event — only the bounded tail. - The fixed-position styles are applied inline so the overlay is self-contained: no external CSS file, no Tailwind dependency, no risk of the host app's stylesheet hiding it.
- The
productionprop exists to make the prod-path testable without mutatingprocess.env.NODE_ENV. The default readsisProductionEnv()on every render so consumers do not need to thread the flag through manually in their own builds.