Implement Next.js Internationalized Routing



Implement support for localized channels using Next.js internationalized routing in your frontend application.


Next.js has built-in support for internationalized (i18n) routing. You can provide a list of locales, the default locale, and domain-specific locales and Next.js will automatically handle the routing.

This page shows how to implement Next.js i18n routing in your Bloomreach Content frontend application using the Reference SPA as an example.


The easiest way to get started is to create your channels using the Reference SPA channel template in the Experience manager and clone the Reference SPA frontend application from Github.

Set Up Localized Channels in Bloomreach Content

Set up your channels in Bloomreach Content using a naming pattern that includes a channel's locale. For example, <name>-<locale>:

  • mychannel-en
  • mychannel-fr

Your frontend application will rely on this naming pattern to match the selected locale to the correct channel and corresponding Delivery API endpoint.

Configure Endpoint Environment Variables

In your frontend application's .env file, add environment variables for each localized channel's Delivery API endpoint as in the following snippet (replace "mycontent" and "mychannel" with the relevant names):



If you don't have an .env file yet, you can create one by copying the provided .env.dist file.

Configure Locales

Add the i18n configuration to your frontend application's next.config.js file. Provide a list of locales that matches the endpoints you configured, as well as the defaultLocale:

module.exports = {
  // existing configuration here
  i18n: {
    locales: ['en', 'fr'],
    defaultLocale: 'en'

The above configuration uses sub-path routing by default. You may also add domains configuration in order to use domain routing. See Locale Strategies in the Next.js i18n documentation for details.

Update Your Frontend Code

In src/utils.ts, find the buildConfiguration function and adapt it so it accepts a locale parameter and uses it to select the correct endpoint environment variable:

export function buildConfiguration(path: string, query: ParsedUrlQuery, locale: any): Omit<Configuration, 'httpClient'> {
  const endpointQueryParameter = 'endpoint';
  const configuration: Record<string, any> = {
  const endpoint = query[endpointQueryParameter];
  if (!endpoint) {
    configuration.endpoint = process.env[`NEXT_PUBLIC_BRXM_ENDPOINT_${locale}`];
  return configuration;

In pages/[[...route]].tsx, adapt Index.getInitialProps to use the locale and pass it into the call to buildConfiguration:

Index.getInitialProps = async ({ req: request, res: response, asPath: path, query, locale }) => {
const configuration = buildConfiguration(path ?? '/', query, locale);

In pages/_error.tsx, do the same for Error.getInitialProps:

Error.getInitialProps = async ({ req: request, res: response, err, asPath, query, locale }) => {
const configuration = buildConfiguration(path, query, locale);