### Install next-intl
Source: https://next-intl.dev/docs/getting-started/app-router
Install the next-intl package using npm.
```bash
npm install next-intl
```
--------------------------------
### Basic Next.js Plugin Setup
Source: https://next-intl.dev/docs/usage/plugin
This is the minimum configuration required to integrate `next-intl` with your Next.js project using the App Router.
```typescript
import {
NextConfig
} from 'next';
import createNextIntlPlugin from 'next-intl/plugin';
const nextConfig: NextConfig = {};
const withNextIntl = createNextIntlPlugin();
export default withNextIntl(nextConfig);
```
--------------------------------
### PO Message Format Example
Source: https://next-intl.dev/docs/usage/plugin
Shows the structure of messages when using the PO format, which supports descriptions and file references.
```po
#. Advance to the next slide
#: src/components/Carousel.tsx
msgid "carousel.next"
msgstr "Right"
```
```po
#. Advance to the next slide
#: src/components/Carousel.tsx
msgid "5VpL9Z"
msgstr "Right"
```
--------------------------------
### i18n-check CLI Output Example
Source: https://next-intl.dev/docs/workflows/messages
This is an example of the output you might see when i18n-check finds missing keys in your message files.
```text
Found missing keys!
┌────────────────────┬───────────────────────────────┐
│ file │ key │
├────────────────────┼───────────────────────────────┤
│ messages/de.json │ NewsArticle.title │
└────────────────────┴───────────────────────────────┘
```
--------------------------------
### JSON Message Format Example
Source: https://next-intl.dev/docs/usage/plugin
Illustrates the structure of messages when using the JSON format. This format is suitable for simple key-value pairs.
```json
{
"greeting": "Hello"
}
```
```json
{
"NhX4DJ": "Hello"
}
```
--------------------------------
### Set up NextIntlClientProvider in _app.tsx (Single Language)
Source: https://next-intl.dev/docs/getting-started/pages-router
For single-language applications, configure `NextIntlClientProvider` with a fixed locale. This simplifies setup when only one language is supported.
```tsx
import {NextIntlClientProvider} from 'next-intl';
export default function App({Component, pageProps}) {
return (
);
}
```
--------------------------------
### Set up NextIntlClientProvider in _app.tsx (Multiple Languages)
Source: https://next-intl.dev/docs/getting-started/pages-router
Configure the `NextIntlClientProvider` in your `_app.tsx` file to manage internationalization. This setup dynamically uses the locale from the router and fetches messages based on the current locale.
```tsx
import {NextIntlClientProvider} from 'next-intl';
import {useRouter} from 'next/router';
export default function App({Component, pageProps}) {
const router = useRouter();
return (
);
}
```
--------------------------------
### Provide Locale to NextIntlClientProvider
Source: https://next-intl.dev/docs/usage/configuration
Example of providing a locale to the `NextIntlClientProvider` component. This is often used in client components to set the initial locale.
```jsx
...
```
--------------------------------
### Example of RTL text
Source: https://next-intl.dev/docs/usage/translations
This is an example of text in Arabic, which is a right-to-left (RTL) language. Proper RTL localization also requires providing the `dir` attribute, layout mirroring, and element mirroring.
```text
النص في اللغة العربية _مثلا_ يُقرأ من اليمين لليسار
```
--------------------------------
### Configuring NextIntlClientProvider with No Messages
Source: https://next-intl.dev/docs/environments/server-client-components
Example of rendering `NextIntlClientProvider` without passing any messages to the client. This can be used to optimize client-side performance by only sending necessary data.
```tsx
...
```
--------------------------------
### Configure Domain-Based Routing with Locale Prefixes
Source: https://next-intl.dev/docs/routing/configuration
Set up domain-based routing to serve localized content from different domains. This example combines `domains` with `localePrefix` to handle custom prefixes for specific locales.
```typescript
import {defineRouting} from 'next-intl/routing';
export const routing = defineRouting({
locales: ['en-US', 'en-CA', 'fr-CA', 'fr-FR'],
defaultLocale: 'en-US',
domains: [
{
domain: 'us.example.com',
defaultLocale: 'en-US',
locales: ['en-US']
},
{
domain: 'ca.example.com',
defaultLocale: 'en-CA',
locales: ['en-CA', 'fr-CA']
},
{
domain: 'fr.example.com',
defaultLocale: 'fr-FR',
locales: ['fr-FR']
}
],
localePrefix: {
mode: 'as-needed',
prefixes: {
// Cleaner prefix for `ca.example.com/fr`
'fr-CA': '/fr'
}
}
});
```
--------------------------------
### Create navigation helpers with next-intl
Source: https://next-intl.dev/docs/routing/setup
Use `createNavigation` with your routing configuration to get lightweight wrappers around Next.js navigation APIs like `Link`, `redirect`, `usePathname`, and `useRouter`.
```typescript
import {createNavigation} from 'next-intl/navigation';
import {routing} from './routing';
// Lightweight wrappers around Next.js' navigation
// APIs that consider the routing configuration
export const {Link, redirect, usePathname, useRouter, getPathname} =
createNavigation(routing);
```
--------------------------------
### Client Component Error Boundary Setup
Source: https://next-intl.dev/docs/environments/error-files
When defining an `error.js` file (a Client Component), use `NextIntlClientProvider` to provide necessary messages for error handling components.
```tsx
import pick from 'lodash/pick';
import {NextIntlClientProvider} from 'next-intl';
import {getMessages} from 'next-intl/server';
export default async function RootLayout(/* ... */) {
const messages = await getMessages();
return (
{children}
);
}
```
--------------------------------
### Configure Source Path for Monorepo
Source: https://next-intl.dev/docs/usage/plugin
Specify multiple paths for `srcPath` in a monorepo setup to include source code from different packages.
```typescript
srcPath: ['./src', '../ui'],
```
--------------------------------
### Cardinal Pluralization Example
Source: https://next-intl.dev/docs/usage/translations
Use the `plural` argument to express the pluralization of a given number of items. The `#` marker formats the value as a number.
```json
"message": "You have {count, plural, =0 {no followers yet} =1 {one follower} other {# followers}}."
```
```javascript
t('message', {count: 3580}); // "You have 3,580 followers."
```
--------------------------------
### Shared Component Example with useTranslations
Source: https://next-intl.dev/docs/environments/server-client-components
This component uses `useTranslations` and can render as either a Server or Client Component depending on where it's imported from. By default, it executes as a Server Component.
```tsx
import {useTranslations} from 'next-intl';
export default function UserDetails({user}) {
const t = useTranslations('UserProfile');
// This component will execute as a Server Component by default.
// However, if it is imported from a Client Component, it will
// execute as a Client Component.
return (
{t('title')}
{t('followers', {count: user.numFollowers})}
);
}
```
--------------------------------
### Select Enum-Based Values Example
Source: https://next-intl.dev/docs/usage/translations
Use the `select` argument to map identifiers to human-readable labels, similar to a JavaScript `switch` statement. The `other` case is required.
```json
"message": "{gender, select, female {She is} male {He is} other {They are}} online."
```
```javascript
t('message', {gender: 'female'}); // "She is online."
```
--------------------------------
### Ordinal Pluralization Example
Source: https://next-intl.dev/docs/usage/translations
Use the `selectordinal` argument to apply pluralization based on an order of items. `next-intl` uses `Intl.PluralRules` to detect the correct tag.
```json
"message": "It's your {year, selectordinal, one {#st} two {#nd} few {#rd} other {#th}} birthday!"
```
--------------------------------
### Server-Side Pagination with Translations
Source: https://next-intl.dev/docs/environments/server-client-components
Manage dynamic server-side state like pagination and reflect it in translated messages. This example shows a basic structure for a Pagination component that uses server-side translations.
```typescript
function Pagination({curPage, totalPages}) {
const t = useTranslations('Pagination');
return
{t('info', {curPage, totalPages})}
;
}
```
--------------------------------
### Mapping Locale with Select Example
Source: https://next-intl.dev/docs/usage/translations
When mapping values that may contain unsupported characters like dashes, use `replaceAll` to convert them to underscores before passing them to the `select` argument.
```json
"label": "{locale, select, en_GB {British English} en_US {American English} other {Unknown}}"
```
```javascript
const locale = 'en-GB';
t('message', {locale: locale.replaceAll('-', '_')});
```
--------------------------------
### Configure srcPath for External Packages
Source: https://next-intl.dev/docs/usage/extraction
Use `experimental.srcPath` in `next.config.ts` to include external package source directories for message extraction. This allows messages from sibling packages and installed modules to be extracted into the main app directory.
```javascript
const withNextIntl = createNextIntlPlugin({
experimental: {
extract: true,
messages: {
path: './messages',
format: 'json',
locales: 'infer',
sourceLocale: 'en'
},
srcPath: [
// First-party messages
'./src',
// Sibling packages in a monorepo
'../ui/src',
// Installed packages in `node_modules`
'./node_modules/@acme/components'
]
}
});
```
--------------------------------
### Root Layout for Static Export
Source: https://next-intl.dev/docs/routing/middleware
A minimal root layout component that simply passes through its children. This is required when a root page component (like the redirect example) is added to `app/page.tsx` for static exports.
```typescript
export default function RootLayout({children}) {
return children;
}
```
--------------------------------
### Type-Safe Message Keys with next-intl
Source: https://next-intl.dev/docs/workflows/typescript
Strictly type message keys to ensure you are using valid keys. This example demonstrates valid and invalid usage of the `useTranslations` hook.
```json
{
"About": {
"title": "Hello"
}
}
```
```typescript
import {useTranslations} from 'next-intl';
function About() {
// ✅ Valid namespace
const t = useTranslations('About');
// ✖️ Unknown message key
t('description');
// ✅ Valid message key
t('title');
}
```
--------------------------------
### Get current time with `useNow`
Source: https://next-intl.dev/docs/usage/dates-times
Use the `useNow` hook to get the current date and time. This hook ensures consistency across re-renders and can be configured to update continuously.
```javascript
import {useNow, useFormatter} from 'next-intl';
function FormattedDate({date}) {
const now = useNow();
const format = useFormatter();
format.relativeTime(date, now);
}
```
--------------------------------
### Set up next-intl middleware for routing
Source: https://next-intl.dev/docs/routing/setup
Create a middleware using `createMiddleware` from `next-intl/middleware` and configure the `matcher` to include or exclude specific pathnames. This handles locale matching.
```typescript
import createMiddleware from 'next-intl/middleware';
import {routing} from './i18n/routing';
export default createMiddleware(routing);
export const config = {
// Match all pathnames except for
// - … if they start with `/api`, `/trpc`, `/_next` or `/_vercel`
// - … the ones containing a dot (e.g. `favicon.ico`)
matcher: '/((?!api|trpc|_next|_vercel|.*\..*).*)'
};
```
--------------------------------
### Create Navigation APIs with Routing Config
Source: https://next-intl.dev/docs/routing/navigation
Use this to create navigation APIs when your routing configuration is known at build time. Import `createNavigation` from 'next-intl/navigation' and pass your routing configuration.
```typescript
import {createNavigation} from 'next-intl/navigation';
import {routing} from './routing';
export const {Link, redirect, usePathname, useRouter, getPathname} =
createNavigation(routing);
```
--------------------------------
### Define static ICU messages
Source: https://next-intl.dev/docs/usage/translations
Static messages in JSON files will be used as-is. This example shows a simple static message.
```json
"message": "Hello world!"
```
--------------------------------
### Provide Client-Side Configuration with NextIntlClientProvider
Source: https://next-intl.dev/docs/usage/configuration
Use `NextIntlClientProvider` in your root layout to provide configuration for Client Components. Props like `locale`, `messages`, `now`, `timeZone`, and `formats` can be inherited from Server Components.
```typescript
import {NextIntlClientProvider} from 'next-intl';
import {getMessages} from 'next-intl/server';
export default async function RootLayout(/* ... */) {
// ...
return (
...
);
}
```
--------------------------------
### Get Current Locale in Regular Components
Source: https://next-intl.dev/docs/usage/configuration
Import and use the `useLocale` hook in regular (client) components to access the current locale.
```javascript
import {useLocale} from 'next-intl';
const locale = useLocale();
```
--------------------------------
### Constructing a basic pathname
Source: https://next-intl.dev/docs/routing/navigation
Use getPathname to create a locale-prefixed URL. Ensure the '@/i18n/navigation' module is imported.
```javascript
import {getPathname} from '@/i18n/navigation';
// Will return `/en/about`
const pathname = getPathname({
locale: 'en',
href: '/about'
});
```
--------------------------------
### Define messages in JSON
Source: https://next-intl.dev/docs/usage/translations
Messages are typically defined in JSON files, grouped by locale. This example shows a simple structure for an 'About' page.
```json
{
"About": {
"title": "About us"
}
}
```
--------------------------------
### Configure Locale Prefix: Always (Default)
Source: https://next-intl.dev/docs/routing/configuration
Sets the routing to always include the locale prefix in the URL, which is the default behavior. For example, `/en/about`.
```typescript
import {defineRouting} from 'next-intl/routing';
export const routing = defineRouting({
// ...
localePrefix: 'always'
});
```
--------------------------------
### Basic React App Usage with IntlProvider
Source: https://next-intl.dev/docs/environments/core-library
Use `IntlProvider` and `useTranslations` for basic i18n in React apps. Ensure messages and locale are provided.
```javascript
import {IntlProvider, useTranslations} from 'use-intl';
// You can get the messages from anywhere you like. You can also
// fetch them from within a component and then render the provider
// along with your app once you have the messages.
const messages = {
App: {
hello: 'Hello {username}!'
}
};
function Root() {
return (
);
}
function App({user}) {
const t = useTranslations('App');
return
{t('hello', {username: user.name})}
;
}
```
--------------------------------
### Get Current Locale in Async Server Components
Source: https://next-intl.dev/docs/usage/configuration
Import and use the `getLocale` function in async Server Components to access the current locale.
```javascript
import {getLocale} from 'next-intl/server';
const locale = await getLocale();
```
--------------------------------
### Configure Global Decorator for NextIntlClientProvider in Storybook
Source: https://next-intl.dev/docs/workflows/storybook
Set up a global decorator in Storybook's preview.tsx to wrap stories with `NextIntlClientProvider`. This enables components to use hook-based APIs like `useTranslations` with a specified locale and messages. Support for async Server Components in Storybook is experimental.
```typescript
import {Preview} from '@storybook/react';
import defaultMessages from '../messages/en.json';
const preview: Preview = {
decorators: [
(Story) => (
)
]
};
export default preview;
```
--------------------------------
### Provide Request Configuration to Client Components
Source: https://next-intl.dev/docs/getting-started/app-router
Wrap the children in your root layout with NextIntlClientProvider to make the request configuration available to Client Components.
```typescript
import {NextIntlClientProvider} from 'next-intl';
type Props = {
children: React.ReactNode;
};
export default async function RootLayout({children}: Props) {
return (
{children}
);
}
```
--------------------------------
### Customize Alternate Links in Middleware
Source: https://next-intl.dev/docs/routing/configuration
Customize the `link` header by modifying the response in your middleware. This example shows how to remove the `x-default` entry from the alternate links.
```typescript
import createMiddleware from 'next-intl/middleware';
import LinkHeader from 'http-link-header';
import {NextRequest} from 'next/server';
import {routing} from './i18n/routing';
const handleI18nRouting = createMiddleware(routing);
export default async function middleware(request: NextRequest) {
const response = handleI18nRouting(request);
// Example: Remove the `x-default` entry
const link = LinkHeader.parse(response.headers.get('link'));
link.refs = link.refs.filter((entry) => entry.hreflang !== 'x-default');
response.headers.set('link', link.toString());
return response;
}
```
--------------------------------
### Render next-intl Component in Tests
Source: https://next-intl.dev/docs/environments/testing
Use `NextIntlClientProvider` to wrap your component for testing. Ensure you provide the locale and messages.
```javascript
import {render} from '@testing-library/react';
import {NextIntlClientProvider} from 'next-intl';
import {expect, it} from 'vitest';
import messages from '../../messages/en.json';
import UserProfile from './UserProfile';
it('renders', () => {
render(
);
});
```
--------------------------------
### Structure nested messages in JSON
Source: https://next-intl.dev/docs/usage/translations
Optionally, structure your messages as nested objects for better organization. This example shows a nested structure for authentication-related messages.
```json
{
"auth": {
"SignUp": {
"title": "Sign up",
"form": {
"placeholder": "Please enter your name",
"submit": "Submit"
}
}
}
}
```
--------------------------------
### Provide Picked Messages with NextIntlClientProvider
Source: https://next-intl.dev/docs/usage/configuration
Wrap components with `NextIntlClientProvider` and provide a subset of messages using a utility like `lodash/pick`. This is useful for managing which messages are available to the client.
```javascript
import {NextIntlClientProvider} from 'next-intl';
import {getMessages} from 'next-intl/server';
import pick from 'lodash/pick';
async function Component({children}) {
// Read messages configured via `i18n/request.ts`
const messages = await getMessages();
return (
...
);
}
```
--------------------------------
### Get Request Config with Locale-based Routing
Source: https://next-intl.dev/docs/usage/configuration
Use this when locale-based routing is enabled. It reads the locale from the `requestLocale` parameter, falling back to a default if necessary.
```typescript
export default getRequestConfig(async ({requestLocale}) => {
// Typically corresponds to the `[locale]` segment
const requested = await requestLocale;
const locale = hasLocale(routing.locales, requested)
? requested
: routing.defaultLocale;
return {
locale
// ...
};
});
```
--------------------------------
### Programmatic Navigation with useRouter
Source: https://next-intl.dev/docs/routing/navigation
Use `useRouter` to navigate programmatically within event handlers. It localizes the pathname automatically. Search parameters can be added via the `query` option, and the locale can be overridden.
```javascript
'use client';
import {useRouter} from '@/i18n/navigation';
const router = useRouter();
// When the user is on `/en`, the router will navigate to `/en/about`
router.push('/about');
// Search params can be added via `query`
router.push({
pathname: '/users',
query: {sortBy: 'name'}
});
// You can override the `locale` to switch to another language
router.replace('/about', {locale: 'de'});
```
```javascript
// 1. A final string (when not using `pathnames`)
router.push('/users/12');
// 2. An object (when using `pathnames`)
router.push({
pathname: '/users/[userId]',
params: {userId: '5'}
});
```
--------------------------------
### Retrieving Current Pathname with usePathname
Source: https://next-intl.dev/docs/routing/navigation
Use `usePathname` to get the current pathname without a locale prefix. If `pathnames` is enabled, it returns an internal pathname template.
```javascript
'use client';
import {usePathname} from '@/i18n/navigation';
// When the user is on `/en`, this will be `/`
const pathname = usePathname();
```
```javascript
// When the user is on `/de/über-uns`, this will be `/about`
const pathname = usePathname();
// When the user is on `/de/neuigkeiten/produktneuheit`,
// this will be `/news/[articleSlug]`
const pathname = usePathname();
```
--------------------------------
### Configure i18n Ally Workspace Settings
Source: https://next-intl.dev/docs/workflows/vscode-integration
Set the path to your message files and preferred key style for i18n Ally. Ensure the 'localesPaths' correctly points to your message directory.
```json
"i18n-ally.localesPaths": ["./path/to/your/messages"], // E.g. "./messages"
"i18n-ally.keystyle": "nested"
```
--------------------------------
### Get Request Config without Locale-based Routing
Source: https://next-intl.dev/docs/usage/configuration
Use this when locale-based routing is disabled. You can provide a static locale, fetch user settings, or read from cookies/headers.
```typescript
export default getRequestConfig(async () => {
// Provide a static locale, fetch a user setting,
// read from `cookies()`, `headers()`, etc.
const locale = 'en';
return {
locale
// ...
};
});
```
--------------------------------
### Basic Localized Link Usage
Source: https://next-intl.dev/docs/routing/navigation
Use the `Link` component to create localized navigation. It automatically handles pathname localization based on the current locale.
```javascript
import {Link} from '@/i18n/navigation';
// When the user is on `/en`, the link will point to `/en/about`
About
// Search params can be added via `query`
Users
// You can override the `locale` to switch to another language
// (this will set the `hreflang` attribute on the anchor tag)
Switch to German
```
--------------------------------
### Configure Experimental Messages Loading
Source: https://next-intl.dev/docs/usage/plugin
Set up a loader for TurboPack or Webpack to import messages as plain JavaScript objects. This configuration enables message loading from a specified path and format.
```typescript
const withNextIntl = createNextIntlPlugin({
experimental: {
messages: {
path: './messages',
format: 'json',
// Optional
precompile: true
}
}
});
```
--------------------------------
### Configure Vitest for next-intl
Source: https://next-intl.dev/docs/environments/testing
Configure Vitest to inline `next-intl` dependencies to avoid deoptimization issues with Next.js server components.
```typescript
import {defineConfig} from 'vitest/config';
export default defineConfig({
test: {
server: {
deps: {
// https://github.com/vercel/next.js/issues/77200
inline: ['next-intl']
}
}
}
});
```
--------------------------------
### Use Augmented Locale Type
Source: https://next-intl.dev/docs/workflows/typescript
After augmenting the Locale type, APIs that return or receive a locale will be type-checked. This example shows using `useLocale` which will be validated against the augmented type.
```typescript
import {useLocale} from 'next-intl';
// ✅ 'en' | 'de'
const locale = useLocale();
```
--------------------------------
### Importing Precompiled Messages
Source: https://next-intl.dev/docs/usage/plugin
Demonstrates how precompiled messages are imported into the application. These messages are processed by build tools like Turbo or Webpack.
```javascript
// ✅ Will be pre-processed by a Turbo- or Webpack loader
const messages = (await import(`../../messages/en.json`)).default;
```
--------------------------------
### useRouter
Source: https://next-intl.dev/docs/routing/navigation
Use `useRouter` for programmatic navigation within your application. It wraps Next.js's `useRouter` and automatically handles pathname localization.
```APIDOC
## useRouter
If you need to navigate programmatically, e.g. in an event handler, `next-intl` provides a convience API that wraps `useRouter` from Next.js and localizes the pathname accordingly.
```
'use client';
import {useRouter} from '@/i18n/navigation';
const router = useRouter();
// When the user is on `/en`, the router will navigate to `/en/about`
router.push('/about');
// Search params can be added via `query`
router.push({
pathname: '/users',
query: {sortBy: 'name'}
});
// You can override the `locale` to switch to another language
router.replace('/about', {locale: 'de'});
```
Depending on if you’re using the `pathnames` setting, dynamic params can either be passed as:
```
// 1. A final string (when not using `pathnames`)
router.push('/users/12');
// 2. An object (when using `pathnames`)
router.push({
pathname: '/users/[userId]',
params: {userId: '5'}
});
```
How can I change the locale for the current page?
By combining `usePathname` with `useRouter`, you can change the locale for the current page programmatically by navigating to the same pathname, while overriding the `locale`.
Depending on if you’re using the `pathnames` setting, you optionally have to forward `params` to potentially resolve an internal pathname.
```
'use client';
import {usePathname, useRouter} from '@/i18n/navigation';
import {useParams} from 'next/navigation';
const pathname = usePathname();
const router = useRouter();
// Without `pathnames`: Pass the current `pathname`
router.replace(pathname, {locale: 'de'});
// With `pathnames`: Pass `params` as well
const params = useParams();
router.replace(
// @ts-expect-error -- TypeScript will validate that only known `params`
// are used in combination with a given `pathname`. Since the two will
// always match for the current route, we can skip runtime checks.
{pathname, params},
{locale: 'de'}
);
```
**Learn more:**
Locale switcher
```
--------------------------------
### Reference Global Date and Time Range Formats
Source: https://next-intl.dev/docs/usage/dates-times
Reference pre-configured global formats by name for date and time ranges. You can optionally override specific options.
```javascript
// Use a global format
format.dateTimeRange(dateTimeA, dateTimeB, 'short');
// Optionally override some options
format.dateTimeRange(dateTimeA, dateTimeB, 'short', {year: 'numeric'});
```
--------------------------------
### Configure Message Loading in Consuming App
Source: https://next-intl.dev/docs/usage/extraction
In the consuming app's `next.config.ts`, configure `experimental.extract.path` for first-party messages and `experimental.messages.path` to include external package messages. This allows for separate extraction and loading strategies.
```typescript
const withNextIntl = createNextIntlPlugin({
experimental: {
// Only extract first-party messages
extract: {
path: './messages'
},
// Transform both first-party messages and external
// ones when loaded (e.g. for .po files)
messages: {
path: [
// First-party messages
'./messages',
// Sibling packages in a monorepo
'../ui/messages',
// Installed packages in `node_modules`
'./node_modules/@acme/components/messages'
],
// Depends on your preference
format: 'po',
locales: 'infer',
sourceLocale: 'en'
},
srcPath: './src'
}
});
```
--------------------------------
### Configure next.config.mjs for message declaration generation
Source: https://next-intl.dev/docs/workflows/typescript
Set up the next-intl plugin in your Next.js configuration to generate type declaration files for your message JSON files.
```javascript
import {createNextIntlPlugin} from 'next-intl/plugin';
const withNextIntl = createNextIntlPlugin({
experimental: {
// Provide the path to the messages that you're using in `AppConfig`
createMessagesDeclaration: './messages/en.json'
}
// ...
});
// ...
```
--------------------------------
### Configure Sherlock Project Settings for next-intl
Source: https://next-intl.dev/docs/workflows/vscode-integration
Set up Sherlock for next-intl by defining schema, source language, available languages, and the next-intl plugin with its path pattern. This configuration is essential for Sherlock to correctly process your internationalization files.
```json
{
"$schema": "https://inlang.com/schema/project-settings",
"sourceLanguageTag": "en",
"languageTags": ["en", "de"],
"modules": [
"https://cdn.jsdelivr.net/npm/@inlang/plugin-next-intl@latest/dist/index.js"
],
"plugin.inlang.nextIntl": {
"pathPattern": "./messages/{languageTag}.json"
}
}
```
--------------------------------
### Link with Locale Prefix Example
Source: https://next-intl.dev/docs/routing/navigation
When the `locale` prop is provided to `Link`, the `href` will always include a locale prefix, even if `localePrefix` is set to 'as-needed'. This ensures correct cookie handling before hydration.
```javascript
// Links to `/en/about`
About
```
--------------------------------
### Type-safe format names with next-intl
Source: https://next-intl.dev/docs/workflows/typescript
Demonstrates how to use type-safe format names for date, number, list, and display name formatting. Ensure the format string exists in your configured formats.
```typescript
function Component() {
const format = useFormatter();
// ✖️ Unknown format string
format.dateTime(new Date(), 'unknown');
// ✅ Valid format
format.dateTime(new Date(), 'short');
// ✅ Valid format
format.number(2, 'precise');
// ✅ Valid format
format.list(['HTML', 'CSS', 'JavaScript'], 'enumeration');
// ✅ Valid format
format.displayName('US', 'region');
}
```
--------------------------------
### Provide Individual Messages to Client Components
Source: https://next-intl.dev/docs/environments/server-client-components
Wrap dynamic client components with `NextIntlClientProvider` and pass only the necessary messages. This is useful when components cannot be moved to the server.
```typescript
import pick from 'lodash/pick';
import {NextIntlClientProvider, useMessages} from 'next-intl';
import ClientCounter from './ClientCounter';
export default function Counter() {
// Receive messages provided in `i18n/request.ts` …
const messages = useMessages();
return (
);
}
```
--------------------------------
### Conditional Rewrite with Next-Intl Middleware
Source: https://next-intl.dev/docs/routing/middleware
Handles custom rewrites after next-intl middleware has run. This example rewrites requests for '/[locale]/profile' to '/[locale]/profile/new' if a specific cookie is set, but only for successful responses.
```typescript
import createMiddleware from 'next-intl/middleware';
import {NextRequest, NextResponse} from 'next/server';
import {routing} from './i18n/routing';
const handleI18nRouting = createMiddleware(routing);
export default async function proxy(request: NextRequest) {
let response = handleI18nRouting(request);
// Additional rewrite when NEW_PROFILE cookie is set
if (response.ok) {
// (not for errors or redirects)
const [, locale, ...rest] = new URL(
response.headers.get('x-middleware-rewrite') || request.url
).pathname.split('/');
const pathname = '/' + rest.join('/');
if (
pathname === '/profile' &&
request.cookies.get('NEW_PROFILE')?.value === 'true'
) {
response = NextResponse.rewrite(
new URL(`/${locale}/profile/new`, request.url),
{headers: response.headers}
);
}
}
return response;
}
export const config = {
// Match only internationalized pathnames
matcher: '/((?!api|trpc|_next|_vercel|.*\..*).*)'
};
```
--------------------------------
### Use Global Formats for Display Names
Source: https://next-intl.dev/docs/usage/display-name
Reference globally configured formats for display names by passing a name as the second argument to `displayName`. You can optionally override specific options like `style`.
```javascript
// Use a global format
format.displayName('US', 'region');
// Optionally override some options
format.displayName('US', 'region', {style: 'narrow'});
```
--------------------------------
### Type-safe message arguments with next-intl
Source: https://next-intl.dev/docs/workflows/typescript
Demonstrates how to provide arguments to translations for type safety. Ensure the argument key matches the placeholder in the message string.
```json
{
"UserProfile": {
"title": "Hello {firstName}"
}
}
```
```typescript
function UserProfile({user}) {
const t = useTranslations('UserProfile');
// ✖️ Missing argument
t('title');
// ✅ Argument is provided
t('title', {firstName: user.firstName});
}
```
--------------------------------
### Integrate next-intl Plugin with Next.js Config (JavaScript)
Source: https://next-intl.dev/docs/getting-started/app-router
Set up the next-intl plugin in your next.config.js file to link the i18n/request.ts file.
```javascript
const createNextIntlPlugin = require('next-intl/plugin');
const withNextIntl = createNextIntlPlugin();
/** @type {import('next').NextConfig} */
const nextConfig = {};
module.exports = withNextIntl(nextConfig);
```
--------------------------------
### Define routing configuration with next-intl
Source: https://next-intl.dev/docs/routing/setup
Use `defineRouting` to configure supported locales and the default locale for your application. This is a central place for routing settings.
```typescript
import {defineRouting} from 'next-intl/routing';
export const routing = defineRouting({
// A list of all locales that are supported
locales: ['en', 'de'],
// Used when no locale matches
defaultLocale: 'en'
});
```
--------------------------------
### Include Intl Polyfills with next-intl
Source: https://next-intl.dev/docs/environments/runtime-requirements
Use this component to dynamically load polyfills for Intl APIs if your target browsers do not support them. It requires the `useLocale` hook from `next-intl` and constructs a script tag pointing to a polyfill service.
```tsx
import {
useLocale
} from 'next-intl';
import Script from 'next/script';
function IntlPolyfills() {
const locale = useLocale();
const polyfills = [
'Intl',
'Intl.Locale',
'Intl.DateTimeFormat',
`Intl.DateTimeFormat.~locale.${locale}`,
'Intl.NumberFormat',
`Intl.NumberFormat.~locale.${locale}`,
'Intl.PluralRules',
`Intl.PluralRules.~locale.${locale}`,
'Intl.RelativeTimeFormat',
`Intl.RelativeTimeFormat.~locale.${locale}`,
'Intl.ListFormat',
`Intl.ListFormat.~locale.${locale}`,
'Intl.DisplayNames',
`Intl.DisplayNames.~locale.${locale}`
];
return (
);
}
```
--------------------------------
### Providing Descriptions for Translators
Source: https://next-intl.dev/docs/usage/extraction
This snippet shows how to provide a description for a message, which aids translators (especially AI translators) in understanding the context of the message.
```javascript
```
--------------------------------
### next.config.ts Configuration with Custom Codec
Source: https://next-intl.dev/docs/usage/plugin
Configures the next-intl plugin to use a custom codec for message formatting. The codec path and file extension are specified.
```typescript
const withNextIntl = createNextIntlPlugin({
experimental: {
messages: {
format: {
codec: './CustomCodec.ts',
extension: '.json'
}
// ...
}
}
});
```
--------------------------------
### Constructing a pathname with query parameters
Source: https://next-intl.dev/docs/routing/navigation
Pass an object to `href` to include search parameters. This is useful for filtering or sorting.
```javascript
// Search params can be added via `query`
const pathname = getPathname({
locale: 'en',
href: {
pathname: '/users',
query: {sortBy: 'name'}
}
});
```
--------------------------------
### Configure Manifest with next-intl
Source: https://next-intl.dev/docs/environments/actions-metadata-route-handlers
When generating a manifest file outside of the `[locale]` dynamic segment, explicitly provide a `locale` to `getTranslations` as it cannot be inferred from the pathname.
```typescript
import {MetadataRoute} from 'next';
import {
getTranslations
} from 'next-intl/server';
export default async function manifest(): Promise {
// Pick a locale that is representative of the app
const locale = 'en';
const t = await getTranslations({
namespace: 'Manifest',
locale
});
return {
name: t('name'),
start_url: '/',
theme_color: '#101E33'
};
}
```
--------------------------------
### Integrate next-intl Plugin with Next.js Config (TypeScript)
Source: https://next-intl.dev/docs/getting-started/app-router
Set up the next-intl plugin in your next.config.ts file to link the i18n/request.ts file.
```typescript
import {NextConfig} from 'next';
import createNextIntlPlugin from 'next-intl/plugin';
const nextConfig: NextConfig = {};
const withNextIntl = createNextIntlPlugin();
export default withNextIntl(nextConfig);
```
--------------------------------
### Provide Messages in getStaticProps (Single Language)
Source: https://next-intl.dev/docs/getting-started/pages-router
When using a single language, specify the locale directly in `getStaticProps` and import the corresponding message file. This ensures the static props are correctly generated.
```tsx
export async function getStaticProps() {
const locale = 'en';
return {
props: {
// You can get the messages from anywhere you like. The recommended pattern
// is to put them in JSON files separated by locale (e.g. `en.json`).
messages: (await import(`../../messages/${locale}.json`)).default
}
};
}
```
--------------------------------
### Configure Source Path for `src` Folder
Source: https://next-intl.dev/docs/usage/plugin
Set the `srcPath` option to `./src` when your application source code is located within a `src` folder.
```typescript
srcPath: './src',
```
--------------------------------
### Configure Source Path for External Packages
Source: https://next-intl.dev/docs/usage/plugin
Include paths to external packages in `srcPath` to allow message extraction from their source code.
```typescript
srcPath: ['./src', './node_modules/@acme/components'],
```
--------------------------------
### Define Basic Routing Configuration
Source: https://next-intl.dev/docs/routing/configuration
Defines the core routing settings including supported locales and the default locale. This configuration is shared between the middleware and navigation APIs.
```typescript
import {defineRouting} from 'next-intl/routing';
export const routing = defineRouting({
// A list of all locales that are supported
locales: ['en', 'de'],
// Used when no locale matches
defaultLocale: 'en'
});
```
--------------------------------
### Provide Formats to NextIntlClientProvider
Source: https://next-intl.dev/docs/usage/configuration
Pass custom format definitions directly to the `NextIntlClientProvider` component. This allows for localized formatting of dates, numbers, lists, and display names in client components.
```typescript
...
```
--------------------------------
### Specify Multiple Messages Directories
Source: https://next-intl.dev/docs/usage/plugin
Provide an array of paths to `experimental.messages.path` to load messages from multiple directories, useful for monorepos or external packages.
```typescript
// Multiple directories with messages
path: ['./messages', '../packages/ui/messages'],
```
--------------------------------
### Configure Locale Prefix: As Needed
Source: https://next-intl.dev/docs/routing/configuration
Configures routing to use no prefix for the default locale (e.g., `/about`) while keeping prefixes for other locales (e.g., `/de/about`). Ensure your `matcher` detects unprefixed pathnames. The middleware may redirect users to a locale based on a cookie if no prefix is present.
```typescript
import {defineRouting} from 'next-intl/routing';
export const routing = defineRouting({
// ...
localePrefix: 'as-needed'
});
```
--------------------------------
### Precompile Messages Configuration
Source: https://next-intl.dev/docs/usage/plugin
Enables message precompilation during the build process for performance optimization. This reduces bundle size and improves runtime message formatting.
```typescript
const withNextIntl = createNextIntlPlugin({
experimental: {
messages: {
path: './messages',
format: 'json',
precompile: true
}
// ...
}
});
```
--------------------------------
### Custom Request Configuration with Options
Source: https://next-intl.dev/docs/usage/plugin
Use the `requestConfig` option to provide a custom path for request-specific configuration when combining with other plugin options.
```typescript
const withNextIntl = createNextIntlPlugin({
requestConfig: './somewhere/else/request.ts'
});
```
--------------------------------
### Configure Source Path Without `src` Folder
Source: https://next-intl.dev/docs/usage/plugin
Set the `srcPath` option to `./` when your application source code is not in a `src` folder.
```typescript
srcPath: './',
```
--------------------------------
### Define Routing with Custom Locale Prefixes
Source: https://next-intl.dev/docs/routing/configuration
Configure routing with custom locale prefixes by providing a locale-based mapping. This allows for user-facing URL customization while internally mapping to the correct locale. Ensure your `matcher` is adapted to these custom prefixes.
```typescript
import {defineRouting} from 'next-intl/routing';
export const routing = defineRouting({
locales: ['en-US', 'de-AT', 'zh'],
defaultLocale: 'en-US',
localePrefix: {
mode: 'always',
prefixes: {
'en-US': '/us',
'de-AT': '/eu/at'
// (/zh will be used as-is)
}
}
});
```
--------------------------------
### Using Explicit IDs for Messages
Source: https://next-intl.dev/docs/usage/extraction
Demonstrates how to assign an explicit ID to a message instead of relying on auto-generated keys. This is useful for messages used in multiple places that require distinct translations.
```javascript
```
--------------------------------
### Reference Global Number Formats
Source: https://next-intl.dev/docs/usage/numbers
You can reference globally configured number formats by passing their name as the second argument to the `format.number` function. Options can be overridden.
```javascript
// Use a global format
format.number(499.9, 'precise');
// Optionally override some options
format.number(499.9, 'price', {currency: 'USD'});
```
--------------------------------
### Configure Matcher for Base Path
Source: https://next-intl.dev/docs/routing/configuration
When using a `basePath` in your Next.js configuration, ensure your middleware `matcher` configuration correctly handles the root of the base path.
```typescript
export const config = {
// The `matcher` is relative to the `basePath`
matcher: [
// This entry handles the root of the base
// path and should always be included
'/'
// ... other matcher config
]
};
```
--------------------------------
### Dynamic Route Parameters with Link
Source: https://next-intl.dev/docs/routing/navigation
When using the `pathnames` setting, dynamic route parameters for the `Link` component can be passed either as a final string or as an object.
```javascript
// 1. A final string (when not using `pathnames`)
Susan
```
```javascript
// 2. An object (when using `pathnames`)
Susan
```
--------------------------------
### Provide All Messages to Client Components
Source: https://next-intl.dev/docs/environments/server-client-components
Make all messages available to Client Components by default. This is suitable for highly dynamic apps where most components utilize React's interactive features.
```typescript
import {NextIntlClientProvider} from 'next-intl';
export default async function RootLayout(/* ... */) {
return (
...
);
}
```
--------------------------------
### Render Raw HTML Markup
Source: https://next-intl.dev/docs/usage/translations
Use `t.markup` to render raw HTML markup. The provided mapping functions receive chunks as a string and must return a string.
```json
{
"markup": "This is important"
}
```
```javascript
// Returns 'This is important'
t.markup('markup', {
important: (chunks) => `${chunks}`
});
```