Installation
Install the SDK, wire up the init file, and render your first translation.
Install
npm install @api18n/react
# or
bun add @api18n/react
# or
pnpm add @api18n/reactreact is a peer dependency at version 18 or higher. The SDK works with
React 18, 19, and Next.js 14 / 15 / 16.
Pair with the CLI
Most setups pair the SDK with @api18n/cli, which generates the JSON
files the SDK reads:
npm install --save-dev @api18n/cliThen in your project root:
npx api18n init && npx api18n login && npx api18n pullThat writes messages/{locale}.json and messages/messages.d.ts. See
the CLI installation guide for the full flow.
Create the init file
This is the only place you'll touch the SDK setup. Conventionally
src/api18n.ts:
// 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',
fallbackLocale: 'en',
});createApi18n registers a singleton. After this runs, useTranslations(),
useLocale(), setLocale() all work anywhere in your app.
Dynamic imports for code-splitting
If you have many locales and want each one in its own chunk, dynamic- import them instead:
import { createApi18n } from '@api18n/react';
const en = (await import('./messages/en.json')).default;
export const api18n = createApi18n({
resources: { en },
defaultLocale: 'en',
});
export async function loadLocale(code: string) {
const messages = await import(`./messages/${code}.json`);
// Use the runtime helpers to merge — see API reference.
}Most apps with ≤ 8 locales eagerly import all of them: the parsed JSON is tiny (~10–50 KB gzipped per locale) and the cost of round-trip dynamic imports outweighs the bundle savings.
Mount the init file
The init file has to run before any component renders. Side-effect import it at the top of your entry point.
Vite / CRA
// src/main.tsx
import './api18n';
import { App } from './App';
createRoot(document.getElementById('root')!).render(<App />);Next.js App Router
// app/layout.tsx
import '../src/api18n';
export default function RootLayout({ children }: { children: React.ReactNode }) {
return (
<html lang="en">
<body>{children}</body>
</html>
);
}For mixed client / server component apps, you also call setRequestLocale
in the layout — see API reference: Server entry.
First component
// app/page.tsx (Next.js) or src/App.tsx (Vite)
'use client'; // only needed in Next.js App Router
import { useTranslations } from '@api18n/react';
export default function Home() {
const t = useTranslations();
return <h1>{t('welcome', { name: 'world' })}</h1>;
}Assuming messages/en.json has { "welcome": "Hello {name}" }, this
renders Hello world.
Enable type safety
With the CLI's typegen on, you'll have messages/messages.d.ts next to
your JSON files. Make sure TypeScript picks it up — either:
- Trust auto-discovery (TS finds
.d.tsfiles inincludepaths automatically), or - Add the path explicitly in
tsconfig.json:
{
"include": ["src", "messages/messages.d.ts"]
}Now t('helo', { name: 'x' }) fails with Argument of type '"helo"' is
not assignable to parameter of type 'TranslationKey', and missing args
fail the same way. Pull the CLI's messages.d.ts into PRs and your code
review starts catching i18n typos before they ship.