Skip to content
3.0 preview (see announcement)
Docs
Environments
Metadata & Route Handlers

Internationalization of Metadata & Route Handlers in Next.js 13

There are a few places in Next.js apps where you might need to apply internationalization outside of React components:

  1. Metadata API (opens in a new tab)
  2. Metadata files (opens in a new tab)
  3. Route Handlers (opens in a new tab)

next-intl/server provides a set of awaitable versions of the functions that you usually call as hooks from within components. Unlike the hooks, these functions require a locale that you receive from Next.js (opens in a new tab).

import {
  getTranslator,
  getFormatter,
  getNow,
  getTimeZone,
  getMessages
} from 'next-intl/server';
 
// The `locale` is received from Next.js via `params`
const locale = params.locale;
 
const t = await getTranslator(locale, 'Metadata');
const format = await getFormatter(locale);
const now = await getNow(locale);
const timeZone = await getTimeZone(locale);
const messages = await getMessages(locale);
💡

The request configuration that you've set up in i18n.ts is automatically inherited by these functions. The locale is the only exception that needs to be provided in comparison to the hooks.

Metadata API

To internationalize metadata like the page title, you can use functionality from next-intl in the generateMetadata (opens in a new tab) function that can be exported from pages and layouts.

app/[locale]/layout.tsx
import {getTranslator} from 'next-intl/server';
 
export async function generateMetadata({params: {locale}}) {
  const t = await getTranslator(locale, 'Metadata');
 
  return {
    title: t('title')
  };
}

Metadata files

If you need to internationalize content within metadata files (opens in a new tab), such as an Open Graph image, you can call APIs from next-intl in the exported function.

app/[locale]/opengraph-image.tsx
import {ImageResponse} from 'next/server';
import {getTranslator} from 'next-intl/server';
 
export default async function Image({params: {locale}}) {
  const t = await getTranslator(locale, 'OpenGraph');
  return new ImageResponse(<div style={{fontSize: 128}}>{t('title')}</div>);
}

Route Handlers

You can use next-intl in Route Handlers (opens in a new tab) too. The required locale can either be received from a search param, a layout segment or by parsing the accept-language header of the request.

app/api/hello/route.tsx
import {NextResponse} from 'next/server';
import {getTranslator} from 'next-intl/server';
 
export async function GET(request) {
  const {searchParams} = new URL(request.url);
  const locale = searchParams.get('locale');
 
  const t = await getTranslator(locale, 'Hello');
  return NextResponse.json({title: t('title')});
}