# General Translation React SDKs (gt-react, gt-next, gt-react-native): Developing with SPA translations URL: https://generaltranslation.com/en-GB/docs/react/guides/developing-spa-translations.mdx --- title: Developing with SPA translations description: How to preview General Translation translations while developing a single-page React app. related: links: - /docs/react/guides/storing-translations - /docs/react/guides/configuring - /docs/react/guides/translating-jsx - /docs/react/guides/managing-locales --- 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/react-spa-quickstart) * A development API key that starts with `gtx-dev-` **CommonJS limitation:** Development hot reloading requires ESM because the compiler injects top-level `await`. It does not work in applications compiled as CommonJS. Production translations still work with the CommonJS startup pattern in the [SPA Quickstart](/docs/react/react-spa-quickstart). ## Setup [#setup] ### 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 ``` ### 2. Add the compiler plugin Enable development hot reload in the config shared by the CLI and compiler: ```json title="gt.config.json" { "files": { "gt": { "output": "src/_gt/[locale].json", "parsingFlags": { "devHotReload": true } } } } ``` Then add the plugin for your bundler. ```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: [react(), gtCompiler({ ...gtConfig })], // [!code highlight] }); ``` Install `dotenv` as a development dependency so webpack can read `.env` and `.env.local`, then add the compiler before the rest of your plugins. Use `DefinePlugin` to expose only development credentials to browser code: ```js title="webpack.config.mjs" import { webpack as gtCompiler } from '@generaltranslation/compiler'; import dotenv from 'dotenv'; import webpack from 'webpack'; import gtConfig from './gt.config.json' with { type: 'json' }; dotenv.config({ path: '.env' }); dotenv.config({ path: '.env.local', override: true }); export default (_env, argv) => { const isProduction = (argv.mode ?? 'production') === 'production'; return { // Keep your existing webpack settings. plugins: [ gtCompiler({ ...gtConfig }), new webpack.DefinePlugin({ 'process.env.GT_PROJECT_ID': JSON.stringify( isProduction ? '' : (process.env.GT_PROJECT_ID ?? '') ), 'process.env.GT_DEV_API_KEY': JSON.stringify( isProduction ? '' : (process.env.GT_DEV_API_KEY ?? '') ), }), ], }; }; ``` See the complete [`gt-react` webpack example](https://github.com/generaltranslation/gt/tree/main/examples/webpack-spa) for loaders, local translation files, and development server settings. Register the compiler before your other Rollup plugins: ```js title="rollup.config.mjs" import { rollup as gtCompiler } from '@generaltranslation/compiler'; export default { input: 'src/index.ts', plugins: [ gtCompiler(), // Your other Rollup plugins ], }; ``` Rollup cannot analyse a fully dynamic translation import. List each locale with a static import specifier: ```ts title="src/loadTranslations.ts" const translationLoaders = { es: () => import('./_gt/es.json'), fr: () => import('./_gt/fr.json'), }; export default async function loadTranslations(locale: string) { const loader = translationLoaders[locale as keyof typeof translationLoaders]; return loader ? (await loader()).default : {}; } ``` Plain Rollup does not provide the development credential integration shown for Vite and webpack. Regenerate local translation files when source content changes. See the complete [`gt-react` Rollup example](https://github.com/generaltranslation/gt/tree/main/examples/rollup-spa). Add the Rspack adapter to your plugins: ```js title="rspack.config.mjs" import { rspack as gtCompiler } from '@generaltranslation/compiler'; export default { plugins: [gtCompiler()], }; ``` Development translation also requires exposing `GT_PROJECT_ID` and `GT_DEV_API_KEY` to browser code without including either value in production bundles. Add the esbuild adapter to the `plugins` array: ```js title="build.mjs" import { build } from 'esbuild'; import { esbuild as gtCompiler } from '@generaltranslation/compiler'; await build({ entryPoints: ['src/index.tsx'], bundle: true, outdir: 'dist', plugins: [gtCompiler()], }); ``` *Note: The esbuild adapter does not support automatic JSX injection. Wrap translatable JSX explicitly or use another adapter when `enableAutoJsxInjection` is required.* See the complete [`gt-react` Vite example](https://github.com/generaltranslation/gt/tree/main/examples/vite-spa) for a full Vite setup. ### 3. Add development credentials Get a development API key at [dash.generaltranslation.com](https://dash.generaltranslation.com/en-US/signin) or by running: ```bash npx gt auth ``` Then add your project ID and development API key to `.env.local` and pass them to your initialisation function: ```bash title=".env.local" VITE_GT_PROJECT_ID="your-project-id" VITE_GT_DEV_API_KEY="your-dev-api-key" ``` ```ts await initializeGTSPA({ ...gtConfig, projectId: import.meta.env.VITE_GT_PROJECT_ID, devApiKey: import.meta.env.VITE_GT_DEV_API_KEY, loadTranslations, }); ``` ```bash title=".env.local" GT_PROJECT_ID="your-project-id" GT_DEV_API_KEY="your-dev-api-key" ``` ```ts await initializeGTSPA({ ...gtConfig, projectId: process.env.GT_PROJECT_ID, devApiKey: process.env.GT_DEV_API_KEY, loadTranslations, }); ``` The webpack config above replaces both values with empty strings in production builds, so development credentials are not included in the production bundle. **Development only:** Use a key starting with `gtx-dev-`. Never expose a production key that starts with `gtx-api-` in browser code. ### 4. Start developing Start your development server and switch to a non-default locale. When you edit translatable content, the compiler recognises the change and `gt-react` requests an updated development translation. ## Next steps - /docs/react/guides/storing-translations - /docs/react/guides/configuring - /docs/react/guides/translating-jsx - /docs/react/guides/managing-locales