Receber por email
← Voltar para o catálogo

web-i18n-next-intl

Type-safe i18n for Next.js App Router

11estrelas
Atualizado há 7 meses

Ver no GitHub ↗ Licença: MIT

Como adicionar

/plugin marketplace add agents-inc/skills

O comando exato pode variar conforme o repositório. Confira o README no GitHub.

Para o autor da skill

Cole no README do seu repo

Mostra que sua skill está catalogada na Skillteca, gera backlink e tráfego rastreável.

[![Skillteca](https://www.skillteca.com.br/api/badge/web-i18n-next-intl/svg)](https://www.skillteca.com.br/skills/web-i18n-next-intl)

Alerta por categoria

Receba novas skills de Design e Frontend toda segunda

1 email curto, só com as skills novas de Design e Frontend. 4 minutos de leitura, sem spam, cancela com 1 clique.

Você confirma o email no primeiro envio. Sem spam. Cancela com 1 clique.

Ler descrição completa

next-intl Internationalization Patterns

Quick Guide: Use next-intl for type-safe internationalization in Next.js App Router. useTranslations for messages, useFormatter for dates/numbers, middleware for locale detection. Call setRequestLocale(locale) for static rendering.

<critical_requirements>

CRITICAL: Before Using This Skill

All code must follow project conventions in CLAUDE.md (kebab-case, named exports, import ordering, import type, named constants)

(You MUST call setRequestLocale(locale) at the top of ALL page/layout components for static rendering)

(You MUST validate locale against routing.locales before using it)

(You MUST use NextIntlClientProvider in the root layout to enable client-side hooks)

(You MUST use named constants for locale codes - NO inline locale strings)

</critical_requirements>

Auto-detection: next-intl, useTranslations, useFormatter, useLocale, NextIntlClientProvider, i18n routing, locale detection, ICU message format

When to use:

  • Implementing internationalization in Next.js App Router
  • Rendering localized messages with interpolation and pluralization
  • Formatting dates, numbers, and relative time per locale
  • Setting up locale-based routing and middleware
  • Generating static pages for multiple locales

Key patterns covered:

  • Project setup with routing.ts, request.ts, and middleware
  • useTranslations hook for messages with ICU syntax
  • useFormatter hook for dates, numbers, and lists
  • Static rendering with generateStaticParams and setRequestLocale
  • TypeScript integration for type-safe translation keys

When NOT to use:

  • Simple single-locale applications (skip i18n complexity)
  • Pages Router (different API - use Pages Router docs)
  • Non-Next.js React applications (use react-intl instead)

Detailed Resources:

  • For code examples, see [examples/](examples/) (core.md, formatting.md, pluralization.md, markup.md)
  • For decision frameworks and anti-patterns, see [reference.md](reference.md)

<philosophy>

Philosophy

next-intl follows the principle of type-safe, locale-aware rendering with ICU message format support. Translations are organized as namespaced JSON objects, loaded per-request for Server Components and provided via context for Client Components. The middleware handles locale detection automatically, while setRequestLocale enables static rendering at build time.

Core principles:

  1. Server-first: Load translations in Server Components for better performance
  2. Type-safe keys: TypeScript augmentation catches missing translations at compile time
  3. ICU standard: Use industry-standard ICU message syntax for pluralization and formatting
  4. Static-friendly: Support static generation with explicit locale parameters

</philosophy>

<patterns>

Core Patterns

Pattern 1: Project Setup

Set up next-intl with the App Router using the standard file structure.

File Structure

src/
  i18n/
    routing.ts       # Locale configuration
    request.ts       # Server-side locale resolution
    navigation.ts    # Locale-aware Link, useRouter
  proxy.ts           # Locale detection and routing (middleware.ts before Next.js 16)
  app/
    [locale]/
      layout.tsx     # Root layout with NextIntlClientProvider
      page.tsx       # Pages within locale segment
messages/
  en.json            # English translations
  de.json            # German translations
Note: In Next.js 16+, middleware.ts was renamed to proxy.ts. If using Next.js 15 or earlier, use middleware.ts.

Configuration Files

// src/i18n/routing.ts
import { defineRouting } from "next-intl/routing";

export const SUPPORTED_LOCALES = ["en", "de", "fr"] as const;
export const DEFAULT_LOCALE = "en";

export const routing = defineRouting({
  locales: SUPPORTED_LOCALES,
  defaultLocale: DEFAULT_LOCALE,
});

export type Locale = (typeof routing.locales)[number];

Why good: named constants for locales enable type-safe usage throughout app, exported Locale type enables type checking of locale parameters

// src/i18n/request.ts
import { getRequestConfig } from "next-intl/server";
import { hasLocale } from "next-intl";
import { routing } from "./routing";

export default getRequestConfig(async ({ requestLocale }) => {
  const requested = await requestLocale;
  const locale = hasLocale(routing.locales, requested)
    ? requested
    : routing.defaultLocale;

  return {
    locale,
    messages: (await import(`../../messages/${locale}.json`)).default,
  };
});

Why good: validates locale against supported list, falls back to default for invalid locales, dynamically imports only needed translation file

// src/i18n/navigation.ts
import { createNavigation } from "next-intl/navigation";
import { routing } from "./routing";

export const { Link, redirect, usePathname, useRouter, getPathname } =
  createNavigation(routing);

Why good: wraps Next.js navigation APIs with locale awareness, Link automatically includes locale prefix

// src/proxy.ts (Next.js 16+) or src/middleware.ts (Next.js 15 and earlier)
import createMiddleware from "next-intl/middleware";
import { routing } from "./i18n/routing";

export default createMiddleware(routing);

export const config = {
  matcher: "/((?!api|_next|_vercel|.*\\..*).*)",
};

Why good: proxy/middleware handles locale detection from URL, cookies, and Accept-Language header, matcher excludes API routes and static files. Add additional exclusions for your API framework routes as needed.

Pattern 2: Root Layout with Provider

Wrap the application with NextIntlClientProvider and validate the locale.

// src/app/[locale]/layout.tsx
import { NextIntlClientProvider, hasLocale } from "next-intl";
import { notFound } from "next/navigation";
import { getMessages, setRequestLocale } from "next-intl/server";
import { routing, type Locale } from "@/i18n/routing";

type Props = {
  children: React.ReactNode;
  params: Promise<{ locale: string }>;
};

export function generateStaticParams() {
  return routing.locales.map((locale) => ({ locale }));
}

export default async function LocaleLayout({ children, params }: Props) {
  const { locale } = await params;

  if (!hasLocale(routing.locales, locale)) {
    notFound();
  }

  setRequestLocale(locale);
  const messages = await getMessages();

  return (
    <html lang={locale}>
      <body>
        <NextIntlClientProvider messages={messages}>
          {children}
        </NextIntlClientProvider>
      </body>
    </html>
  );
}

Why good: validates locale and returns 404 for invalid locales, setRequestLocale enables static rendering, generateStaticParams pre-renders all locale variants, explicit messages prop ensures Client Components receive translations, html lang attribute improves accessibility

Note: In next-intl v4.0+, NextIntlClientProvider auto-inherits messages from server config. Passing messages explicitly is optional but recommended for clarity.

Pattern 3: useTranslations Hook

Use the useTranslations hook for rendering localized messages.

Basic Usage

// src/app/[locale]/about/page.tsx
import { useTranslations } from "next-intl";
import { setRequestLocale } from "next-intl/server";

type Props = {
  params: Promise<{ locale: string }>;
};

export default async function AboutPage({ params }: Props) {
  const { locale } = await params;
  setRequestLocale(locale);

  const t = useTranslations("About");

  return (
    <article>
      <h1>{t("title")}</h1>
      <p>{t("description")}</p>
    </article>
  );
}
// messages/en.json
{
  "About": {
    "title": "About Us",
    "description": "Learn more about our company."
  }
}

Why good: namespaced translations keep messages organized, setRequestLocale at top of component enables static rendering

With Interpolati

Compartilhar X LinkedIn