From 10c2a417c0a8c0e390d315be10aae6be6e7b9f79 Mon Sep 17 00:00:00 2001 From: Ernest McCarter Date: Thu, 9 Jul 2026 15:59:19 -0700 Subject: [PATCH 1/9] docs(react): split React quickstart into SPA and server-rendered guides - Add tutorials/quickstart-spa: Vite-first setup with initializeGTSPA(), a bootstrap entry module awaited before render, and no provider - Add tutorials/quickstart-ssr: initializeGT() at module scope, per-request getTranslationsSnapshot(locale) passed to , with a concrete cookie -> Accept-Language -> default locale resolver using determineLocale - Turn react/index into a chooser between the two quickstarts --- docs/en-US/react/index.mdx | 395 +--------------- docs/en-US/react/meta.json | 3 +- docs/en-US/react/tutorials/quickstart-spa.mdx | 444 ++++++++++++++++++ docs/en-US/react/tutorials/quickstart-ssr.mdx | 326 +++++++++++++ 4 files changed, 797 insertions(+), 371 deletions(-) create mode 100644 docs/en-US/react/tutorials/quickstart-spa.mdx create mode 100644 docs/en-US/react/tutorials/quickstart-ssr.mdx diff --git a/docs/en-US/react/index.mdx b/docs/en-US/react/index.mdx index 024fe556..30f5dd85 100644 --- a/docs/en-US/react/index.mdx +++ b/docs/en-US/react/index.mdx @@ -3,386 +3,41 @@ title: React Quickstart description: Add multiple languages to your 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. +## Getting started -**Prerequisites:** -- A React app (Vite, Create React App, or similar) -- Node.js 18+ +Add translations to your React app with `gt-react`. Setup differs depending on how your app renders, so choose the quickstart that matches your setup: - - **Want automatic setup?** Run `npx gt@latest` to configure everything with the [Setup Wizard](/docs/cli/init). This guide covers manual setup. - - ---- - -## Step 1: Install the packages - -`gt-react` is the library that powers translations in your app. `gt` is the CLI tool that prepares translations for production. - - - - ```bash - npm i gt-react - npm i -D gt - ``` - - - ```bash - yarn add gt-react - yarn add --dev gt - ``` - - - ```bash - bun add gt-react - bun add --dev gt - ``` - - - ```bash - pnpm add gt-react - pnpm add --save-dev gt - ``` - - - ---- - -## Step 2: Create a translation config file - -Create a **`gt.config.json`** file in your project root. This tells the library which languages you support: - -```json title="gt.config.json" -{ - "defaultLocale": "en", - "locales": ["es", "fr", "ja"], - "files": { - "gt": { - "output": "public/_gt/[locale].json" - } - } -} -``` - -- **`defaultLocale`** — the language your app is written in (your source language). -- **`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). + + + For client-side rendered apps (Vite, Create React App, webpack). Initialize once with `initializeGTSPA()` — no provider needed. + + + For SSR frameworks (TanStack Start, React Router, custom SSR). Load a translations snapshot on the server and pass it to ``. + + - **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: - -```ts title="src/loadTranslations.ts" -export default async function loadTranslations(locale: string) { - try { - const translations = await import(`../public/_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: Add the GTProvider to your app - -The **`GTProvider`** component gives your entire app access to translations. Wrap your app at the root level: - -```tsx title="src/App.tsx" -import { GTProvider } from 'gt-react'; -import gtConfig from '../gt.config.json'; -import loadTranslations from './loadTranslations'; - -export default function App() { - return ( - - {/* Your app content */} - - ); -} -``` - -`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 - -Now, wrap any text you want translated with the **``** component. `` stands for "translate": - -```tsx title="src/components/Welcome.tsx" -import { T } from 'gt-react'; - -export default function Welcome() { - return ( -
- -

Welcome to my app

-

This content will be translated automatically.

-
-
- ); -} -``` - -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. - ---- - -## Step 6: Add a language switcher - -Drop in a **``** so users can change languages: - -```tsx title="src/components/Welcome.tsx" -import { T, LocaleSelector } from 'gt-react'; - -export default function Welcome() { - return ( -
- - -

Welcome to my app

-

This content will be translated automatically.

-
-
- ); -} -``` - -`LocaleSelector` renders a dropdown populated with the languages from your `gt.config.json`. - ---- - -## Step 7: Set up environment variables (optional) - -To see translations in development, you need API keys from General Translation. These enable **on-demand translation** — your app translates content in real time as you develop. - -Create a **`.env.local`** file with the correct prefix for your bundler: - - - - ```bash title=".env.local" - VITE_GT_API_KEY="your-dev-api-key" - VITE_GT_PROJECT_ID="your-project-id" - ``` - - - ```bash title=".env.local" - REACT_APP_GT_API_KEY="your-dev-api-key" - REACT_APP_GT_PROJECT_ID="your-project-id" - ``` - - - -Get your free keys at [dash.generaltranslation.com](https://dash.generaltranslation.com/signup) or by running: - -```bash -npx gt auth -``` - - - For development, use a key starting with `gtx-dev-`. Production keys (`gtx-api-`) are for CI/CD only. - - Client-side bundlers like Vite and CRA require environment variables to use specific prefixes (`VITE_` or `REACT_APP_`) to be exposed to the browser. Bare `GT_API_KEY` will not be available at runtime. - - - - - Yes. Without API keys, `gt-react` works as a standard i18n library. You won't get on-demand translation in development, but you can still: - - Provide your own translation files manually - - Use all components (``, ``, `LocaleSelector`, etc.) - - Run `npx gt generate` to create translation file templates, then translate them yourself - - - ---- - -## Step 8: See it working - -Start your dev server: - - - - ```bash - npm run dev - ``` - - - ```bash - yarn dev - ``` - - - ```bash - bun dev - ``` - - - ```bash - pnpm dev - ``` - - - -Open your app and use the language dropdown to switch languages. You should see your content translated. - - - In development, translations happen on-demand — you may see a brief loading state the first time you switch to a new language. In production, translations are pre-generated and load instantly. + **Want automatic setup?** Run `npx gt@latest` to configure everything with the [Setup Wizard](/docs/cli/init). ---- - -## Step 9: Translate strings (not just JSX) - -For plain strings — like `placeholder` attributes, `aria-label` values, or `alt` text — use the **`useGT`** hook: - -```tsx title="src/components/ContactForm.tsx" -import { useGT } from 'gt-react'; - -export default function ContactForm() { - const gt = useGT(); - - return ( -
- - -
- ); -} -``` - ---- - -## Step 10: Deploy to production - -In production, translations are pre-generated at build time (no real-time API calls). Add the translate command to your build script: - -```json title="package.json" -{ - "scripts": { - "build": "npx gt translate && " - } -} -``` +## How the two setups differ -Set your **production** environment variables in your hosting provider (Vercel, Netlify, etc.): +| | SPA | Server-rendered | +| --- | --- | --- | +| Initialization | `initializeGTSPA()` in your entry point, awaited before render | `initializeGT()` at module scope in your root route | +| Translation loading | In the browser, during initialization | On the server, per request, via `getTranslationsSnapshot(locale)` | +| Provider | None | `` | +| Locale detection | Automatic (cookie, then browser language) | Your route loader resolves it from the request | -```bash -GT_PROJECT_ID=your-project-id -GT_API_KEY=gtx-api-your-production-key -``` +Everything after setup is identical: mark content with [``](/docs/react/guides/t), translate strings with [`useGT`](/docs/react/guides/strings), and pre-generate production translations with [`npx gt translate`](/docs/cli/translate). - - Production keys start with `gtx-api-` (not `gtx-dev-`). Get one from [dash.generaltranslation.com](https://dash.generaltranslation.com). Never publicly expose your `GT_API_KEY`. + + **Using a full-stack framework?** [`gt-next`](/docs/next) covers Next.js and [`gt-tanstack-start`](/docs/tanstack-start) covers TanStack Start — both build on `gt-react` and handle the server integration for you. -That's it — your app is now multilingual. 🎉 - ---- - -## Troubleshooting - - - - `gt-react` stores the user's language preference in a cookie called `generaltranslation.locale`. If you previously tested with a different language, this cookie may override your selection. Clear your cookies and try again. - - - [Chrome](https://support.google.com/chrome/answer/95647) - - [Firefox](https://support.mozilla.org/en-US/kb/delete-cookies-remove-info-websites-stored) - - [Safari](https://support.apple.com/en-mn/guide/safari/sfri11471/16.0/mac/11.0) - - - This is expected. In development, translations happen on-demand (your content is translated in real time via the API). This delay **does not exist in production** — all translations are pre-generated by `npx gt translate`. - - - Ambiguous text can lead to inaccurate translations. For example, "apple" could mean the fruit or the company. Add a `context` prop to help: - - ```jsx - Apple - ``` - - Both `` and `useGT()` support the `context` option. - - - ---- - ## Next steps -- [**`` Component Guide**](/docs/react/guides/t) — Learn about variables, plurals, and advanced translation patterns -- [**String Translation Guide**](/docs/react/guides/strings) — Deep dive into `useGT` -- [**Variable Components**](/docs/react/guides/variables) — Handle dynamic content with ``, ``, ``, and `` -- [**Pluralization**](/docs/react/api/components/plural) — Handle plural forms with the `` component -- [**Deploying to Production**](/docs/react/tutorials/quickdeploy) — CI/CD setup, caching, and performance optimization -- [**Shared Strings**](/docs/react/guides/shared-strings) — Translate text in arrays, config objects, and shared data with `msg()` +- [Introduction](/docs/react/introduction) - What `gt-react` does and how it works +- [`` component guide](/docs/react/guides/t) - Translate JSX content +- [String translation guide](/docs/react/guides/strings) - Translate plain strings with `useGT` +- [Deploying to production](/docs/react/tutorials/quickdeploy) - CI/CD setup for translations diff --git a/docs/en-US/react/meta.json b/docs/en-US/react/meta.json index 193b540d..109d0966 100644 --- a/docs/en-US/react/meta.json +++ b/docs/en-US/react/meta.json @@ -28,7 +28,8 @@ "./api/helpers", "./api/types", "---Tutorials---", - "./tutorials/quickstart", + "./tutorials/quickstart-spa", + "./tutorials/quickstart-ssr", "./tutorials/quickdeploy", "./tutorials/mini-shop" ], diff --git a/docs/en-US/react/tutorials/quickstart-spa.mdx b/docs/en-US/react/tutorials/quickstart-spa.mdx new file mode 100644 index 00000000..1c4da050 --- /dev/null +++ b/docs/en-US/react/tutorials/quickstart-spa.mdx @@ -0,0 +1,444 @@ +--- +title: SPA Quickstart +description: Add multiple languages to your single-page React app in under 10 minutes +--- + +By the end of this guide, your single-page React app will display content in multiple languages, with a language switcher your users can interact with. + +In a single-page app, `gt-react` runs entirely in the browser — you initialize it once at startup with `initializeGTSPA()`, and you don't need a provider component. + +**Prerequisites:** +- A client-side rendered React app (Vite, Create React App, webpack, or similar) +- 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. + + + + **Server-rendered app?** If your framework renders on the server (TanStack Start, React Router, or a custom SSR setup), follow the [server-rendered quickstart](/docs/react/tutorials/quickstart-ssr) instead. + + +--- + +## Step 1: Install the packages + +`gt-react` is the library that powers translations in your app. `gt` is the CLI tool that prepares translations for production, and `@generaltranslation/compiler` is a build plugin for your bundler. + + + + ```bash + npm i gt-react + npm i -D gt @generaltranslation/compiler + ``` + + + ```bash + yarn add gt-react + yarn add --dev gt @generaltranslation/compiler + ``` + + + ```bash + bun add gt-react + bun add --dev gt @generaltranslation/compiler + ``` + + + ```bash + pnpm add gt-react + pnpm add --save-dev gt @generaltranslation/compiler + ``` + + + +--- + +## Step 2: Create a translation config file + +Create a **`gt.config.json`** file in your project root. This tells the library which languages you support: + +```json title="gt.config.json" +{ + "defaultLocale": "en", + "locales": ["es", "fr", "ja"], + "files": { + "gt": { + "output": "src/_gt/[locale].json" + } + } +} +``` + +- **`defaultLocale`** — the language your app is written in (your source language). +- **`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 4). + + + **File location:** Bundlers like Vite import translation files as modules, so they should live inside `src/`. If you load translations over HTTP instead (see the Create React App note in Step 4), use `"public/_gt/[locale].json"`. + + +--- + +## Step 3: Add the compiler plugin + +Add the GT compiler plugin to your bundler config. It analyzes your source files at build time — validating translation calls and precomputing translation metadata so that work doesn't happen in the browser: + +```ts title="vite.config.ts" +import react from '@vitejs/plugin-react'; +import { vite as gtCompiler } from '@generaltranslation/compiler'; // [!code highlight] +import { defineConfig } from 'vite'; + +export default defineConfig({ + plugins: [gtCompiler(), react()], // [!code highlight] +}); +``` + + + + `@generaltranslation/compiler` also exports plugins for other bundlers — import the one that matches yours: + + ```ts + import { webpack as gtCompiler } from '@generaltranslation/compiler'; + // also available: rollup, esbuild + ``` + + + +See the [compiler concepts page](/docs/react/concepts/compiler) for everything the compiler can do, including automatic JSX wrapping. + +--- + +## Step 4: Create a translation loader + +In an SPA, `gt-react` needs a function to load translation files in the browser at runtime. Create a `loadTranslations` file: + +```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 {}; + } +} +``` + +This function loads JSON translation files from your `src/_gt/` directory. The CLI generates these files when you run `npx gt translate`. + + + + CRA's webpack config blocks dynamic `import()` from outside `src/`. Store translations in `public/_gt/` and 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 5: Initialize the library + +Call **`initializeGTSPA`** once at startup, before your app renders. It takes your config and translation loader, determines the user's locale, and loads the translations for it. + +The most robust pattern is a small entry module that initializes GT first, then loads the rest of the app: + +```ts title="src/index.ts" +import { initializeGTSPA } from 'gt-react'; +import gtConfig from '../gt.config.json'; +import loadTranslations from './loadTranslations'; + +await initializeGTSPA({ + defaultLocale: gtConfig.defaultLocale, + locales: gtConfig.locales, + loadTranslations, +}); + +await import('./main'); // render the app only after GT is ready +``` + +```tsx title="src/main.tsx" +import { StrictMode } from 'react'; +import { createRoot } from 'react-dom/client'; +import App from './App'; + +createRoot(document.getElementById('root')!).render( + + + +); +``` + +Then update the module script tag in your `index.html` to point at the new entry: change its `src` from `/src/main.tsx` to `/src/index.ts`. + +`initializeGTSPA` runs once at startup — the configuration is immutable for the lifetime of the app. After it resolves, every component and hook in your app can access translations. **You don't need to wrap your app in a provider.** + + + + CRA may not support top-level `await`, so render inside `.then()`: + + ```tsx title="src/index.tsx" + import { StrictMode } from 'react'; + import { createRoot } from 'react-dom/client'; + import { initializeGTSPA } from 'gt-react'; + import loadTranslations from './loadTranslations'; + import App from './App'; + + initializeGTSPA({ + defaultLocale: 'en', + locales: ['es', 'fr', 'ja'], + loadTranslations, + }).then(() => { + createRoot(document.getElementById('root')!).render( + + + + ); + }); + ``` + + + +--- + +## Step 6: Mark content for translation + +Now, wrap any text you want translated with the **``** component. `` stands for "translate": + +```tsx title="src/components/Welcome.tsx" +import { T } from 'gt-react'; + +export default function Welcome() { + return ( +
+ +

