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

Welcome to my app

-

This content will be translated automatically.

-
-
- ); +export default function Header() { + return ; } ``` -`LocaleSelector` renders a dropdown populated with the languages from your `gt.config.json`. +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 7: Set up environment variables (optional) +## 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: +If your framework builds with Vite, `gt-react` reads these automatically during initialization: - - - ```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" - ``` - - +```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: @@ -251,81 +219,11 @@ 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. --- -## 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 +## 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: @@ -337,7 +235,7 @@ In production, translations are pre-generated at build time (no real-time API ca } ``` -Set your **production** environment variables in your hosting provider (Vercel, Netlify, etc.): +Set your **production** environment variables in your hosting provider: ```bash GT_PROJECT_ID=your-project-id @@ -366,13 +264,13 @@ That's it — your app is now multilingual. 🎉 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: + 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 + Apple ``` - Both `` and `useGT()` support the `context` option. + Both `` and `useGT()` support the `$context` option. @@ -380,9 +278,7 @@ That's it — your app is now multilingual. 🎉 ## Next steps +- [**`` API**](/docs/react/api/components/gtprovider) — Full reference for the provider's props - [**`` 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/meta.json b/docs/en-US/react/meta.json index 193b540d..25e3086c 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/spa-development-translations", "./tutorials/quickdeploy", "./tutorials/mini-shop" ], 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 new file mode 100644 index 00000000..ef00b894 --- /dev/null +++ b/docs/en-US/react/tutorials/quickstart-spa.mdx @@ -0,0 +1,267 @@ +--- +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, 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 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 your translations. + + + + ```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). + + + **File location:** Bundlers like Vite import translation files as modules, so they should live inside `src/`. + + +--- + +## 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: + +```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`. + +--- + +## 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. + +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.** + + + **Want live translations in development?** Follow the [SPA development translations guide](/docs/react/tutorials/spa-development-translations) to add the compiler and development credentials. + + +--- + +## 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. + +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 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`. + +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 7: Authenticate and translate + +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 +``` + +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. 🎉 + +--- + +## 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) + + + 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 +- [**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..7302a181 --- /dev/null +++ b/docs/en-US/react/tutorials/spa-development-translations.mdx @@ -0,0 +1,93 @@ +--- +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'; +import gtConfig from './gt.config.json'; // [!code highlight] + +export default defineConfig({ + plugins: [gtCompiler({ ...gtConfig }), 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. + + + **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