API reference
Every export of @api18n/react, what it does, and how to use it.
The SDK has three entry points:
import { createApi18n, useTranslations } from '@api18n/react'; // client
import { setRequestLocale, getTranslations } from '@api18n/react/server';
import { detectLocale } from '@api18n/react/next'; // optionalThe default @api18n/react import is what 90% of users need. /server is
opt-in for Next.js Server Components. /next is opt-in for Next.js
middleware.
Client API (@api18n/react)
createApi18n(options)
Initialises the singleton. Call once, in your init file.
function createApi18n(options: CreateApi18nOptions): Api18nInstance;
interface CreateApi18nOptions {
resources: Resources; // { [locale]: NestedMessages }
defaultLocale: string;
fallbackLocale?: string; // defaults to defaultLocale
}
interface Api18nInstance {
getLocale(): string;
setLocale(locale: string): void;
/** @internal */ _store: Api18nStore;
}Throws if resources is empty or defaultLocale isn't present in
resources.
useTranslations(namespace?)
Returns the t() function. Subscribed via useSyncExternalStore — only
re-renders the component when its locale's flat map changes.
function useTranslations(namespace?: string): TFunction;
// With Messages augmentation:
type TFunction = <K extends TranslationKey>(
key: K,
...args: HasArgs<ArgsFor<K>> extends true ? [ArgsFor<K>] : []
) => RenderResult<K>;
// Without augmentation (permissive fallback):
type TFunction = (key: string, args?: Args) => string | ReactNode[];The namespace argument is a prefix: useTranslations('checkout') makes
t('confirm') look up 'checkout.confirm'.
useLocale()
function useLocale(): string;Returns the active locale. Re-renders the calling component when locale changes.
setLocale(locale)
function setLocale(locale: string): void;Plain function — callable from event handlers, route guards, even
outside React. Notifies every component subscribed via useLocale or
useTranslations.
getLocale()
function getLocale(): string;One-shot read for non-React code (e.g., a fetch wrapper that wants the current locale).
useFormatter()
Locale-scoped wrappers for the standard Intl APIs.
function useFormatter(): Formatter;
interface Formatter {
number(value: number, options?: Intl.NumberFormatOptions): string;
dateTime(value: Date | number, options?: Intl.DateTimeFormatOptions): string;
relativeTime(
value: number,
unit: Intl.RelativeTimeFormatUnit,
options?: Intl.RelativeTimeFormatOptions,
): string;
list(items: Iterable<string>, options?: Intl.ListFormatOptions): string;
}Useful when you need to format a value that isn't keyed in your translation files — e.g., a transaction amount or a relative timestamp.
const f = useFormatter();
return <span>{f.number(1234.5, { style: 'currency', currency: 'USD' })}</span>;
// → "$1,234.50" in en, "US$ 1.234,50" in pt-BRServer API (@api18n/react/server)
setRequestLocale(locale)
Pins the locale for the current React cache() slot. Call this once in
your root layout (or in middleware) before any Server Component reads
translations.
import { setRequestLocale } from '@api18n/react/server';
export default async function Layout({ children, params }) {
const { locale } = await params;
setRequestLocale(locale);
return <html lang={locale}>{children}</html>;
}Behind the scenes, this uses React's cache() so the per-request locale
doesn't leak between concurrent requests during streaming SSR.
getTranslations(namespace?)
The Server Component equivalent of useTranslations. Async because it
resolves the per-request locale via cache().
async function getTranslations(namespace?: string): Promise<ServerTFunction>;import { getTranslations } from '@api18n/react/server';
export default async function Page() {
const t = await getTranslations();
return <h1>{t('welcome', { name: 'Eduardo' })}</h1>;
}Strings rendered by getTranslations arrive as plain HTML — zero client
JavaScript per string.
Next.js helper (@api18n/react/next)
detectLocale(url, headers, cookies, options)
Framework-agnostic locale detection for Next.js middleware.
function detectLocale(
url: URL,
headers: Headers,
cookies: { get(name: string): { value: string } | undefined },
options: {
locales: readonly string[];
defaultLocale: string;
cookieName?: string; // default: NEXT_LOCALE
},
): {
locale: string;
basePath: string;
hasLocalePrefix: boolean;
};Detection order:
- URL prefix —
/en/...,/pt-BR/...if the first segment matches a locale. - Cookie —
NEXT_LOCALE(or yourcookieName). Accept-Language— best-effort match, including base-language fallback.defaultLocaleas last resort.
Example wiring:
// middleware.ts
import { NextResponse } from 'next/server';
import { detectLocale } from '@api18n/react/next';
export function middleware(request: Request) {
const url = new URL(request.url);
const { locale, basePath, hasLocalePrefix } = detectLocale(
url,
request.headers,
request.cookies,
{
locales: ['en', 'pt-BR', 'de'],
defaultLocale: 'en',
},
);
if (!hasLocalePrefix) {
return NextResponse.redirect(new URL(`/${locale}${basePath}`, request.url));
}
return NextResponse.next();
}Type exports
import type {
Api18nInstance,
ArgsFor,
CreateApi18nOptions,
Formatter,
Messages, // augmentable interface
NestedMessages,
Resources,
TFunction,
TranslationKey,
} from '@api18n/react';Augmenting Messages
The CLI's messages.d.ts looks like:
import '@api18n/react';
declare module '@api18n/react' {
interface Messages {
'button.cancel': { __raw: 'Cancel' };
hello: { __raw: 'Hello {name}'; name: string | number };
'cart.items': {
__raw: '{count, plural, one {# item} other {# items}}';
count: number;
};
}
}Once the interface is augmented, TFunction switches from the permissive
fallback to the strict typed signature. Add messages.d.ts to
tsconfig.json's include array (or let TS auto-discover it) and your
editor will autocomplete keys and arg names.