Welcome to my app

+

This content will be translated automatically.

+
+
+ ); +} +``` + +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. + +--- + +## 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'; + +export default function Welcome() { + return ( +
+ + +

Welcome to my app

+

This content will be translated automatically.

+
+
+ ); +} +``` + +`LocaleSelector` renders a dropdown populated with the languages from your `gt.config.json`. + +When the user picks a language, `gt-react` saves the choice to the `generaltranslation.locale` cookie and reloads the page — `initializeGTSPA` then re-runs and loads the new locale's translations before the app renders. + +--- + +## Step 8: Set up environment variables (optional) + +To see translations in development, you need API keys from General Translation. These enable **on-demand translation** — your app translates content in real time as you develop. + +Create a **`.env.local`** file with the correct prefix for your bundler: + + + + ```bash title=".env.local" + VITE_GT_PROJECT_ID="your-project-id" + VITE_GT_DEV_API_KEY="your-dev-api-key" + ``` + + `gt-react` reads these automatically during initialization — no extra code needed. The dev API key is only read in development, so it stays out of production bundles. + + + ```bash title=".env.local" + REACT_APP_GT_PROJECT_ID="your-project-id" + REACT_APP_GT_DEV_API_KEY="your-dev-api-key" + ``` + + CRA environment variables are not read automatically — pass them to `initializeGTSPA`: + + ```tsx title="src/index.tsx" + initializeGTSPA({ + defaultLocale: 'en', + locales: ['es', 'fr', 'ja'], + loadTranslations, + projectId: process.env.REACT_APP_GT_PROJECT_ID, + devApiKey: + process.env.NODE_ENV === 'development' + ? process.env.REACT_APP_GT_DEV_API_KEY + : undefined, + }); + ``` + + + +Get your free keys at [dash.generaltranslation.com](https://dash.generaltranslation.com/signup) or by running: + +```bash +npx gt auth +``` + + + For development, use a key starting with `gtx-dev-`. Production keys (`gtx-api-`) are for CI/CD only. + + Client-side bundlers like Vite and CRA require environment variables to use specific prefixes (`VITE_` or `REACT_APP_`) to be exposed to the browser. Bare `GT_API_KEY` will not be available at runtime. + + + + + Yes. Without API keys, `gt-react` works as a standard i18n library. You won't get on-demand translation in development, but you can still: + - Provide your own translation files manually + - Use all components (``, ``, `LocaleSelector`, etc.) + - Run `npx gt generate` to create translation file templates, then translate them yourself + + + +--- + +## Step 9: See it working + +Start your dev server: + + + + ```bash + npm run dev + ``` + + + ```bash + yarn dev + ``` + + + ```bash + bun dev + ``` + + + ```bash + pnpm dev + ``` + + + +Open your app and use the language dropdown to switch languages. You should see your content translated. + + + **Note:** In development, translations happen on-demand — content may briefly appear in your source language the first time you switch to a new language, then update once the translation is ready. In production, translations are pre-generated and load instantly. + + +--- + +## Step 10: Translate strings (not just JSX) + +For plain strings — like `placeholder` attributes, `aria-label` values, or `alt` text — use the **`useGT`** hook: + +```tsx title="src/components/ContactForm.tsx" +import { useGT } from 'gt-react'; + +export default function ContactForm() { + const gt = useGT(); + + return ( +
+ + +
+ ); +} +``` + +--- + +## Step 11: Deploy to production + +In production, translations are pre-generated at build time (no real-time API calls). Add the translate command to your build script: + +```json title="package.json" +{ + "scripts": { + "build": "npx gt translate && " + } +} +``` + +Set your **production** environment variables in your hosting provider (Vercel, Netlify, etc.): + +```bash +GT_PROJECT_ID=your-project-id +GT_API_KEY=gtx-api-your-production-key +``` + + + Production keys start with `gtx-api-` (not `gtx-dev-`). Get one from [dash.generaltranslation.com](https://dash.generaltranslation.com). Never publicly expose your `GT_API_KEY`. + + +That's it — your app is now multilingual. 🎉 + +--- + +## Troubleshooting + + + + `gt-react` stores the user's language preference in a cookie called `generaltranslation.locale`. If you previously tested with a different language, this cookie may override your selection. Clear your cookies and try again. + + - [Chrome](https://support.google.com/chrome/answer/95647) + - [Firefox](https://support.mozilla.org/en-US/kb/delete-cookies-remove-info-websites-stored) + - [Safari](https://support.apple.com/en-mn/guide/safari/sfri11471/16.0/mac/11.0) + + + This is expected. In development, translations happen on-demand (your content is translated in real time via the API). This delay **does not exist in production** — all translations are pre-generated by `npx gt translate`. + + + Ambiguous text can lead to inaccurate translations. For example, "apple" could mean the fruit or the company. Add a `$context` prop to help: + + ```jsx + Apple + ``` + + Both `` and `useGT()` support the `$context` option. + + + +--- + +## Next steps + +- [**`` Component Guide**](/docs/react/guides/t) — Learn about variables, plurals, and advanced translation patterns +- [**String Translation Guide**](/docs/react/guides/strings) — Deep dive into `useGT` +- [**Variable Components**](/docs/react/guides/variables) — Handle dynamic content with ``, ``, ``, and `` +- [**Pluralization**](/docs/react/api/components/plural) — Handle plural forms with the `` component +- [**Deploying to Production**](/docs/react/tutorials/quickdeploy) — CI/CD setup, caching, and performance optimization +- [**Shared Strings**](/docs/react/guides/shared-strings) — Translate text in arrays, config objects, and shared data with `msg()` diff --git a/docs/en-US/react/tutorials/quickstart-ssr.mdx b/docs/en-US/react/tutorials/quickstart-ssr.mdx new file mode 100644 index 00000000..eee3ecc8 --- /dev/null +++ b/docs/en-US/react/tutorials/quickstart-ssr.mdx @@ -0,0 +1,326 @@ +--- +title: Server-rendered Quickstart +description: Add multiple languages to your server-rendered React app in under 10 minutes +--- + +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. + +Server-rendered apps work differently from SPAs: the server resolves the user's locale, loads a translations snapshot, and passes both to a `` so the first render is already translated. There is no client-side loading state. + +**Prerequisites:** +- A server-rendered React app (TanStack Start, React Router, or a custom SSR setup) +- Node.js 18+ + + + **Using TanStack Start?** Use [`gt-tanstack-start`](/docs/tanstack-start) instead — it re-exports the `gt-react` API and adds `parseLocale()` for isomorphic locale detection. The setup below is the same, minus writing your own locale resolver. + + + + **Client-side only app?** If your app renders entirely in the browser (Vite, Create React App), follow the [SPA quickstart](/docs/react/tutorials/quickstart-spa) instead — it skips the provider entirely. + + +--- + +## Step 1: Install the packages + +`gt-react` is the library that powers translations in your app. `gt` is the CLI tool that prepares translations for production. + + + + ```bash + npm i gt-react + npm i -D gt + ``` + + + ```bash + yarn add gt-react + yarn add --dev gt + ``` + + + ```bash + bun add gt-react + bun add --dev gt + ``` + + + ```bash + pnpm add gt-react + pnpm add --save-dev gt + ``` + + + +--- + +## Step 2: Create a translation config file + +Create a **`gt.config.json`** file in your project root. This tells the library which languages you support: + +```json title="gt.config.json" +{ + "defaultLocale": "en", + "locales": ["es", "fr", "ja"], + "files": { + "gt": { + "output": "src/_gt/[locale].json" + } + } +} +``` + +- **`defaultLocale`** — the language your app is written in (your source language). +- **`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). + +--- + +## Step 3: Create a translation loader + +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(`./_gt/${locale}.json`); + return translations.default; + } catch (error) { + 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, +}); +``` + +Unlike `initializeGTSPA`, `initializeGT` doesn't load any translations itself — that happens per request in the next step. + +--- + +## Step 5: Load translations on the server + +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/routes/root.tsx" +import { GTProvider, getTranslationsSnapshot } from 'gt-react'; + +// In your route loader (exact API depends on your framework) +export async function loader({ request }) { + const locale = resolveLocale(request); // [!code highlight] + return { + locale, + translations: await getTranslationsSnapshot(locale), // [!code highlight] + }; +} + +export default function Root({ children }) { + const { locale, translations } = useLoaderData(); + return ( + + {children} + + ); +} +``` + +For `resolveLocale`, read the **`generaltranslation.locale`** cookie first — that's where `gt-react` persists the user's language choice — then fall back to the request's `Accept-Language` header, and finally your default locale. The **`determineLocale`** helper from `generaltranslation` (already a dependency of `gt-react`) picks the best supported match from a list of candidates: + +```ts title="src/resolveLocale.ts" +import { determineLocale } from 'generaltranslation'; +import gtConfig from '../gt.config.json'; + +export function resolveLocale(request: Request): string { + const candidates: string[] = []; + + // 1. The locale cookie is the source of truth — gt-react writes it + // when the user picks a language + const cookie = request.headers + .get('cookie') + ?.split('; ') + .find((entry) => entry.startsWith('generaltranslation.locale=')); + if (cookie) candidates.push(cookie.split('=')[1]); + + // 2. Fall back to the languages the browser asks for + const acceptLanguage = request.headers.get('accept-language'); + if (acceptLanguage) { + candidates.push( + ...acceptLanguage.split(',').map((entry) => entry.split(';')[0].trim()) + ); + } + + // 3. Pick the best supported match, or fall back to the default locale + return ( + determineLocale(candidates, [gtConfig.defaultLocale, ...gtConfig.locales]) ?? + gtConfig.defaultLocale + ); +} +``` + + + **Note:** This is exactly what `gt-next` and `gt-tanstack-start` do for you automatically — if you're on Next.js or TanStack Start, use those packages instead of writing a resolver by hand. + + + + **No loading state:** `` renders synchronously from the snapshot. Whatever loading behavior you want (pending UI, streaming) belongs in your framework's route loader, not in GT. + + +--- + +## Step 6: Mark content for translation + +Wrap any text you want translated with the **``** component. `` stands for "translate": + +```tsx title="src/components/Welcome.tsx" +import { T } from 'gt-react'; + +export default function Welcome() { + return ( +
+ +

