# General Translation React SDKs (gt-react, gt-next, gt-react-native): Configuring a Bazel SPA
URL: https://generaltranslation.com/en-US/docs/react/guides/spa/configuring-bazel-spa.mdx
Docs index: https://generaltranslation.com/llms.txt
Description: How to configure gt-react in a Bazel-powered single-page React application.

Configure the application runtime and optionally bundle generated translation catalogs with your Bazel build.

This guide prepares the application runtime. Mark user-facing content for translation separately.

## React Bazel SPA setup [#setup]

Initialize `gt-react` before the application entry point runs.

### 1. Install gt-react

Install the latest `gt-react` with the repository's preferred package manager. Skip this step when it is already installed.

### 2. Add a `gt.config.json` file to the root of the project

Add a `gt.config.json` file to the root of the project. This file will contain the configuration for the `gt-react` package.

The locales already present in the project or supplied to the setup task are authoritative. Preserve any existing `locales` and `defaultLocale` values. The values below are examples only. If the project has no locale configuration, do not infer locale requirements from these examples.

```json title="gt.config.json"
{
  "defaultLocale": "en",
  "locales": ["fr", "de"]
}
```

The optional [`src`](/docs/cli/reference/config#src) field designates the source files GT scans for inline content; when omitted, it defaults to these JavaScript and TypeScript globs under `src`, `app`, `pages`, and `components`:

```json title="gt.config.json"
{
  "defaultLocale": "en",
  "locales": ["fr", "de"],
  "src": [
    "src/**/*.{js,jsx,ts,tsx}",
    "app/**/*.{js,jsx,ts,tsx}",
    "pages/**/*.{js,jsx,ts,tsx}",
    "components/**/*.{js,jsx,ts,tsx}"
  ]
}
```

### 3. Initialize the library

[`initializeGTSPA`](/docs/react/reference/config#initialize-spa) configures module-level translation functions and awaits the initial catalog. Call it in a bootstrap module before importing code that translates at module scope.

Create `src/index.js` as the bootstrap file and import the existing `src/main.jsx` entry after initialization.

Locate the Bazel target that builds the browser bundle. Preserve the project's existing rule, dependencies, source declarations, and build options. Do not replace its bundler or add a second build pipeline.

The target must receive every file imported by the new bootstrap. Add the installed `gt-react` npm label to the dependency list. Add `gt.config.json` to `srcs` or `data` when it is not already covered by a declared input. The bootstrap file is covered automatically when the target already includes the source directory with a glob.

Then change the target's browser entry point from the existing React entry to the new bootstrap file. For an application using Aspect's `esbuild` rule at the repository root, the resulting target can look like this:

```python title="BUILD.bazel"
load("@aspect_rules_esbuild//esbuild:defs.bzl", "esbuild")

esbuild(
    name = "app",
    srcs = glob(["src/**"]) + ["gt.config.json"],
    deps = [
        ":node_modules/react",
        ":node_modules/react-dom",
        ":node_modules/gt-react",
    ],
    entry_point = "src/index.js",
    format = "esm",
    output = "app.js",
)
```

Use the labels and attributes already established by the project. For example, a target in a child Bazel package may use `//:gt.config.json` and `//:node_modules/gt-react` instead of root-package-relative labels. If the bundle depends on a first-party `js_library`, declare `gt-react` on the target that owns the importing source rather than duplicating it arbitrarily.

Use an async bootstrap function unless the existing Bazel bundle already supports top-level await. Do not change the output format or JavaScript target solely to enable top-level await.

```js title="src/index.js"
import { initializeGTSPA } from 'gt-react';

import gtConfig from '../gt.config.json';

async function bootstrap() {
  await initializeGTSPA(gtConfig);
  await import('./main');
}

void bootstrap();
```

Do not leave the original entry configured as a second browser entry. It must render only after [`initializeGTSPA`](/docs/react/reference/config#initialize-spa) resolves. Run the repository's normal Bazel build or test target for the application. Do not start a persistent development or preview server.

## Loading translations [#translations]

When [`initializeGTSPA`](/docs/react/reference/config#initialize-spa) is called without a [`loadTranslations`](/docs/react/reference/functions/load-translations) function, the runtime loads translations from the General Translation CDN only when a [`projectId`](/docs/react/reference/config#project-id) is available. To ship catalogs in the application bundle, configure an output path and a matching loader. The steps below use `src/_gt/[locale].json`.

### 1. Update the config

Set `files.gt.output` to the location where the CLI should write generated translation files.

Only add or merge the `files.gt.output` setting. Preserve the project's existing `locales` and `defaultLocale`; the values shown below remain examples and must not replace the project's configured locales.

Typically in a Bazel-powered application, the translations will be stored in the `src/_gt` directory. This is so we can use the translations in the application code.

```json title="gt.config.json"
{
  "locales": ["fr", "zh"],
  "defaultLocale": "en",
  "files": {
    "gt": {
      "output": "src/_gt/[locale].json"
    }
  }
}
```

### 2. Add the stubs

Create one empty JSON file for each target locale already configured in `gt.config.json`, excluding the default locale. These stubs let imports resolve before translation bundles exist. The `fr` and `zh` files below illustrate the example configuration from this guide; create files for the project's actual configured target locales instead. If no target locales are configured, do not invent locales or create placeholder files.

<Files>
  <Folder name="src">
    <Folder name="_gt">
      <File name="fr.json" />
      <File name="zh.json" />
    </Folder>
  </Folder>
</Files>

```json title="src/_gt/fr.json"
{}
```

```json title="src/_gt/zh.json"
{}
```

Ensure the owning Bazel target declares these JSON files. An existing `glob(["src/**"])` includes them; otherwise add the files to the target's `srcs` or `data` according to the rule's API.

### 3. Add the loader

Create `src/loadTranslations.js` to load the translations. It must resolve to the same output location configured in `files.gt.output`.

List every configured target locale explicitly in `translationLoaders`. Each loader must use a literal import path so Bazel and the underlying bundler can discover every translation file at build time. The `fr` and `zh` entries below match this guide's example configuration; use the project's actual configured target locales instead.

```js title="src/loadTranslations.js"
const translationLoaders = {
  fr: () => import('./_gt/fr.json'),
  zh: () => import('./_gt/zh.json'),
};

export default async function loadTranslations(locale) {
  const loader = translationLoaders[locale];
  if (!loader) {
    console.warn(`No translations found for locale "${locale}"`);
    return {};
  }

  const translations = await loader();
  return translations.default;
}
```

### 4. Update the initializer

Update the initializer to use the new loader function. Preserve the async bootstrap form and the original application-entry import.

```js title="src/index.js"
import { initializeGTSPA } from 'gt-react';

import gtConfig from '../gt.config.json';
import loadTranslations from './loadTranslations';

async function bootstrap() {
  await initializeGTSPA({ ...gtConfig, loadTranslations });
  await import('./main');
}

void bootstrap();
```

Run the Bazel build or test target again after adding the bundled translations.

## Next steps

- /docs/react/guides/spa/internationalizing-react-spa
- /docs/react/guides/developing-spa-translations
- /docs/react/guides/storing-translations
- /docs/react/guides/managing-locales

## Sitemap

See the full [sitemap](https://generaltranslation.com/sitemap.md) for all pages.
