Skip to content
Development
Skill

/web-i18n-next-intl

Type-safe i18n for the App Router — locale routing, message rendering, formatting and static generation. Load when a project imports next-intl.

From plugin
agents-inc-skills
24200 skills
Install
$ npx -y skills add agents-inc/skills --skill web-i18n-next-intl --agent claude-code

How it fires

How this skill gets triggered: by you, by Claude, or both.

  • Fires itselfAuto-invocation. Claude auto-loads it when your prompt matches the work.Auto-invocation is when the right skill fires by itself at the right moment, driven by a FLOW.md router and a hook, instead of you invoking it by name. It is the difference between a skill being installed and a skill actually getting used.Read the full definition →
  • You can call itInvoke it directly when you want it.
  • Slash command/web-i18n-next-intl

Context preview

The summary Claude sees to decide when to auto-load this skill.

Type-safe i18n for the App Router — locale routing, message rendering, formatting and static generation. Load when a project imports next-intl.

SKILL.md

web-i18n-next-intl.SKILL.md
name: web-i18n-next-intl
description: Type-safe i18n for the App Router — locale routing, message rendering, formatting and static generation. Load when a project imports next-intl.

next-intl Internationalization Patterns

> **Quick Guide:** `useTranslations` renders messages, `useFormatter` renders dates, numbers and > lists, and `createMiddleware` detects the locale. `setRequestLocale(locale)` at the top of a > page or layout is what keeps it statically renderable. v4.0+ registers types through the > `AppConfig` interface and sets the locale cookie only when the user switches away from their > Accept-Language preference. Every pattern here is App Router — the Pages Router integration is a > separate API and none of this transfers to it.

**Detailed Resources:**

  • [examples/core.md](examples/core.md) — setup, provider, `useTranslations`, plurals, formatting, static rendering, locale switching, types
  • [examples/formatting.md](examples/formatting.md) — relative time with auto-update, list formatting, combined format patterns
  • [examples/pluralization.md](examples/pluralization.md) — ordinals, plural nested in select, zero-case handling
  • [examples/markup.md](examples/markup.md) — `t.markup()` for HTML strings: email bodies, feeds, sanitisation
  • [reference.md](reference.md) — decision trees, anti-pattern code, ICU syntax tables, setup checklists

---

Which path applies

  • **Rendering inside a component** — `useTranslations` and `useFormatter`, with

`NextIntlClientProvider` above any Client Component that calls them. Follow [examples/core.md](examples/core.md).

  • **Rendering outside the component tree** — metadata, Server Actions and other async contexts take

`getTranslations({ locale, namespace })`, which needs the locale passed explicitly. Also in [examples/core.md](examples/core.md).

  • **Producing an HTML string rather than elements** — `t.markup()` instead of `t.rich()`, and the

sanitisation that goes with it. Follow [examples/markup.md](examples/markup.md).

---

<critical_requirements>

Before writing next-intl code

**Call `setRequestLocale(locale)` at the top of every page and layout, before any hook.** It is what lets next-intl resolve the locale without a request, which is what keeps the route statically renderable.

**Validate the locale with `hasLocale(routing.locales, locale)` before using it.** An unvalidated segment reaches the message loader and fails there, well away from the route that produced it.

**Wrap the tree in `NextIntlClientProvider`.** Client Components read their messages from that context and render nothing without it.

</critical_requirements>

---

**Auto-detection:** next-intl, useTranslations, useFormatter, useLocale, getTranslations, setRequestLocale, NextIntlClientProvider, defineRouting, createNavigation, hasLocale, ICU message format

**Applies to:**

  • Locale-segment routing, locale detection and the locale-aware navigation APIs
  • Rendering messages with interpolation, pluralization and embedded markup
  • Formatting dates, numbers, relative time and lists per locale
  • Generating every locale variant of a route at build time
  • Typing message keys and formats so a missing key fails at compile time

**Handled elsewhere:**

  • Framework routing and rendering beyond the locale segment — this skill settles what next-intl adds

to a route, not how routes are defined

  • Translation file authoring and sync with a translation vendor — messages arrive as JSON and where

they came from is not this skill's concern

  • Client state other than the locale — the locale is read with `useLocale()` and never mirrored
  • Date arithmetic — formatting a `Date` is this skill's job; producing one is not

---

<philosophy>

Translations are namespaced JSON, resolved per request on the server and handed to the client through context. Two decisions follow from that. Locale-aware rendering is a server concern by default, so the client tree carries only what interactivity needs. And because a request is what normally supplies the locale, static rendering needs it supplied another way — which is what `setRequestLocale` is for, and why it has to run before anything reads the locale.

</philosophy>

---

<patterns>

Core patterns

Pattern 1: Project setup

Four modules and a proxy: `routing.ts` declares the locales, `request.ts` resolves one per request, `navigation.ts` produces locale-aware navigation APIs, and the proxy detects the locale from URL, cookie and `Accept-Language`.

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

export const routing = defineRouting({
  locales: ["en", "de", "fr"],
  defaultLocale: "en",
});

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

The proxy file is `proxy.ts` from Next.js 16 onwards and `middleware.ts` before it; the export is `createMiddleware(routing)` either way.

Full code: [examples/core.md](examples/core.md)

Pattern 2: Root layout with provider

Validate the locale, set it, load the messages, and wrap the tree.

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

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

From v4.0 the provider inherits messages from the server config, so the `messages` prop is optional.

Full code: [examples/core.md](examples/core.md)

Pattern 3: useTranslations

A namespace scopes the keys, and values are named placeholders.

const t = useTranslations("Profile");

t("greeting", { name: user.name }); // "Hello, Jane!"
t("unreadCount", { count: messages.length });

Full code: [examples/core.md](examples/core.md)

Pattern 4: Pluralization with ICU syntax

The plural form is chosen by the locale's own CLDR rules, and `#` renders the formatted count. `=0` matches exactly zero, which is distinct from the `zero` CLDR category.

{
  "itemCoun
Read more
Ships withagents-inc-skills

The official skills marketplace for Agents Inc. 150+ skills covering everything from React and Prisma to Redis, ElevenLabs, and infrastructure tooling. Pick the skills that match your stack and install them via Claude Code. Need more control?

Get the whole plugin

Other skills on agents-inc-skills.