### 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 (