Change locale
Implement a reactive language switcher. Learn how to utilize createLocaleProvider and setLocale to update routing and user preference states.
To allow users to switch languages, the header needs a language switcher that updates the URL, cookie, and router in one gesture. This guide explains how to wire createLocaleProvider and build a switcher with useLocaleContext.
Prerequisites
- Locale runtime
- TanStack Router — app wrapped in
RouterProvider - A hook that returns the active locale string from your message library (or route context)
Define the provider
TanStack i18n does not ship message catalogs. The provider reads locale from your hook and handles switching (persist, URL, router invalidate):
// src/i18n/provider.tsx
import { createLocaleProvider } from "@Wadiou/tanstack-i18n/react";
import { locale } from "../locale";
import { useLocale } from "./use-locale"; // wraps use-intl, route, etc.
export const { LocaleProvider, useLocaleContext } = createLocaleProvider({
runtime: locale,
useLocale,
});Mount LocaleProvider inside your root route layout (nested under your message provider and router). For the complete provider layout and nesting structure, see the use-intl integration guide.
Build the switcher
function LanguageSwitcher() {
const { locales, locale, setLocale } = useLocaleContext();
return (
<select
aria-label="Language"
value={locale}
onChange={(e) => void setLocale(e.target.value)}
>
{locales.map((code) => (
<option key={code} value={code}>
{code === "en" ? "English" : "العربية"}
</option>
))}
</select>
);
}useLocaleContext fields:
| Field | Source |
|---|---|
locale | Your useLocale hook |
locales | config.locales |
defaultLocale | config.defaultLocale |
setLocale | Provider — persist, URL, router invalidate |
What happens on setLocale("ar")
- No-op if already
ar - All persist adapters write (
LOCALEcookie, session if configured) - URL updates via
history.replaceState—/en/about→/ar/about(unless path ignored) router.invalidate()reloads loaders and your message hook picks upar
Browser only — call setLocale from event handlers, not loaders.
Flow details: persist writes in Adapters; resolution order in Behavior contract.
Solid marketing site
Same API from @Wadiou/tanstack-i18n/solid:
import { createLocaleProvider } from "@Wadiou/tanstack-i18n/solid";
export const { LocaleProvider, useLocaleContext } = createLocaleProvider({
runtime: locale,
useLocale,
});Types: CreateLocaleProviderDeps, LocaleContextValue.
How it works
TanStack i18n owns routing + persist. Your library owns strings — reload catalogs when locale changes via root beforeLoad. Full recipe: use-intl. Overview: Get started — locale vs messages.
Complete example (so far)
Header in marketing layout:
import { LanguageSwitcher } from "./LanguageSwitcher";
import { LocalizedLink } from "../i18n/routes";
function Header() {
return (
<header>
<LocalizedLink to="/">Home</LocalizedLink>
<LocalizedLink to="/about">About</LocalizedLink>
<LanguageSwitcher />
</header>
);
}API reference
createLocaleProvider({ runtime, useLocale })
Returns { LocaleProvider, useLocaleContext }. Mount LocaleProvider inside RouterProvider. Use setLocale from useLocaleContext in UI — not the core runtime directly.
What's next
Wire message catalogs: use-intl. Runtime guarantees: Behavior contract.
TanStack Router
Integrate TanStack i18n with TanStack Router. Set up localized route trees and configure type-safe navigation helpers like createNavigation.
Integrations
Integrate TanStack i18n routing with message and translation libraries. Explore guides for react-intl, use-intl, react-i18next, and Paraglide.