diff --git a/docs/en-US/react/index.mdx b/docs/en-US/react/index.mdx
index 024fe556..ef6971b0 100644
--- a/docs/en-US/react/index.mdx
+++ b/docs/en-US/react/index.mdx
@@ -1,16 +1,16 @@
---
title: React Quickstart
-description: Add multiple languages to your React app in under 10 minutes
+description: Add multiple languages to your server-rendered React app in under 10 minutes
---
-By the end of this guide, your React app will display content in multiple languages, with a language switcher your users can interact with.
+By the end of this guide, your server-rendered React app will display content in multiple languages, with a language switcher your users can interact with.
**Prerequisites:**
-- A React app (Vite, Create React App, or similar)
+- A server-rendered React app (React Router or a custom SSR setup)
- Node.js 18+
- **Want automatic setup?** Run `npx gt@latest` to configure everything with the [Setup Wizard](/docs/cli/init). This guide covers manual setup.
+ **Client-side only app?** If your app renders entirely in the browser with Vite, follow the [SPA quickstart](/docs/react/tutorials/quickstart-spa) instead — it skips the provider entirely.
---
@@ -58,7 +58,7 @@ Create a **`gt.config.json`** file in your project root. This tells the library
"locales": ["es", "fr", "ja"],
"files": {
"gt": {
- "output": "public/_gt/[locale].json"
+ "output": "src/_gt/[locale].json"
}
}
}
@@ -68,116 +68,78 @@ Create a **`gt.config.json`** file in your project root. This tells the library
- **`locales`** — the languages you want to translate into. Pick any from the [supported locales list](/docs/platform/supported-locales).
- **`files`** — tells the CLI where to save translation files. The `output` path should match the import path in your `loadTranslations` function (Step 3).
-
- **Using Vite?** Set the output path to `"src/_gt/[locale].json"` instead of `"public/_gt/[locale].json"`. Vite imports translation files as modules, so they should live inside `src/` rather than `public/`.
-
-
---
## Step 3: Create a translation loader
-`gt-react` runs entirely on the client, so it needs a function to load translation files at runtime. Create a `loadTranslations` file:
+Create a `loadTranslations` function that loads a locale's translation file. On the server this runs during rendering; the CLI generates the files when you run `npx gt translate`:
```ts title="src/loadTranslations.ts"
export default async function loadTranslations(locale: string) {
try {
- const translations = await import(`../public/_gt/${locale}.json`);
+ const translations = await import(`./_gt/${locale}.json`);
return translations.default;
} catch (error) {
- console.warn(`No translations found for ${locale}`);
return {};
}
}
```
-This function loads JSON translation files from your `public/_gt/` directory. The CLI generates these files when you run `npx gt translate`.
+---
-
-
- Since Vite translation files live in `src/_gt/` (see Step 2), update the import path:
-
- ```ts title="src/loadTranslations.ts"
- export default async function loadTranslations(locale: string) {
- try {
- const translations = await import(`./_gt/${locale}.json`);
- return translations.default;
- } catch (error) {
- console.warn(`No translations found for ${locale}`);
- return {};
- }
- }
- ```
-
-
- CRA's webpack config blocks dynamic `import()` from outside `src/`. Use `fetch()` instead:
-
- ```ts title="src/loadTranslations.ts"
- export default async function loadTranslations(locale: string) {
- try {
- const response = await fetch(`${process.env.PUBLIC_URL}/_gt/${locale}.json`);
- if (!response.ok) throw new Error('Not found');
- return await response.json();
- } catch (error) {
- console.warn(`No translations found for ${locale}`);
- return {};
- }
- }
- ```
-
-
+## Step 4: Initialize the library
+
+Call **`initializeGT`** at module scope in a file that loads on both the server and the client — your root route or layout is the natural place. It registers your config and translation loader once; the configuration is immutable for the lifetime of the app:
+
+```tsx title="src/routes/root.tsx"
+import { initializeGT } from 'gt-react';
+import gtConfig from '../../gt.config.json';
+import loadTranslations from '../loadTranslations';
+
+initializeGT({
+ defaultLocale: gtConfig.defaultLocale,
+ locales: gtConfig.locales,
+ loadTranslations,
+});
+```
---
-## Step 4: Add the GTProvider to your app
+## Step 5: Load translations on the server
-The **`GTProvider`** component gives your entire app access to translations. Wrap your app at the root level:
+In your root route's loader (or equivalent server handler), resolve the request locale and fetch a translations snapshot with **`getTranslationsSnapshot`**, then pass both to **``**:
-```tsx title="src/App.tsx"
-import { GTProvider } from 'gt-react';
-import gtConfig from '../gt.config.json';
-import loadTranslations from './loadTranslations';
+```tsx title="src/routes/root.tsx"
+import {
+ GTProvider,
+ getTranslationsSnapshot,
+ parseLocale,
+} from 'gt-react';
-export default function App() {
+// In your route loader (exact API depends on your framework)
+export async function loader({ request }) {
+ const locale = parseLocale(request); // [!code highlight]
+ return {
+ locale,
+ translations: await getTranslationsSnapshot(locale), // [!code highlight]
+ };
+}
+
+export default function Root({ children }) {
+ const { locale, translations } = useLoaderData();
return (
-
- {/* Your app content */}
+
+ {children}
);
}
```
-`GTProvider` takes your config and translation loader as props. It manages locale state and makes translations available to all child components.
-
-
-
- CRA restricts imports to files inside `src/`, so `import gtConfig from '../gt.config.json'` will fail. Either copy `gt.config.json` into `src/`, or inline the config directly:
-
- ```tsx title="src/App.tsx"
- import { GTProvider } from 'gt-react';
- import loadTranslations from './loadTranslations';
-
- export default function App() {
- return (
-
- {/* Your app content */}
-
- );
- }
- ```
-
-
-
---
-## Step 5: Mark content for translation
+## Step 6: Mark content for translation
-Now, wrap any text you want translated with the **``** component. `` stands for "translate":
+Wrap any text you want translated with the **``** component. `` stands for "translate":
```tsx title="src/components/Welcome.tsx"
import { T } from 'gt-react';
@@ -194,54 +156,60 @@ export default function Welcome() {
}
```
-You can wrap as much or as little JSX as you want inside ``. Everything inside it — text, nested elements, even formatting — gets translated as a unit.
+For plain strings — like `placeholder` attributes or `aria-label` values — use the **`useGT`** hook:
+
+```tsx title="src/components/ContactForm.tsx"
+import { useGT } from 'gt-react';
+
+export default function ContactForm() {
+ const gt = useGT();
+ return ;
+}
+```
---
-## Step 6: Add a language switcher
+## Step 7: Add a language switcher
Drop in a **``** so users can change languages:
-```tsx title="src/components/Welcome.tsx"
-import { T, LocaleSelector } from 'gt-react';
+```tsx title="src/components/Header.tsx"
+import { LocaleSelector } from 'gt-react';
-export default function Welcome() {
- return (
-
-
-
-