Welcome to my app

+

This content will be translated automatically.

+
+
+ ); +} +``` + +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 7: Add a language switcher + +Drop in a **``** so users can change languages: + +```tsx title="src/components/Header.tsx" +import { LocaleSelector } from 'gt-react'; + +export default function Header() { + return ; +} +``` + +When the user picks a language, `gt-react` persists the choice in the `generaltranslation.locale` cookie and reloads the page, so the server re-renders everything in the new locale. + +--- + +## Step 8: Set up environment variables (optional) + +To see translations in development, you need API keys from General Translation. These enable **on-demand translation** — your app translates content in real time as you develop. + +If your framework builds with Vite, `gt-react` reads these automatically during initialization: + +```bash title=".env.local" +VITE_GT_PROJECT_ID="your-project-id" +VITE_GT_DEV_API_KEY="your-dev-api-key" +``` + +Otherwise, pass credentials to `initializeGT` yourself: + +```ts +initializeGT({ + defaultLocale: gtConfig.defaultLocale, + locales: gtConfig.locales, + loadTranslations, + projectId: process.env.GT_PROJECT_ID, + devApiKey: + process.env.NODE_ENV === 'development' + ? process.env.GT_DEV_API_KEY + : undefined, +}); +``` + +Get your free keys at [dash.generaltranslation.com](https://dash.generaltranslation.com/signup) or by running: + +```bash +npx gt auth +``` + + + For development, use a key starting with `gtx-dev-`. Production keys (`gtx-api-`) are for CI/CD only. + + +--- + +## Step 9: Deploy to production + +In production, translations are pre-generated at build time (no real-time API calls). Add the translate command to your build script: + +```json title="package.json" +{ + "scripts": { + "build": "npx gt translate && " + } +} +``` + +Set your **production** environment variables in your hosting provider: + +```bash +GT_PROJECT_ID=your-project-id +GT_API_KEY=gtx-api-your-production-key +``` + + + Production keys start with `gtx-api-` (not `gtx-dev-`). Get one from [dash.generaltranslation.com](https://dash.generaltranslation.com). Never publicly expose your `GT_API_KEY`. + + +That's it — your app is now multilingual. 🎉 + +--- + +## Troubleshooting + + + + Make sure your locale resolver reads the `generaltranslation.locale` cookie. If the server ignores it, the client and server will disagree about the current locale. + + + This is expected. In development, translations happen on-demand (your content is translated in real time via the API). This delay **does not exist in production** — all translations are pre-generated by `npx gt translate`. + + + Ambiguous text can lead to inaccurate translations. For example, "apple" could mean the fruit or the company. Add a `$context` prop to help: + + ```jsx + Apple + ``` + + Both `` and `useGT()` support the `$context` option. + + + +--- + +## Next steps + +- [**`` API**](/docs/react/api/components/gtprovider) — Full reference for the provider's props +- [**TanStack Start Quickstart**](/docs/tanstack-start) — The same setup with `parseLocale()` included +- [**`` Component Guide**](/docs/react/guides/t) — Learn about variables, plurals, and advanced translation patterns +- [**String Translation Guide**](/docs/react/guides/strings) — Deep dive into `useGT` +- [**Deploying to Production**](/docs/react/tutorials/quickdeploy) — CI/CD setup, caching, and performance optimization From ab1714ff7b5af9805367c1beaf7dba29ff04b254 Mon Sep 17 00:00:00 2001 From: Ernest McCarter Date: Thu, 9 Jul 2026 16:52:40 -0700 Subject: [PATCH 2/9] docs(react): make server-rendered quickstart primary --- docs/en-US/react/index.mdx | 335 ++++++++++++++++-- docs/en-US/react/meta.json | 1 - docs/en-US/react/tutorials/quickstart-spa.mdx | 2 +- docs/en-US/react/tutorials/quickstart-ssr.mdx | 326 ----------------- 4 files changed, 310 insertions(+), 354 deletions(-) delete mode 100644 docs/en-US/react/tutorials/quickstart-ssr.mdx diff --git a/docs/en-US/react/index.mdx b/docs/en-US/react/index.mdx index 30f5dd85..ec5f2b92 100644 --- a/docs/en-US/react/index.mdx +++ b/docs/en-US/react/index.mdx @@ -1,43 +1,326 @@ --- 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 --- -## Getting started +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. -Add translations to your React app with `gt-react`. Setup differs depending on how your app renders, so choose the quickstart that matches your setup: +Server-rendered apps work differently from SPAs: the server resolves the user's locale, loads a translations snapshot, and passes both to a `` so the first render is already translated. There is no client-side loading state. - - - For client-side rendered apps (Vite, Create React App, webpack). Initialize once with `initializeGTSPA()` — no provider needed. - - - For SSR frameworks (TanStack Start, React Router, custom SSR). Load a translations snapshot on the server and pass it to ``. - - +**Prerequisites:** +- A server-rendered React app (TanStack Start, 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). + **Using TanStack Start?** Use [`gt-tanstack-start`](/docs/tanstack-start) instead — it re-exports the `gt-react` API and adds `parseLocale()` for isomorphic locale detection. The setup below is the same, minus writing your own locale resolver. -## How the two setups differ + + **Client-side only app?** If your app renders entirely in the browser (Vite, Create React App), follow the [SPA quickstart](/docs/react/tutorials/quickstart-spa) instead — it skips the provider entirely. + + +--- -| | SPA | Server-rendered | -| --- | --- | --- | -| Initialization | `initializeGTSPA()` in your entry point, awaited before render | `initializeGT()` at module scope in your root route | -| Translation loading | In the browser, during initialization | On the server, per request, via `getTranslationsSnapshot(locale)` | -| Provider | None | `` | -| Locale detection | Automatic (cookie, then browser language) | Your route loader resolves it from the request | +## Step 1: Install the packages -Everything after setup is identical: mark content with [``](/docs/react/guides/t), translate strings with [`useGT`](/docs/react/guides/strings), and pre-generate production translations with [`npx gt translate`](/docs/cli/translate). +`gt-react` is the library that powers translations in your app. `gt` is the CLI tool that prepares translations for production. - - **Using a full-stack framework?** [`gt-next`](/docs/next) covers Next.js and [`gt-tanstack-start`](/docs/tanstack-start) covers TanStack Start — both build on `gt-react` and handle the server integration for you. + + + ```bash + npm i gt-react + npm i -D gt + ``` + + + ```bash + yarn add gt-react + yarn add --dev gt + ``` + + + ```bash + bun add gt-react + bun add --dev gt + ``` + + + ```bash + pnpm add gt-react + pnpm add --save-dev gt + ``` + + + +--- + +## Step 2: Create a translation config file + +Create a **`gt.config.json`** file in your project root. This tells the library which languages you support: + +```json title="gt.config.json" +{ + "defaultLocale": "en", + "locales": ["es", "fr", "ja"], + "files": { + "gt": { + "output": "src/_gt/[locale].json" + } + } +} +``` + +- **`defaultLocale`** — the language your app is written in (your source language). +- **`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). + +--- + +## Step 3: Create a translation loader + +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(`./_gt/${locale}.json`); + return translations.default; + } catch (error) { + 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, +}); +``` + +Unlike `initializeGTSPA`, `initializeGT` doesn't load any translations itself — that happens per request in the next step. + +--- + +## Step 5: Load translations on the server + +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/routes/root.tsx" +import { GTProvider, getTranslationsSnapshot } from 'gt-react'; + +// In your route loader (exact API depends on your framework) +export async function loader({ request }) { + const locale = resolveLocale(request); // [!code highlight] + return { + locale, + translations: await getTranslationsSnapshot(locale), // [!code highlight] + }; +} + +export default function Root({ children }) { + const { locale, translations } = useLoaderData(); + return ( + + {children} + + ); +} +``` + +For `resolveLocale`, read the **`generaltranslation.locale`** cookie first — that's where `gt-react` persists the user's language choice — then fall back to the request's `Accept-Language` header, and finally your default locale. The **`determineLocale`** helper from `generaltranslation` (already a dependency of `gt-react`) picks the best supported match from a list of candidates: + +```ts title="src/resolveLocale.ts" +import { determineLocale } from 'generaltranslation'; +import gtConfig from '../gt.config.json'; + +export function resolveLocale(request: Request): string { + const candidates: string[] = []; + + // 1. The locale cookie is the source of truth — gt-react writes it + // when the user picks a language + const cookie = request.headers + .get('cookie') + ?.split('; ') + .find((entry) => entry.startsWith('generaltranslation.locale=')); + if (cookie) candidates.push(cookie.split('=')[1]); + + // 2. Fall back to the languages the browser asks for + const acceptLanguage = request.headers.get('accept-language'); + if (acceptLanguage) { + candidates.push( + ...acceptLanguage.split(',').map((entry) => entry.split(';')[0].trim()) + ); + } + + // 3. Pick the best supported match, or fall back to the default locale + return ( + determineLocale(candidates, [gtConfig.defaultLocale, ...gtConfig.locales]) ?? + gtConfig.defaultLocale + ); +} +``` + + + **Note:** This is exactly what `gt-next` and `gt-tanstack-start` do for you automatically — if you're on Next.js or TanStack Start, use those packages instead of writing a resolver by hand. + + + + **No loading state:** `` renders synchronously from the snapshot. Whatever loading behavior you want (pending UI, streaming) belongs in your framework's route loader, not in GT. +--- + +## Step 6: Mark content for translation + +Wrap any text you want translated with the **``** component. `` stands for "translate": + +```tsx title="src/components/Welcome.tsx" +import { T } from 'gt-react'; + +export default function Welcome() { + return ( +
+ +

