Localization that just works at runtime.
A lightweight i18n library for React. Switch languages instantly, fall back gracefully when a
translation is missing, detect browser locales, and persist language preferences with configurable storage —
all while keeping components in sync with useSyncExternalStore, with no external localization dependencies required.
Atum Localization
Small API. Real-time updates. Zero bloat.
Everything the library does, and nothing it makes you carry.
Runtime language switching
Call setLanguage() anywhere in the tree and every connected component updates immediately.
Fallback language support
Missing a key in the active locale? It resolves from the configured fallback before giving up.
React Context integration
One provider at the root. Every hook downstream reads from the same localization instance.
TypeScript support
Ships with full type declarations, so resources and options are checked as you write them.
No external i18n deps
No gettext, no ICU parser, no locale-data bundle. Just your own resource objects.
Built on useSyncExternalStore
Subscriptions are handled the way React itself recommends for external state — efficient by default.
Browser language detection
Detect the user's browser locale automatically and match regional locales before falling back to the base language.
Language persistence
Persist the selected language with LocalStorage, SessionStorage, or disable persistence when you do not need it.
Configurable storage key
Use the default storage key or provide your own key for language persistence.
Six steps to a localized app
The order matters here — each step builds on the last.
Create translation resources
Plain objects, one per language. Keys are whatever you want — SCREAMING_CASE keeps them easy to spot in JSX.
locales/en.tsexport default { TITLE: "Atum Localization", LOGIN: "Login", SAVE: "Save", CANCEL: "Cancel", LANGUAGE: "Language", };
Create the localization instance
Wire your resources together with a default and a fallback language.
localization.tsimport { createLocalization } from "atum-localization"; import en from "./locales/en"; import ta from "./locales/ta"; export const localization = createLocalization({ defaultLanguage: "en", fallbackLanguage: "en", resources: { en, ta }, });
Enable language detection
Automatically detect the browser locale and persist an explicitly selected language using LocalStorage, SessionStorage, or no persistence.
localization.tsexport const localization = createLocalization({ defaultLanguage: "en", fallbackLanguage: "en", resources: { en, ta }, detection: { enabled: true, storage: "local", storageKey: "atum-localization-language", }, });
Detection priority: stored language → browser language → defaultLanguage. Regional locales try an exact match first, then the base language.
Wrap your application
Mount LocalizationProvider once, at the root.
main.tsximport { LocalizationProvider } from "atum-localization"; import { localization } from "./localization"; <LocalizationProvider localization={localization}> <App /> </LocalizationProvider>
Translate content
useTranslation() returns a t() function scoped to the current language.
Home.tsximport { useTranslation } from "atum-localization"; export default function Home() { const { t } = useTranslation(); return <h1>{t("TITLE")}</h1>; }
Change language
useLanguage() gives you the active language and a setter — this is what powers the demo above.
LanguageSelector.tsximport { useLanguage } from "atum-localization"; export default function LanguageSelector() { const { language, setLanguage } = useLanguage(); return ( <select value={language} onChange={e => setLanguage(e.target.value)}> <option value="en">English</option> <option value="ta">Tamil</option> </select> ); }
Everything the package exports
One factory function, one provider, two hooks.
createLocalization(options)
Creates a localization instance from your resources.
| Option | Type | Description |
|---|---|---|
| defaultLanguage | string | Initial app language |
| fallbackLanguage | string | Used when a key is missing |
| resources | LocalizationResources | Your translation objects |
| detection | LanguageDetectionOptions | Browser language detection and persistence configuration |
detection
Configures browser language detection and language persistence.
detection: { enabled: true, storage: "local", storageKey: "atum-localization-language", }
| Option | Type | Default | Description |
|---|---|---|---|
| enabled | boolean | false | Enables browser language detection and persistence |
| storage | "local" | "session" | "none" | "local" | Controls where the selected language is persisted |
| storageKey | string | "atum-localization-language" | Storage key used to persist the language |
LocalizationProvider
Provides the instance to the component tree via React Context.
<LocalizationProvider localization={localization}> <App /> </LocalizationProvider>
useTranslation()
Returns the translation function bound to the active language.
const { t } = useTranslation(); t("LOGIN"); // → "Login"
useLanguage()
Returns the current language and a function to change it.
const { language, setLanguage } = useLanguage(); setLanguage("ta");
Missing a translation? Nothing breaks.
If a key isn't found in the active language, atum-localization looks in the fallback language. Still nothing? It returns the key itself, so your UI stays legible instead of blank.