new·The score now tells you which way it movedA brain's exam only ever grows: its own material writes questions, and so does every question a real caller asked and did not get answered. The score is a percentage over that growing set, so a brain that learned more could post a smaller number — and this week three did. One of them answered two MORE questions than the week before and showed eighteen points less. Printed as a single percentage, that reads as decline to a reader and as punishment to anyone who contributes material.all news →
mozg.beta
Sign in

Next.js · Guides · all subjects

internationalization

13 notes, read out of this brain and free to use. Each one was extracted from a source and is re-checked against its exam.

Locale definition and examples

A locale is an identifier for a set of language and formatting preferences, usually including the preferred language and possibly geographic region. Examples: en-US (English as spoken in the United States), nl-NL (Dutch as spoken in the Netherlands), nl (Dutch with no specific region).

Routing internationalization strategies

Routing can be internationalized by either sub-path (e.g., /fr/products) or domain (e.g., my-site.fr/products). The user's language preferences from the browser's Accept-Language header should be used to select which locale to use.

Proxy-based locale detection and redirection

Use a proxy middleware function to check if the pathname contains a supported locale. If not, determine the user's preferred locale from the Accept-Language header and redirect to include the locale prefix. For example, a request to /products is redirected to /en-US/products. The proxy matcher should use '/((?!_next).*)', to skip internal paths.

App directory structure for i18n support

All special files inside app/ should be nested under app/[lang] to enable the Next.js router to dynamically handle different locales and forward the lang parameter to every layout and page. For example, at path /en-US/products, the lang parameter is "en-US".

Accessing lang parameter in pages and layouts

The lang parameter can be accessed in page and layout components via the params prop. In TypeScript, use PageProps<'/[lang]'> or LayoutProps<'/[lang]'> for strong typing. Pages and layouts should await params to access the lang value: const { lang } = await params.

Translation dictionary pattern

Maintain separate dictionary files (JSON objects) for each locale that map keys to localized strings. For example, dictionaries/en.json maps to English content and dictionaries/nl.json maps to Dutch content. Create a getDictionary function that dynamically imports the translation file for the requested locale.

Example: getDictionary implementation with imports

```ts import 'server-only' const dictionaries = { en: () => import('./dictionaries/en.json').then((module) => module.default), nl: () => import('./dictionaries/nl.json').then((module) => module.default), } export type Locale = keyof typeof dictionaries export const hasLocale = (locale: string): locale is Locale => locale in dictionaries export const getDictionary = async (locale: Locale) => dictionaries[locale]() ``` This pattern dynamically imports translation files and provides a type-safe hasLocale guard to ensure only supported locales are used.

Locale validation and error handling

Use hasLocale to narrow the locale type to supported locales and validate it. If an unsupported locale is detected, return a 404 using notFound() rather than allowing a runtime error.

Translation files only run on server

Layouts and pages in the app/ directory default to Server Components, so translation files and dictionary lookups run only on the server. Only the resulting HTML is sent to the browser, so translation file size does not affect client-side JavaScript bundle size.

Using next/root-params for locale sharing

Import lang from 'next/root-params' to access the locale from any Server Component or server-side utility without prop drilling. The lang() getter returns the current locale as a root parameter. Since every route is nested under app/[lang], lang is available as a root parameter throughout the application.

Example: getDictionary with next/root-params

```ts import { lang } from 'next/root-params' import { notFound } from 'next/navigation' const dictionaries = { en: () => import('./dictionaries/en.json').then((module) => module.default), nl: () => import('./dictionaries/nl.json').then((module) => module.default), } export type Locale = keyof typeof dictionaries export const hasLocale = (locale: string): locale is Locale => locale in dictionaries export const getDictionary = async () => { const locale = await lang() if (!hasLocale(locale)) notFound() return dictionaries[locale]() } ``` This approach eliminates the need to pass locale as a parameter to getDictionary, as it retrieves the locale internally from root-params.

next/root-params build-time safety

Files that import from 'next/root-params' do not need 'import server-only' because the import already fails at build time if used in a Client Component.

Root parameter getter scope limitations

Root parameter getters from next/root-params run in Server Components and server-side utilities, but not in Client Components, Server Actions, or Route Handlers.

Give your agent this brain