Better TranslateHome
GitHub
Getting Started
  • Introduction
  • Mission
  • Installation
  • CLI
  • Skills
  • RTL
  • Changelog
Adapters
  • Core
  • React
  • Expo
  • Astro
  • MD & MDX
  • Next.js
  • TanStack Router

React

Use @better-translate/react when React components need translations and locale switching.

1. Install the packages

npm install @better-translate/core @better-translate/react

2. Create the shared translator

Create src/i18n.ts:

ts
1import { configureTranslations } from "@better-translate/core";23const en = {4  home: {5    title: "Hello",6  },7} as const;89const es = {10  home: {11    title: "Hola",12  },13} as const;1415export const translator = await configureTranslations({16  availableLocales: ["en", "es"] as const,17  defaultLocale: "en",18  fallbackLocale: "en",19  messages: { en, es },20});

3. Wrap your app

Create or update src/main.tsx:

tsx
1import React from "react";2import ReactDOM from "react-dom/client";34import { BetterTranslateProvider } from "@better-translate/react";56import { App } from "./app";7import { translator } from "./i18n";89ReactDOM.createRoot(document.getElementById("root")!).render(10  <React.StrictMode>11    <BetterTranslateProvider translator={translator}>12      <App />13    </BetterTranslateProvider>14  </React.StrictMode>,15);

4. Read translations inside a component

Create src/header.tsx:

tsx
1import { useTranslations } from "@better-translate/react";23import { translator } from "./i18n";45export function Header() {6  const { locale, setLocale, t } = useTranslations<typeof translator>();78  return (9    <header>10      <h1>{t("home.title")}</h1>11      <button onClick={() => setLocale("en")} disabled={locale === "en"}>12        English13      </button>14      <button onClick={() => setLocale("es")} disabled={locale === "es"}>15        Espanol16      </button>17    </header>18  );19}

Optional: type useTranslations() once for the whole app

If you want plain useTranslations() to autocomplete your translation keys without repeating <typeof translator> in every component, add one declaration file:

Create src/better-translate.d.ts:

ts
1import { translator } from "./i18n";23declare module "@better-translate/react" {4  interface BetterTranslateReactTypes {5    translator: typeof translator;6  }7}

Then your components can call the hook without a generic:

tsx
1import { useTranslations } from "@better-translate/react";23export function Header() {4  const { locale, setLocale, t } = useTranslations();56  return (7    <header>8      <h1>{t("home.title")}</h1>9      <button onClick={() => setLocale("en")} disabled={locale === "en"}>10        English11      </button>12      <button onClick={() => setLocale("es")} disabled={locale === "es"}>13        Espanol14      </button>15    </header>16  );17}

Explicit generics still work, so you can keep using useTranslations<typeof translator>() where that fits your codebase better.

When to use React only

Use only @better-translate/core + @better-translate/react when:

  • your app is a React SPA
  • your app is an Expo app
  • locale changes happen in client components

If you are in Next.js App Router, keep this package for client hooks and add the Next.js adapter for routing and server helpers.

Generate locale files automatically

Instead of writing every translation by hand, use the CLI to extract strings and generate locale files: CLI guide

Continue with

  • Expo setup
  • Next.js setup

Examples

  • react-vite-example
  • expo-example