Welcome to my app

+

This content will be translated automatically.

+
+
+ ); +} +``` + +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 7: Add a language switcher + +Drop in a **``** so users can change languages: + +```tsx title="src/components/Header.tsx" +import { LocaleSelector } from 'gt-react'; + +export default function Header() { + return ; +} +``` + +When the user picks a language, `gt-react` persists the choice in the `generaltranslation.locale` cookie and reloads the page, so the server re-renders everything in the new locale. + +--- + +## Step 8: Set up environment variables (optional) + +To see translations in development, you need API keys from General Translation. These enable **on-demand translation** — your app translates content in real time as you develop. + +If your framework builds with Vite, `gt-react` reads these automatically during initialization: + +```bash title=".env.local" +VITE_GT_PROJECT_ID="your-project-id" +VITE_GT_DEV_API_KEY="your-dev-api-key" +``` + +Otherwise, pass credentials to `initializeGT` yourself: + +```ts +initializeGT({ + defaultLocale: gtConfig.defaultLocale, + locales: gtConfig.locales, + loadTranslations, + projectId: process.env.GT_PROJECT_ID, + devApiKey: + process.env.NODE_ENV === 'development' + ? process.env.GT_DEV_API_KEY + : undefined, +}); +``` + +Get your free keys at [dash.generaltranslation.com](https://dash.generaltranslation.com/signup) or by running: + +```bash +npx gt auth +``` + + + For development, use a key starting with `gtx-dev-`. Production keys (`gtx-api-`) are for CI/CD only. + + +--- + +## Step 9: Deploy to production + +In production, translations are pre-generated at build time (no real-time API calls). Add the translate command to your build script: + +```json title="package.json" +{ + "scripts": { + "build": "npx gt translate && " + } +} +``` + +Set your **production** environment variables in your hosting provider: + +```bash +GT_PROJECT_ID=your-project-id +GT_API_KEY=gtx-api-your-production-key +``` + + + Production keys start with `gtx-api-` (not `gtx-dev-`). Get one from [dash.generaltranslation.com](https://dash.generaltranslation.com). Never publicly expose your `GT_API_KEY`. + + +That's it — your app is now multilingual. 🎉 + +--- + +## Troubleshooting + + + + Make sure your locale resolver reads the `generaltranslation.locale` cookie. If the server ignores it, the client and server will disagree about the current locale. + + + This is expected. In development, translations happen on-demand (your content is translated in real time via the API). This delay **does not exist in production** — all translations are pre-generated by `npx gt translate`. + + + Ambiguous text can lead to inaccurate translations. For example, "apple" could mean the fruit or the company. Add a `$context` prop to help: + + ```jsx + Apple + ``` + + Both `` and `useGT()` support the `$context` option. + + + +--- + ## Next steps -- [Introduction](/docs/react/introduction) - What `gt-react` does and how it works -- [`` component guide](/docs/react/guides/t) - Translate JSX content -- [String translation guide](/docs/react/guides/strings) - Translate plain strings with `useGT` -- [Deploying to production](/docs/react/tutorials/quickdeploy) - CI/CD setup for translations +- [**`` API**](/docs/react/api/components/gtprovider) — Full reference for the provider's props +- [**TanStack Start Quickstart**](/docs/tanstack-start) — The same setup with `parseLocale()` included +- [**`` Component Guide**](/docs/react/guides/t) — Learn about variables, plurals, and advanced translation patterns +- [**String Translation Guide**](/docs/react/guides/strings) — Deep dive into `useGT` +- [**Deploying to Production**](/docs/react/tutorials/quickdeploy) — CI/CD setup, caching, and performance optimization diff --git a/docs/en-US/react/meta.json b/docs/en-US/react/meta.json index 109d0966..f4f369ba 100644 --- a/docs/en-US/react/meta.json +++ b/docs/en-US/react/meta.json @@ -29,7 +29,6 @@ "./api/types", "---Tutorials---", "./tutorials/quickstart-spa", - "./tutorials/quickstart-ssr", "./tutorials/quickdeploy", "./tutorials/mini-shop" ], diff --git a/docs/en-US/react/tutorials/quickstart-spa.mdx b/docs/en-US/react/tutorials/quickstart-spa.mdx index 1c4da050..6a065c85 100644 --- a/docs/en-US/react/tutorials/quickstart-spa.mdx +++ b/docs/en-US/react/tutorials/quickstart-spa.mdx @@ -16,7 +16,7 @@ In a single-page app, `gt-react` runs entirely in the browser — you initialize
- **Server-rendered app?** If your framework renders on the server (TanStack Start, React Router, or a custom SSR setup), follow the [server-rendered quickstart](/docs/react/tutorials/quickstart-ssr) instead. + **Server-rendered app?** If your framework renders on the server (TanStack Start, React Router, or a custom SSR setup), follow the [React quickstart](/docs/react) instead. --- diff --git a/docs/en-US/react/tutorials/quickstart-ssr.mdx b/docs/en-US/react/tutorials/quickstart-ssr.mdx deleted file mode 100644 index eee3ecc8..00000000 --- a/docs/en-US/react/tutorials/quickstart-ssr.mdx +++ /dev/null @@ -1,326 +0,0 @@ ---- -title: Server-rendered Quickstart -description: Add multiple languages to your server-rendered React app in under 10 minutes ---- - -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. - -Server-rendered apps work differently from SPAs: the server resolves the user's locale, loads a translations snapshot, and passes both to a `` so the first render is already translated. There is no client-side loading state. - -**Prerequisites:** -- A server-rendered React app (TanStack Start, React Router, or a custom SSR setup) -- Node.js 18+ - - - **Using TanStack Start?** Use [`gt-tanstack-start`](/docs/tanstack-start) instead — it re-exports the `gt-react` API and adds `parseLocale()` for isomorphic locale detection. The setup below is the same, minus writing your own locale resolver. - - - - **Client-side only app?** If your app renders entirely in the browser (Vite, Create React App), follow the [SPA quickstart](/docs/react/tutorials/quickstart-spa) instead — it skips the provider entirely. - - ---- - -## Step 1: Install the packages - -`gt-react` is the library that powers translations in your app. `gt` is the CLI tool that prepares translations for production. - - - - ```bash - npm i gt-react - npm i -D gt - ``` - - - ```bash - yarn add gt-react - yarn add --dev gt - ``` - - - ```bash - bun add gt-react - bun add --dev gt - ``` - - - ```bash - pnpm add gt-react - pnpm add --save-dev gt - ``` - - - ---- - -## Step 2: Create a translation config file - -Create a **`gt.config.json`** file in your project root. This tells the library which languages you support: - -```json title="gt.config.json" -{ - "defaultLocale": "en", - "locales": ["es", "fr", "ja"], - "files": { - "gt": { - "output": "src/_gt/[locale].json" - } - } -} -``` - -- **`defaultLocale`** — the language your app is written in (your source language). -- **`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). - ---- - -## Step 3: Create a translation loader - -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(`./_gt/${locale}.json`); - return translations.default; - } catch (error) { - 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, -}); -``` - -Unlike `initializeGTSPA`, `initializeGT` doesn't load any translations itself — that happens per request in the next step. - ---- - -## Step 5: Load translations on the server - -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/routes/root.tsx" -import { GTProvider, getTranslationsSnapshot } from 'gt-react'; - -// In your route loader (exact API depends on your framework) -export async function loader({ request }) { - const locale = resolveLocale(request); // [!code highlight] - return { - locale, - translations: await getTranslationsSnapshot(locale), // [!code highlight] - }; -} - -export default function Root({ children }) { - const { locale, translations } = useLoaderData(); - return ( - - {children} - - ); -} -``` - -For `resolveLocale`, read the **`generaltranslation.locale`** cookie first — that's where `gt-react` persists the user's language choice — then fall back to the request's `Accept-Language` header, and finally your default locale. The **`determineLocale`** helper from `generaltranslation` (already a dependency of `gt-react`) picks the best supported match from a list of candidates: - -```ts title="src/resolveLocale.ts" -import { determineLocale } from 'generaltranslation'; -import gtConfig from '../gt.config.json'; - -export function resolveLocale(request: Request): string { - const candidates: string[] = []; - - // 1. The locale cookie is the source of truth — gt-react writes it - // when the user picks a language - const cookie = request.headers - .get('cookie') - ?.split('; ') - .find((entry) => entry.startsWith('generaltranslation.locale=')); - if (cookie) candidates.push(cookie.split('=')[1]); - - // 2. Fall back to the languages the browser asks for - const acceptLanguage = request.headers.get('accept-language'); - if (acceptLanguage) { - candidates.push( - ...acceptLanguage.split(',').map((entry) => entry.split(';')[0].trim()) - ); - } - - // 3. Pick the best supported match, or fall back to the default locale - return ( - determineLocale(candidates, [gtConfig.defaultLocale, ...gtConfig.locales]) ?? - gtConfig.defaultLocale - ); -} -``` - - - **Note:** This is exactly what `gt-next` and `gt-tanstack-start` do for you automatically — if you're on Next.js or TanStack Start, use those packages instead of writing a resolver by hand. - - - - **No loading state:** `` renders synchronously from the snapshot. Whatever loading behavior you want (pending UI, streaming) belongs in your framework's route loader, not in GT. - - ---- - -## Step 6: Mark content for translation - -Wrap any text you want translated with the **``** component. `` stands for "translate": - -```tsx title="src/components/Welcome.tsx" -import { T } from 'gt-react'; - -export default function Welcome() { - return ( -
- -

