> This page is for Developer.

> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://docs.bigcommerce.com/llms.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://docs.bigcommerce.com/_mcp/server.

# Static Translations

> Translate the fixed text in a Catalyst storefront with per-locale message files, and enable locales in the control panel.

You can translate the fixed text in your storefront's interface, such as buttons and labels, into multiple languages with static strings. This page describes the required `messages/` subdirectory, the translation file format, and how to make a locale available to shoppers. Catalyst uses the [next-intl](https://next-intl.dev/docs/getting-started/app-router) library to handle localization.

> **Info**
>
> These files cover your Catalyst storefront only. Checkout renders from BigCommerce, so its static strings come from the channel's theme language files. See [Accessing Checkout Theme Files](/developer/docs/storefront/headless/theme-files).

## Required subdirectory

Each Catalyst project reserves a top level `/messages/` subdirectory for localization.
For your storefront to function properly, both the `/messages/` subdirectory and the `/messages/en.json` file, which contains the default English phrases, must be present.
You can localize static phrases by providing other JSON translation files in the `/messages/` directory.

The default language file, `en.json`, is in US English. You can adjust its phrase strings to meet your needs.

## Translation file

To translate static phrases, create a JSON file for each language you support.

Name your translation files based on the [BCP 47 specification](https://tools.ietf.org/html/bcp47) of language tags and country or region codes. For an overview of how these language tags are constructed, see [Language tags in HTML and XML](https://www.w3.org/International/articles/language-tags/).

You can find a list of code subtags in the [IANA Language Subtag Registry](https://www.iana.org/assignments/language-subtag-registry). These subtags are primitives that you can combine to create file name prefixes for individual regions. Here are some examples:

| Localization file name | Corresponding regional language variant | Subtags used                      |
| ---------------------- | --------------------------------------- | --------------------------------- |
| `en.json` (default)    | English                                 | en (English)                      |
| `en-US.json`           | US English                              | en (English) + US (United States) |
| `en-AU.json`           | Australian English                      | en (English) + AU (Australia)     |
| `es-US.json`           | US Spanish                              | es (Spanish) + US (United States) |
| `es-ES.json`           | Castilian Spanish                       | es (Spanish) + ES (Spain)         |
| `fr.json`              | French                                  | fr (French)                       |
| `fr-CA.json`           | Canadian French                         | fr (French) + CA (Canada)         |

### Translation keys

The JSON files should contain key-value pairs for each locale. You can define translations based on pre-defined keys used to translate the Catalyst storefront's [basic ecommerce functionality](/developer/docs/storefront/catalyst/overview#ecommerce-functionality). Shoppers see the translated values you specify as static string translations.

Use the existing `en.json` file as a template for the schema. You can only provide translated values for the translation keys specified in the template.

For example, the `en.json` file contains the following translation keys:

```json showLineNumbers={false}
"Home": {
  "FeaturedProducts": {
    "title": "Featured collection",
    "cta": "View more"
  },
  "NewestProducts": {
    "title": "New arrivals"
  }
}
```

In your newly-created JSON file, add a translation of the value to the new locale.

```json showLineNumbers={false}
"Home": {
  "FeaturedProducts": {
    "title": "Collection en vedette",
    "cta": "Voir plus"
  },
  "NewestProducts": {
    "title": "Nouveautés"
  }
}
```

## Enable the locale

Catalyst doesn't keep a list of locales in code. It reads the enabled locales, and the subfolder each one is served at, from your store's default channel (`BIGCOMMERCE_CHANNEL_ID`) at runtime. To make a new translation file available to shoppers, enable the matching locale on that channel in the control panel.

See [Add a locale in Catalyst](/developer/docs/storefront/catalyst/features/localization/multi-language/setup#add-a-locale-in-catalyst). No code change or redeploy is needed.

Name each translation file after the locale code you enable. For example, enabling French (`fr`) requires a `messages/fr.json` file.

> **Warning**
>
> Every enabled locale needs a matching translation file. If a shopper requests a locale that's enabled but has no file in `messages/`, its pages return a 404. Within a file that does exist, any key you leave out falls back to the English value in `en.json`.

## Load a locale from another channel (optional)

If you want a locale to load data from a different channel, map the locale to that channel ID in the `channels.config.ts` file. The mapping key is the locale code, not the URL subfolder. Subfolders are set per locale in the control panel, and can differ from the code (for example, `de` served at `/de-de`).

For example, to have the `fr` locale use a channel ID of `12345`, include the following:

```ts showLineNumbers={false}
const localeToChannelsMappings: Record<string, string> = {
  fr: '12345',
};
```

## Use keys in React components

In a **server** component, load messages with `getTranslations`:

```tsx showLineNumbers={false}
import { getTranslations } from 'next-intl/server';
// ...

export default async function Home() {
  const t = await getTranslations('Home');
  // ...

  return (
    <div>
      <FeaturedProductList
        products={featuredProducts}
        title={t('FeaturedProducts.title')}
      />
    </div>
  );
}
```

**Client** and **shared** components use regular hooks to translate messages:

```tsx showLineNumbers={false}
'use client';

import { useTranslations } from 'next-intl';
// ...

const Component = () => {
  const t = useTranslations('Cart');
  // ...

  return (
    <Button>
      {t('proceedToCheckout')}
    </Button>
  );
}
```

## Routing and locale detection

Catalyst uses next-intl's default [locale detection](https://next-intl.dev/docs/routing/middleware#locale-detection). When a shopper visits a URL without a locale subfolder, Catalyst picks a locale from the shopper's locale cookie, set when they choose a locale in the locale switcher, and otherwise from the `Accept-Language` request header. Detection only chooses among the locales enabled in the control panel. To change this behavior, edit the routing configuration in `createRouting` in `i18n/locale-routing.ts`.

## Next steps

* Follow the [Catalyst Multi-Language Setup](/developer/docs/storefront/catalyst/features/localization/multi-language/setup) tutorial to translate static strings, catalog data, and Makeswift content for a new locale.
* See the [next-intl documentation](https://next-intl.dev/docs/usage/translations) for message formatting options.