Overview

React + Next.js i18n runtime SDK for the api18n translation manager.

@api18n/react is the runtime layer of api18n. It reads the JSON files the CLI pulled into your repo and renders translated strings in your app — with ICU plurals, date / number formatting, rich tag interpolation, and fully typed t() calls.

What it does

  • Renders translations with useTranslations() in client components and getTranslations() in server components.
  • Switches locales via setLocale() — a plain function callable from anywhere (event handlers, route guards, even outside React).
  • Parses ICU MessageFormat at runtime: plurals, selects, dates, numbers, and rich tags map directly to React components.
  • Types every key via the messages.d.ts the CLI generates. Wrong key, missing arg, wrong arg type — all fail TypeScript.

What it doesn't do

  • No Provider in your JSX. Init is a side-effect import; components just call useTranslations(). The singleton handles state via useSyncExternalStore under the hood.
  • No automatic locale detection. The SDK doesn't read cookies or Accept-Language headers on its own. For Next.js App Router, use the detectLocale helper in @api18n/react/next and wire it through your middleware.
  • No translation fetching at runtime. The SDK reads the JSON your CLI already pulled — no network requests, no hydration delays.

Why singleton (no Provider)

Most React i18n libraries ask you to wrap your app in a <Provider> and prop-drill locale through context. Modern apps with deep server / client component trees make this awkward. Singleton state with useSyncExternalStore is:

  • Less boilerplate. One init file, side-effect import, done.
  • Faster re-renders. Only components that actually called useTranslations() re-render on setLocale — not the whole tree.
  • Server-safe. The /server entry uses React's cache() so per-request locale doesn't leak between concurrent requests.

Quickstart

// src/api18n.ts
import { createApi18n } from '@api18n/react';
import en from './messages/en.json';
import ptBR from './messages/pt-BR.json';

export const api18n = createApi18n({
  resources: { en, 'pt-BR': ptBR },
  defaultLocale: 'en',
});
// src/main.tsx (Vite/CRA)  — or  app/layout.tsx (Next.js)
import './api18n';
import { App } from './App';
import { useTranslations } from '@api18n/react';

export function Home() {
  const t = useTranslations();
  return <h1>{t('welcome', { name: 'Eduardo' })}</h1>;
}

That's the whole client-side surface. For Server Components, swap useTranslations for getTranslations from @api18n/react/server — walked through in Examples.

Next steps