Localization and Internationalization in BigCommerce Catalyst describe the ability to present a personalized shopping experience for shoppers in different locales. Catalyst utilizes the Next.js App Router Internationalization library to detect and track a shopper’s preferred locale, enabling the delivery of content in the correct language, the application of locale-specific formatting, and also tailoring of product offerings to specific locales.
Here, we’ll discuss internationalization from the perspective of a single Catalyst channel supporting multiple locales. However, we’ll then discuss a potential multi-storefront setup as well.
Available Locales for Internationalization in BigCommerce Catalyst
Recall that the available languages for your Catalyst storefront are selected when initially setting up the storefront channel. You can also change the default and available languages at any time in the Localization tab when viewing the channel in the control panel.

Each available language is expressed with a locale code (for example, en). Available locales for the Catalyst storefront are fetched and stored in build-time config whenever a new build is run or when the development server is started. See the following key locations in the Catalyst project:
- next.config.ts: The SettingsQuery defined here is run to fetch available languages during build.
- build-config: Files related to the management of build-time locale config are located here.
- build-config/build-config.json: This file should exist in your project if the dev server has been run. This contains the generated locale config.
How Locale Is Detected
Catalyst uses the shopper’s browser preferences to detect locale by default, using the Accept-Language HTTP request header and matching this to one of the available locales configured on the storefront channel. If the detected locale is not available for the channel, then Catalyst will use the locale set as the default.
The Catalyst routing system, in tandem with the Next.js App Router Internationalization library, supports an optional URL segment to set locale:
mystore.com/fr/my-product
A user whose detected locale is different from the default will redirect to a URL like the above. If browsed directly, the explicit URL segment will also set the corresponding locale context. Whether locale is detected automatically, determined by the storefront’s default locale, or explicitly found in the request URL, the established locale context is available via the [locale] Next.js parameter.
See the following files for details on locale detection:
- middlewares/with-intl.ts – Initial locale detection with Next.js App Router Internationalization is done here, with context provided by the build-time locale config.
- middlewares/with-routes.ts – We’ve already seen the role this file plays in routing a request to its final destination. This includes explicitly including the locale segment in the rewritten URL.
Language and Currency Switchers
By default, Catalyst includes a language switcher and a currency switcher in the site header if multiple languages or currencies are available. The configured locales and currencies populate these switchers on the storefront channel. Therefore, available locales are dependent on the build-time config, and the language switcher utilizes the URL segment as described above.

Localization of Static Text
In this section, we’ll explore how Catalyst translates the static text that is part of your Catalyst application into the shopper’s language.
Storing Translations
In your Catalyst directory, there is a /messages/ subdirectory that is used for localization. Each language file in this directory corresponds with a locale, such as /messages/en.json. This file contains the default English phrases.
Each language that you want to support must have its own JSON file. Additionally, you must name each language file based on the BCP 47 specification of language tags and country or region codes.
Each translation file must also contain key-value pairs. Therefore, you can define translations based on pre-defined keys used to translate the Catalyst storefront’s basic e-commerce functionality. These translated values will display to shoppers as static string translations. It is common practice to use the existing en.json file as a template for the schema. For example, the en.json file contains the following translation keys and their English-language strings:
"ChangePassword": {
"title": "Change password",
"newPassword": "New password",
"confirmPassword": "Confirm password",
"passwordUpdated": "Password has been updated successfully!",
"somethingWentWrong": "Something went wrong. Please try again later."
},
Using Keys in React Components
Now, let’s look at how server and client components use translations. The example below shows how a server component uses translations. The call to getTranslations() with the locale and “namespace” pulls in the translated key-value pairs from the correct translation file.
import { getTranslations } from 'next-intl/server';
...
export default async function ChangePassword({ params, searchParams }: Props) {
...
const t = await getTranslations('Auth.ChangePassword');
...
return (
<ResetPasswordSection
...
confirmPasswordLabel = { t('confirmPassword') }
newPasswordLabel = { t('newPassword') }
title = { t('title') }
/>
);
}
On the other hand, client components handle the translation a little differently. The root app/[locale]layout.tsx file sets up a NextIntlClientProvider that is necessary for the appropriate client component hooks. Then, client components use the useTranslations method to translate static text:
import { useTranslations } from 'next-intl';
export function ProductFaqs({
...
}: {
...
}) {
...
const t = useTranslations('Components.Footer');
...
return allFaqs.length <= 0 ? '' : (
<section ...>
<div ...>
<h2 ...>
{ t('heading') }
</h2>
...
</div>
</section>
);
}
Localization of Dynamic Content
The most of the text presented to your shoppers will originate not with static strings in your code but with your catalog data, CMS content, or other merchandising integrations. While the localization strategy will depend on the features and capabilities of the providers you use for your content, here we’ll discuss the multi-language and multi-locale capabilities available in Catalyst’s built-in data sources.
BigCommerce Data
You’ll enter details for your BigCommerce catalog data in your store’s default language, but you can provide language-specific overrides for this content. Utilizing the GraphQL Admin API, it’s possible to set basic product information, SEO information, availability, and other details for a specific locale.
Catalyst sets the locale context of queries to the GraphQL Storefront API using the Accept-Language request header, so all rendered content will appear in a shopper’s preferred language if it exists. For example, this also ensures that cart data is associated with the correct locale.
The file client/index.ts is where the Accept-Language header is set.
Makeswift Content
Similar to catalog data, Catalyst identifies the locale context when it loads page content managed by the Makeswift visual editor. When you create a Makeswift site, it sets the initial locales to match the storefront’s available languages. You can then configure the available locales in the site settings.

The editor’s locale switcher makes it possible to custom-tailor not only text for specific locales, but also aspects of layout and content visibility.

Multi-Storefront
An alternative strategy to multi-language on a single storefront channel is to set up separate channels for different locales, which can be necessary if more than just language should vary. If available products, category structure, available currencies, or available shipping methods should vary by locale, then multi-storefront is likely an ideal strategy.
Path-Based
Catalyst has built-in support for mapping a locale path to a specific channel. The following example, in channels.config.ts, maps the /fr subpath to channel ID 12345:
const localeToChannelsMappings: Record<string, string> = {
fr: '12345',
};
With this mapping in place, when Catalyst detects French as the locale (such as when visiting a URL like mystore.com/fr/my-product), it sends API requests to the BigCommerce channel ID you specified.
Domain-Based
If your own setup requires each storefront to be on its own domain, there are multiple ways to accomplish this. In the most straightforward scenario, each domain should point to a separate production deployment of Catalyst, where varying environment configurations can handle the correct mapping to the storefront channel:

On the other hand, your requirements may necessitate a single deployment handling multiple domains:

Catalyst does not have built-in tooling for a true multi-tenant scenario such as this, but it can be accomplished with customization. See this Vercel guide and sample multi-tenant app.
Likely steps to consider include:
- Firstly, creating a [domain] Dynamic Route Segment similar to [locale], as seen in the example app.
- Then, setting the domain URL segment with middleware, as seen in the example app.
- Finally, consuming the domain route param and using it to conditionally set a channel ID where the API client is used.
Please contact us at manish@bay20.com or call us at +91-8800519180 / +91-9582784309 for any support related to Bigcommerce. You can also visit the Bigcommerce development page to check the services we offer.