Welcome to my app

-

This content will be translated automatically.

-
-
- ); -} -``` - -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 7: Add a language switcher - -Drop in a **``** so users can change languages: - -```tsx title="src/components/Header.tsx" -import { LocaleSelector } from 'gt-react'; - -export default function Header() { - return ; -} -``` - -When the user picks a language, `gt-react` persists the choice in the `generaltranslation.locale` cookie and reloads the page, so the server re-renders everything in the new locale. - ---- - -## Step 8: Set up environment variables (optional) - -To see translations in development, you need API keys from General Translation. These enable **on-demand translation** — your app translates content in real time as you develop. - -If your framework builds with Vite, `gt-react` reads these automatically during initialization: - -```bash title=".env.local" -VITE_GT_PROJECT_ID="your-project-id" -VITE_GT_DEV_API_KEY="your-dev-api-key" -``` - -Otherwise, pass credentials to `initializeGT` yourself: - -```ts -initializeGT({ - defaultLocale: gtConfig.defaultLocale, - locales: gtConfig.locales, - loadTranslations, - projectId: process.env.GT_PROJECT_ID, - devApiKey: - process.env.NODE_ENV === 'development' - ? process.env.GT_DEV_API_KEY - : undefined, -}); -``` - -Get your free keys at [dash.generaltranslation.com](https://dash.generaltranslation.com/signup) or by running: - -```bash -npx gt auth -``` - - - For development, use a key starting with `gtx-dev-`. Production keys (`gtx-api-`) are for CI/CD only. - - ---- - -## Step 9: Deploy to production - -In production, translations are pre-generated at build time (no real-time API calls). Add the translate command to your build script: - -```json title="package.json" -{ - "scripts": { - "build": "npx gt translate && " - } -} -``` - -Set your **production** environment variables in your hosting provider: - -```bash -GT_PROJECT_ID=your-project-id -GT_API_KEY=gtx-api-your-production-key -``` - - - Production keys start with `gtx-api-` (not `gtx-dev-`). Get one from [dash.generaltranslation.com](https://dash.generaltranslation.com). Never publicly expose your `GT_API_KEY`. - - -That's it — your app is now multilingual. 🎉 - ---- - -## Troubleshooting - - - - Make sure your locale resolver reads the `generaltranslation.locale` cookie. If the server ignores it, the client and server will disagree about the current locale. - - - This is expected. In development, translations happen on-demand (your content is translated in real time via the API). This delay **does not exist in production** — all translations are pre-generated by `npx gt translate`. - - - Ambiguous text can lead to inaccurate translations. For example, "apple" could mean the fruit or the company. Add a `$context` prop to help: - - ```jsx - Apple - ``` - - Both `` and `useGT()` support the `$context` option. - - - ---- - -## Next steps - -- [**`` API**](/docs/react/api/components/gtprovider) — Full reference for the provider's props -- [**TanStack Start Quickstart**](/docs/tanstack-start) — The same setup with `parseLocale()` included -- [**`` Component Guide**](/docs/react/guides/t) — Learn about variables, plurals, and advanced translation patterns -- [**String Translation Guide**](/docs/react/guides/strings) — Deep dive into `useGT` -- [**Deploying to Production**](/docs/react/tutorials/quickdeploy) — CI/CD setup, caching, and performance optimization From 76cc8847946bdc1b8cc1eccb3fa2ee0dfbf377ce Mon Sep 17 00:00:00 2001 From: Ernest McCarter Date: Thu, 9 Jul 2026 17:14:07 -0700 Subject: [PATCH 3/9] docs(react): address quickstart review --- docs/en-US/react/index.mdx | 60 +---- docs/en-US/react/meta.json | 1 + docs/en-US/react/tutorials/quickstart-spa.mdx | 210 +++--------------- .../spa-development-translations.mdx | 114 ++++++++++ 4 files changed, 154 insertions(+), 231 deletions(-) create mode 100644 docs/en-US/react/tutorials/spa-development-translations.mdx diff --git a/docs/en-US/react/index.mdx b/docs/en-US/react/index.mdx index ec5f2b92..da08c757 100644 --- a/docs/en-US/react/index.mdx +++ b/docs/en-US/react/index.mdx @@ -5,16 +5,10 @@ description: Add multiple languages to your server-rendered React app in under 1 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. -Server-rendered apps work differently from SPAs: the server resolves the user's locale, loads a translations snapshot, and passes both to a `` so the first render is already translated. There is no client-side loading state. - **Prerequisites:** -- A server-rendered React app (TanStack Start, React Router, or a custom SSR setup) +- A server-rendered React app (React Router or a custom SSR setup) - Node.js 18+ - - **Using TanStack Start?** Use [`gt-tanstack-start`](/docs/tanstack-start) instead — it re-exports the `gt-react` API and adds `parseLocale()` for isomorphic locale detection. The setup below is the same, minus writing your own locale resolver. - - **Client-side only app?** If your app renders entirely in the browser (Vite, Create React App), follow the [SPA quickstart](/docs/react/tutorials/quickstart-spa) instead — it skips the provider entirely. @@ -109,8 +103,6 @@ initializeGT({ }); ``` -Unlike `initializeGTSPA`, `initializeGT` doesn't load any translations itself — that happens per request in the next step. - --- ## Step 5: Load translations on the server @@ -118,11 +110,15 @@ Unlike `initializeGTSPA`, `initializeGT` doesn't load any translations itself 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/routes/root.tsx" -import { GTProvider, getTranslationsSnapshot } from 'gt-react'; +import { + GTProvider, + getTranslationsSnapshot, + parseLocale, +} from 'gt-react'; // In your route loader (exact API depends on your framework) export async function loader({ request }) { - const locale = resolveLocale(request); // [!code highlight] + const locale = parseLocale(request); // [!code highlight] return { locale, translations: await getTranslationsSnapshot(locale), // [!code highlight] @@ -139,47 +135,6 @@ export default function Root({ children }) { } ``` -For `resolveLocale`, read the **`generaltranslation.locale`** cookie first — that's where `gt-react` persists the user's language choice — then fall back to the request's `Accept-Language` header, and finally your default locale. The **`determineLocale`** helper from `generaltranslation` (already a dependency of `gt-react`) picks the best supported match from a list of candidates: - -```ts title="src/resolveLocale.ts" -import { determineLocale } from 'generaltranslation'; -import gtConfig from '../gt.config.json'; - -export function resolveLocale(request: Request): string { - const candidates: string[] = []; - - // 1. The locale cookie is the source of truth — gt-react writes it - // when the user picks a language - const cookie = request.headers - .get('cookie') - ?.split('; ') - .find((entry) => entry.startsWith('generaltranslation.locale=')); - if (cookie) candidates.push(cookie.split('=')[1]); - - // 2. Fall back to the languages the browser asks for - const acceptLanguage = request.headers.get('accept-language'); - if (acceptLanguage) { - candidates.push( - ...acceptLanguage.split(',').map((entry) => entry.split(';')[0].trim()) - ); - } - - // 3. Pick the best supported match, or fall back to the default locale - return ( - determineLocale(candidates, [gtConfig.defaultLocale, ...gtConfig.locales]) ?? - gtConfig.defaultLocale - ); -} -``` - - - **Note:** This is exactly what `gt-next` and `gt-tanstack-start` do for you automatically — if you're on Next.js or TanStack Start, use those packages instead of writing a resolver by hand. - - - - **No loading state:** `` renders synchronously from the snapshot. Whatever loading behavior you want (pending UI, streaming) belongs in your framework's route loader, not in GT. - - --- ## Step 6: Mark content for translation @@ -320,7 +275,6 @@ That's it — your app is now multilingual. 🎉 ## Next steps - [**`` API**](/docs/react/api/components/gtprovider) — Full reference for the provider's props -- [**TanStack Start Quickstart**](/docs/tanstack-start) — The same setup with `parseLocale()` included - [**`` Component Guide**](/docs/react/guides/t) — Learn about variables, plurals, and advanced translation patterns - [**String Translation Guide**](/docs/react/guides/strings) — Deep dive into `useGT` - [**Deploying to Production**](/docs/react/tutorials/quickdeploy) — CI/CD setup, caching, and performance optimization diff --git a/docs/en-US/react/meta.json b/docs/en-US/react/meta.json index f4f369ba..25e3086c 100644 --- a/docs/en-US/react/meta.json +++ b/docs/en-US/react/meta.json @@ -29,6 +29,7 @@ "./api/types", "---Tutorials---", "./tutorials/quickstart-spa", + "./tutorials/spa-development-translations", "./tutorials/quickdeploy", "./tutorials/mini-shop" ], diff --git a/docs/en-US/react/tutorials/quickstart-spa.mdx b/docs/en-US/react/tutorials/quickstart-spa.mdx index 6a065c85..c0e69052 100644 --- a/docs/en-US/react/tutorials/quickstart-spa.mdx +++ b/docs/en-US/react/tutorials/quickstart-spa.mdx @@ -16,38 +16,38 @@ In a single-page app, `gt-react` runs entirely in the browser — you initialize
- **Server-rendered app?** If your framework renders on the server (TanStack Start, React Router, or a custom SSR setup), follow the [React quickstart](/docs/react) instead. + **Server-rendered app?** If your app renders on the server, follow the [React quickstart](/docs/react) instead. --- ## Step 1: Install the packages -`gt-react` is the library that powers translations in your app. `gt` is the CLI tool that prepares translations for production, and `@generaltranslation/compiler` is a build plugin for your bundler. +`gt-react` is the library that powers translations in your app. `gt` is the CLI tool that prepares your translations. ```bash npm i gt-react - npm i -D gt @generaltranslation/compiler + npm i -D gt ``` ```bash yarn add gt-react - yarn add --dev gt @generaltranslation/compiler + yarn add --dev gt ``` ```bash bun add gt-react - bun add --dev gt @generaltranslation/compiler + bun add --dev gt ``` ```bash pnpm add gt-react - pnpm add --save-dev gt @generaltranslation/compiler + pnpm add --save-dev gt ``` @@ -72,44 +72,15 @@ Create a **`gt.config.json`** file in your project root. This tells the library - **`defaultLocale`** — the language your app is written in (your source language). - **`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 4). +- **`files`** — tells the CLI where to save translation files. The `output` path should match the import path in your `loadTranslations` function (Step 3). - **File location:** Bundlers like Vite import translation files as modules, so they should live inside `src/`. If you load translations over HTTP instead (see the Create React App note in Step 4), use `"public/_gt/[locale].json"`. + **File location:** Bundlers like Vite import translation files as modules, so they should live inside `src/`. If you load translations over HTTP instead (see the Create React App note in Step 3), use `"public/_gt/[locale].json"`. --- -## Step 3: Add the compiler plugin - -Add the GT compiler plugin to your bundler config. It analyzes your source files at build time — validating translation calls and precomputing translation metadata so that work doesn't happen in the browser: - -```ts title="vite.config.ts" -import react from '@vitejs/plugin-react'; -import { vite as gtCompiler } from '@generaltranslation/compiler'; // [!code highlight] -import { defineConfig } from 'vite'; - -export default defineConfig({ - plugins: [gtCompiler(), react()], // [!code highlight] -}); -``` - - - - `@generaltranslation/compiler` also exports plugins for other bundlers — import the one that matches yours: - - ```ts - import { webpack as gtCompiler } from '@generaltranslation/compiler'; - // also available: rollup, esbuild - ``` - - - -See the [compiler concepts page](/docs/react/concepts/compiler) for everything the compiler can do, including automatic JSX wrapping. - ---- - -## Step 4: Create a translation loader +## Step 3: Create a translation loader In an SPA, `gt-react` needs a function to load translation files in the browser at runtime. Create a `loadTranslations` file: @@ -148,7 +119,7 @@ This function loads JSON translation files from your `src/_gt/` directory. The C --- -## Step 5: Initialize the library +## Step 4: Initialize the library Call **`initializeGTSPA`** once at startup, before your app renders. It takes your config and translation loader, determines the user's locale, and loads the translations for it. @@ -184,6 +155,10 @@ Then update the module script tag in your `index.html` to point at the new entry `initializeGTSPA` runs once at startup — the configuration is immutable for the lifetime of the app. After it resolves, every component and hook in your app can access translations. **You don't need to wrap your app in a provider.** + + **Want live translations in development?** Follow the [SPA development translations guide](/docs/react/tutorials/spa-development-translations) to add the compiler and development credentials. + + CRA may not support top-level `await`, so render inside `.then()`: @@ -212,7 +187,7 @@ Then update the module script tag in your `index.html` to point at the new entry --- -## Step 6: Mark content for translation +## Step 5: Mark content for translation Now, wrap any text you want translated with the **``** component. `` stands for "translate": @@ -233,9 +208,20 @@ 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 strings outside React components, use **`t()`**. It works at module level because `initializeGTSPA()` loads translations before the rest of your app: + +```ts title="src/navigation.ts" +import { t } from 'gt-react'; + +export const navigation = [ + { label: t('Home'), href: '/' }, + { label: t('About'), href: '/about' }, +]; +``` + --- -## Step 7: Add a language switcher +## Step 6: Add a language switcher Drop in a **``** so users can change languages: @@ -261,148 +247,15 @@ When the user picks a language, `gt-react` saves the choice to the `generaltrans --- -## Step 8: Set up environment variables (optional) - -To see translations in development, you need API keys from General Translation. These enable **on-demand translation** — your app translates content in real time as you develop. +## Step 7: Translate -Create a **`.env.local`** file with the correct prefix for your bundler: - - - - ```bash title=".env.local" - VITE_GT_PROJECT_ID="your-project-id" - VITE_GT_DEV_API_KEY="your-dev-api-key" - ``` - - `gt-react` reads these automatically during initialization — no extra code needed. The dev API key is only read in development, so it stays out of production bundles. - - - ```bash title=".env.local" - REACT_APP_GT_PROJECT_ID="your-project-id" - REACT_APP_GT_DEV_API_KEY="your-dev-api-key" - ``` - - CRA environment variables are not read automatically — pass them to `initializeGTSPA`: - - ```tsx title="src/index.tsx" - initializeGTSPA({ - defaultLocale: 'en', - locales: ['es', 'fr', 'ja'], - loadTranslations, - projectId: process.env.REACT_APP_GT_PROJECT_ID, - devApiKey: - process.env.NODE_ENV === 'development' - ? process.env.REACT_APP_GT_DEV_API_KEY - : undefined, - }); - ``` - - - -Get your free keys at [dash.generaltranslation.com](https://dash.generaltranslation.com/signup) or by running: +Run the translate command to generate translation files for every configured locale: ```bash -npx gt auth +npx gt translate ``` - - For development, use a key starting with `gtx-dev-`. Production keys (`gtx-api-`) are for CI/CD only. - - Client-side bundlers like Vite and CRA require environment variables to use specific prefixes (`VITE_` or `REACT_APP_`) to be exposed to the browser. Bare `GT_API_KEY` will not be available at runtime. - - - - - Yes. Without API keys, `gt-react` works as a standard i18n library. You won't get on-demand translation in development, but you can still: - - Provide your own translation files manually - - Use all components (``, ``, `LocaleSelector`, etc.) - - Run `npx gt generate` to create translation file templates, then translate them yourself - - - ---- - -## Step 9: See it working - -Start your dev server: - - - - ```bash - npm run dev - ``` - - - ```bash - yarn dev - ``` - - - ```bash - bun dev - ``` - - - ```bash - pnpm dev - ``` - - - -Open your app and use the language dropdown to switch languages. You should see your content translated. - - - **Note:** In development, translations happen on-demand — content may briefly appear in your source language the first time you switch to a new language, then update once the translation is ready. In production, translations are pre-generated and load instantly. - - ---- - -## Step 10: Translate strings (not just JSX) - -For plain strings — like `placeholder` attributes, `aria-label` values, or `alt` text — use the **`useGT`** hook: - -```tsx title="src/components/ContactForm.tsx" -import { useGT } from 'gt-react'; - -export default function ContactForm() { - const gt = useGT(); - - return ( -
- - -
- ); -} -``` - ---- - -## Step 11: Deploy to production - -In production, translations are pre-generated at build time (no real-time API calls). Add the translate command to your build script: - -```json title="package.json" -{ - "scripts": { - "build": "npx gt translate && " - } -} -``` - -Set your **production** environment variables in your hosting provider (Vercel, Netlify, etc.): - -```bash -GT_PROJECT_ID=your-project-id -GT_API_KEY=gtx-api-your-production-key -``` - - - Production keys start with `gtx-api-` (not `gtx-dev-`). Get one from [dash.generaltranslation.com](https://dash.generaltranslation.com). Never publicly expose your `GT_API_KEY`. - +The CLI scans your app, translates its content, and writes the results to the output path in `gt.config.json`. Run it again whenever your source content changes. That's it — your app is now multilingual. 🎉 @@ -440,5 +293,6 @@ That's it — your app is now multilingual. 🎉 - [**String Translation Guide**](/docs/react/guides/strings) — Deep dive into `useGT` - [**Variable Components**](/docs/react/guides/variables) — Handle dynamic content with ``, ``, ``, and `` - [**Pluralization**](/docs/react/api/components/plural) — Handle plural forms with the `` component +- [**SPA development translations**](/docs/react/tutorials/spa-development-translations) — See translations update live while developing - [**Deploying to Production**](/docs/react/tutorials/quickdeploy) — CI/CD setup, caching, and performance optimization - [**Shared Strings**](/docs/react/guides/shared-strings) — Translate text in arrays, config objects, and shared data with `msg()` diff --git a/docs/en-US/react/tutorials/spa-development-translations.mdx b/docs/en-US/react/tutorials/spa-development-translations.mdx new file mode 100644 index 00000000..4b01907a --- /dev/null +++ b/docs/en-US/react/tutorials/spa-development-translations.mdx @@ -0,0 +1,114 @@ +--- +title: SPA development translations +description: See translations update live while developing your single-page React app +--- + +Development translations let you preview translated content as you edit your SPA. They require the GT compiler and a development API key. + +**Prerequisites:** +- A single-page React app configured with the [SPA Quickstart](/docs/react/tutorials/quickstart-spa) +- A development API key that starts with `gtx-dev-` + +## Step 1: Install the compiler + +Install `@generaltranslation/compiler` as a development dependency: + + + + ```bash + npm i -D @generaltranslation/compiler + ``` + + + ```bash + yarn add --dev @generaltranslation/compiler + ``` + + + ```bash + bun add --dev @generaltranslation/compiler + ``` + + + ```bash + pnpm add --save-dev @generaltranslation/compiler + ``` + + + +## Step 2: Add the compiler plugin + +Add the plugin for your bundler. For Vite: + +```ts title="vite.config.ts" +import react from '@vitejs/plugin-react'; +import { vite as gtCompiler } from '@generaltranslation/compiler'; // [!code highlight] +import { defineConfig } from 'vite'; + +export default defineConfig({ + plugins: [gtCompiler(), react()], // [!code highlight] +}); +``` + + + + `@generaltranslation/compiler` also exports `webpack`, `rollup`, and `esbuild` plugins. Import the plugin that matches your bundler. + + ```ts + import { webpack as gtCompiler } from '@generaltranslation/compiler'; + ``` + + + +## Step 3: Add development credentials + +Get a development API key at [dash.generaltranslation.com](https://dash.generaltranslation.com/signup) or by running: + +```bash +npx gt auth +``` + +Then add your project ID and development API key to `.env.local`: + + + + ```bash title=".env.local" + VITE_GT_PROJECT_ID="your-project-id" + VITE_GT_DEV_API_KEY="your-dev-api-key" + ``` + + `gt-react` reads these values automatically during initialization. + + + ```bash title=".env.local" + REACT_APP_GT_PROJECT_ID="your-project-id" + REACT_APP_GT_DEV_API_KEY="your-dev-api-key" + ``` + + Pass the values to `initializeGTSPA()` because Create React App environment variables are not read automatically: + + ```tsx title="src/index.tsx" + await initializeGTSPA({ + defaultLocale: 'en', + locales: ['es', 'fr', 'ja'], + loadTranslations, + projectId: process.env.REACT_APP_GT_PROJECT_ID, + devApiKey: process.env.REACT_APP_GT_DEV_API_KEY, + }); + ``` + + + + + **Development only:** Use a key starting with `gtx-dev-`. Never expose a production key that starts with `gtx-api-` in browser code. + + +## Step 4: Start developing + +Start your development server and switch to a non-default locale. When you edit translatable content, the compiler registers the change and `gt-react` requests an updated development translation. + +## Next steps + +- [SPA Quickstart](/docs/react/tutorials/quickstart-spa) - Review the complete SPA setup +- [Compiler](/docs/react/concepts/compiler) - Learn about compiler validation and automatic JSX injection +- [Production vs Development](/docs/react/concepts/environments) - Understand how translation behavior changes by environment From be3591afd48dee1bff33284e8d4c5651de0a1895 Mon Sep 17 00:00:00 2001 From: Ernest McCarter Date: Mon, 13 Jul 2026 16:16:27 -0700 Subject: [PATCH 4/9] docs(react): remove Create React App guidance --- docs/en-US/react/index.mdx | 2 +- docs/en-US/react/tutorials/mini-shop.mdx | 47 +++++------------- docs/en-US/react/tutorials/quickstart-spa.mdx | 49 +------------------ .../spa-development-translations.mdx | 32 ++---------- 4 files changed, 19 insertions(+), 111 deletions(-) diff --git a/docs/en-US/react/index.mdx b/docs/en-US/react/index.mdx index da08c757..fc2ed828 100644 --- a/docs/en-US/react/index.mdx +++ b/docs/en-US/react/index.mdx @@ -10,7 +10,7 @@ By the end of this guide, your server-rendered React app will display content in - Node.js 18+ - **Client-side only app?** If your app renders entirely in the browser (Vite, Create React App), follow the [SPA quickstart](/docs/react/tutorials/quickstart-spa) instead — it skips the provider entirely. + **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. --- diff --git a/docs/en-US/react/tutorials/mini-shop.mdx b/docs/en-US/react/tutorials/mini-shop.mdx index fc774784..d8205c30 100644 --- a/docs/en-US/react/tutorials/mini-shop.mdx +++ b/docs/en-US/react/tutorials/mini-shop.mdx @@ -99,19 +99,13 @@ You can follow this tutorial without keys (it will render the default language). Learn more in [Production vs Development](/docs/react/concepts/environments). - + ```bash title=".env.local" copy VITE_GT_API_KEY="your-dev-api-key" VITE_GT_PROJECT_ID="your-project-id" ``` - - ```bash title=".env.local" copy - REACT_APP_GT_API_KEY="your-dev-api-key" - REACT_APP_GT_PROJECT_ID="your-project-id" - ``` - - Dashboard: https://dash.generaltranslation.com/signup - Or via CLI: @@ -363,38 +357,19 @@ export default function App() { Add a simple dev script to your `package.json`, then start the app. - - - ```json title="package.json" copy - { - "scripts": { - "dev": "vite" - } - } - ``` - - Run: - - ```bash - npm run dev - ``` - - - ```json title="package.json" copy - { - "scripts": { - "start": "react-scripts start" - } +```json title="package.json" copy +{ + "scripts": { + "dev": "vite" } - ``` +} +``` - Run: +Run: - ```bash - npm start - ``` - - +```bash +npm run dev +``` --- diff --git a/docs/en-US/react/tutorials/quickstart-spa.mdx b/docs/en-US/react/tutorials/quickstart-spa.mdx index c0e69052..2e430004 100644 --- a/docs/en-US/react/tutorials/quickstart-spa.mdx +++ b/docs/en-US/react/tutorials/quickstart-spa.mdx @@ -8,7 +8,7 @@ By the end of this guide, your single-page React app will display content in mul In a single-page app, `gt-react` runs entirely in the browser — you initialize it once at startup with `initializeGTSPA()`, and you don't need a provider component. **Prerequisites:** -- A client-side rendered React app (Vite, Create React App, webpack, or similar) +- A client-side rendered React app (Vite, webpack, or similar) - Node.js 18+ @@ -75,7 +75,7 @@ Create a **`gt.config.json`** file in your project root. This tells the library - **`files`** — tells the CLI where to save translation files. The `output` path should match the import path in your `loadTranslations` function (Step 3). - **File location:** Bundlers like Vite import translation files as modules, so they should live inside `src/`. If you load translations over HTTP instead (see the Create React App note in Step 3), use `"public/_gt/[locale].json"`. + **File location:** Bundlers like Vite import translation files as modules, so they should live inside `src/`. --- @@ -98,25 +98,6 @@ export default async function loadTranslations(locale: string) { This function loads JSON translation files from your `src/_gt/` directory. The CLI generates these files when you run `npx gt translate`. - - - CRA's webpack config blocks dynamic `import()` from outside `src/`. Store translations in `public/_gt/` and 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 @@ -159,32 +140,6 @@ Then update the module script tag in your `index.html` to point at the new entry **Want live translations in development?** Follow the [SPA development translations guide](/docs/react/tutorials/spa-development-translations) to add the compiler and development credentials. - - - CRA may not support top-level `await`, so render inside `.then()`: - - ```tsx title="src/index.tsx" - import { StrictMode } from 'react'; - import { createRoot } from 'react-dom/client'; - import { initializeGTSPA } from 'gt-react'; - import loadTranslations from './loadTranslations'; - import App from './App'; - - initializeGTSPA({ - defaultLocale: 'en', - locales: ['es', 'fr', 'ja'], - loadTranslations, - }).then(() => { - createRoot(document.getElementById('root')!).render( - - - - ); - }); - ``` - - - --- ## Step 5: Mark content for translation diff --git a/docs/en-US/react/tutorials/spa-development-translations.mdx b/docs/en-US/react/tutorials/spa-development-translations.mdx index 4b01907a..26fe1eac 100644 --- a/docs/en-US/react/tutorials/spa-development-translations.mdx +++ b/docs/en-US/react/tutorials/spa-development-translations.mdx @@ -70,34 +70,12 @@ npx gt auth Then add your project ID and development API key to `.env.local`: - - - ```bash title=".env.local" - VITE_GT_PROJECT_ID="your-project-id" - VITE_GT_DEV_API_KEY="your-dev-api-key" - ``` - - `gt-react` reads these values automatically during initialization. - - - ```bash title=".env.local" - REACT_APP_GT_PROJECT_ID="your-project-id" - REACT_APP_GT_DEV_API_KEY="your-dev-api-key" - ``` - - Pass the values to `initializeGTSPA()` because Create React App environment variables are not read automatically: +```bash title=".env.local" +VITE_GT_PROJECT_ID="your-project-id" +VITE_GT_DEV_API_KEY="your-dev-api-key" +``` - ```tsx title="src/index.tsx" - await initializeGTSPA({ - defaultLocale: 'en', - locales: ['es', 'fr', 'ja'], - loadTranslations, - projectId: process.env.REACT_APP_GT_PROJECT_ID, - devApiKey: process.env.REACT_APP_GT_DEV_API_KEY, - }); - ``` - - +`gt-react` reads these values automatically during initialization. **Development only:** Use a key starting with `gtx-dev-`. Never expose a production key that starts with `gtx-api-` in browser code. From 5f982d6f4325ac9a939d42b51114e434e1af2521 Mon Sep 17 00:00:00 2001 From: Ernest McCarter Date: Mon, 13 Jul 2026 16:16:53 -0700 Subject: [PATCH 5/9] docs(react): remove development latency accordion --- docs/en-US/react/index.mdx | 3 --- docs/en-US/react/tutorials/quickstart-spa.mdx | 3 --- 2 files changed, 6 deletions(-) diff --git a/docs/en-US/react/index.mdx b/docs/en-US/react/index.mdx index fc2ed828..a4619d60 100644 --- a/docs/en-US/react/index.mdx +++ b/docs/en-US/react/index.mdx @@ -256,9 +256,6 @@ That's it — your app is now multilingual. 🎉 Make sure your locale resolver reads the `generaltranslation.locale` cookie. If the server ignores it, the client and server will disagree about the current locale. - - This is expected. In development, translations happen on-demand (your content is translated in real time via the API). This delay **does not exist in production** — all translations are pre-generated by `npx gt translate`. - Ambiguous text can lead to inaccurate translations. For example, "apple" could mean the fruit or the company. Add a `$context` prop to help: diff --git a/docs/en-US/react/tutorials/quickstart-spa.mdx b/docs/en-US/react/tutorials/quickstart-spa.mdx index 2e430004..c9784028 100644 --- a/docs/en-US/react/tutorials/quickstart-spa.mdx +++ b/docs/en-US/react/tutorials/quickstart-spa.mdx @@ -226,9 +226,6 @@ That's it — your app is now multilingual. 🎉 - [Firefox](https://support.mozilla.org/en-US/kb/delete-cookies-remove-info-websites-stored) - [Safari](https://support.apple.com/en-mn/guide/safari/sfri11471/16.0/mac/11.0) - - This is expected. In development, translations happen on-demand (your content is translated in real time via the API). This delay **does not exist in production** — all translations are pre-generated by `npx gt translate`. - Ambiguous text can lead to inaccurate translations. For example, "apple" could mean the fruit or the company. Add a `$context` prop to help: From 72b42cdd57f31dcfb0087c03e934ccaa03a03d23 Mon Sep 17 00:00:00 2001 From: Ernest McCarter Date: Mon, 13 Jul 2026 16:18:59 -0700 Subject: [PATCH 6/9] docs(react): authenticate before SPA translation --- docs/en-US/react/tutorials/quickstart-spa.mdx | 21 +++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/docs/en-US/react/tutorials/quickstart-spa.mdx b/docs/en-US/react/tutorials/quickstart-spa.mdx index c9784028..ef00b894 100644 --- a/docs/en-US/react/tutorials/quickstart-spa.mdx +++ b/docs/en-US/react/tutorials/quickstart-spa.mdx @@ -202,9 +202,26 @@ When the user picks a language, `gt-react` saves the choice to the `generaltrans --- -## Step 7: Translate +## Step 7: Authenticate and translate -Run the translate command to generate translation files for every configured locale: +Before translating, authenticate with General Translation: + +```bash +npx gt auth +``` + +Follow the prompts to create an account or log in. When prompted for a key type, choose a production key. The command generates an API key and project ID, then adds them to `.env.local` in your project root: + +```bash title=".env.local" +GT_PROJECT_ID="your-project-id" +GT_API_KEY="gtx-api-your-production-key" +``` + + + **Keep your key private:** Do not commit `.env.local` or expose `GT_API_KEY` in browser code. + + +Then run the translate command to generate translation files for every configured locale: ```bash npx gt translate From 2c40aba520287e13b14f3535a4842c120ba54cd9 Mon Sep 17 00:00:00 2001 From: Ernest McCarter Date: Mon, 13 Jul 2026 16:20:35 -0700 Subject: [PATCH 7/9] docs(react): configure SPA compiler from GT config --- docs/en-US/react/tutorials/spa-development-translations.mdx | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/docs/en-US/react/tutorials/spa-development-translations.mdx b/docs/en-US/react/tutorials/spa-development-translations.mdx index 26fe1eac..4355398b 100644 --- a/docs/en-US/react/tutorials/spa-development-translations.mdx +++ b/docs/en-US/react/tutorials/spa-development-translations.mdx @@ -44,12 +44,15 @@ Add the plugin for your bundler. For Vite: import react from '@vitejs/plugin-react'; import { vite as gtCompiler } from '@generaltranslation/compiler'; // [!code highlight] import { defineConfig } from 'vite'; +import gtConfig from './gt.config.json'; // [!code highlight] export default defineConfig({ - plugins: [gtCompiler(), react()], // [!code highlight] + plugins: [gtCompiler({ ...gtConfig }), react()], // [!code highlight] }); ``` +Passing `gtConfig` keeps the compiler aligned with the locales and settings used by `initializeGTSPA()`. + `@generaltranslation/compiler` also exports `webpack`, `rollup`, and `esbuild` plugins. Import the plugin that matches your bundler. From 13049f8384f9c978a05b844905cd91c58e65922b Mon Sep 17 00:00:00 2001 From: Ernest McCarter Date: Mon, 13 Jul 2026 16:21:59 -0700 Subject: [PATCH 8/9] docs(react): trim SPA compiler explanation --- docs/en-US/react/tutorials/spa-development-translations.mdx | 2 -- 1 file changed, 2 deletions(-) diff --git a/docs/en-US/react/tutorials/spa-development-translations.mdx b/docs/en-US/react/tutorials/spa-development-translations.mdx index 4355398b..7302a181 100644 --- a/docs/en-US/react/tutorials/spa-development-translations.mdx +++ b/docs/en-US/react/tutorials/spa-development-translations.mdx @@ -51,8 +51,6 @@ export default defineConfig({ }); ``` -Passing `gtConfig` keeps the compiler aligned with the locales and settings used by `initializeGTSPA()`. - `@generaltranslation/compiler` also exports `webpack`, `rollup`, and `esbuild` plugins. Import the plugin that matches your bundler. From ca5b351ebd415983d3d7280c4080a9fd4ef68dfa Mon Sep 17 00:00:00 2001 From: Ernest McCarter Date: Mon, 13 Jul 2026 16:25:55 -0700 Subject: [PATCH 9/9] docs(react): align quickstart troubleshooting --- docs/en-US/react/index.mdx | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/docs/en-US/react/index.mdx b/docs/en-US/react/index.mdx index a4619d60..ef6971b0 100644 --- a/docs/en-US/react/index.mdx +++ b/docs/en-US/react/index.mdx @@ -253,8 +253,15 @@ That's it — your app is now multilingual. 🎉 ## Troubleshooting - - Make sure your locale resolver reads the `generaltranslation.locale` cookie. If the server ignores it, the client and server will disagree about the current locale. + + `gt-react` stores the user's language preference in a cookie called `generaltranslation.locale`. If you previously tested with a different language, this cookie may override your selection. Clear your cookies and try again. + + - [Chrome](https://support.google.com/chrome/answer/95647) + - [Firefox](https://support.mozilla.org/en-US/kb/delete-cookies-remove-info-websites-stored) + - [Safari](https://support.apple.com/en-mn/guide/safari/sfri11471/16.0/mac/11.0) + + + This is expected. In development, translations happen on-demand (your content is translated in real time via the API). This delay **does not exist in production** — all translations are pre-generated by `npx gt translate`. Ambiguous text can lead to inaccurate translations. For example, "apple" could mean the fruit or the company. Add a `$context` prop to help: