Use when you have a written implementation plan to execute in a separate session with review checkpoints
npx skills add soilmass/vibe-coding-plugin --skill "i18n"
Install specific skill from multi-skill repository
# Description
>
# SKILL.md
name: i18n
description: >
Next.js 15 internationalization with next-intl β locale routing, useTranslations, server-side getTranslations, middleware locale detection
allowed-tools: Read, Grep, Glob
i18n
Purpose
Next.js 15 internationalization with next-intl. Covers [locale] route segments, translation
hooks, server-side translations, and middleware locale detection. The ONE skill for i18n decisions.
When to Use
- Adding multi-language support to Next.js 15 app
- Setting up
[locale]route segments - Using
useTranslationsorgetTranslations - Configuring middleware for locale detection
- Managing translation JSON files
When NOT to Use
- Routing without i18n β
nextjs-routing - Middleware without locale logic β
nextjs-middleware - SEO/metadata per locale β
nextjs-metadata(composes with this skill)
Pattern
Route structure with [locale] segment
src/app/
βββ [locale]/
β βββ layout.tsx # Locale-aware layout
β βββ page.tsx # Home page
β βββ about/page.tsx # About page
βββ i18n/
β βββ request.ts # next-intl request config
β βββ routing.ts # Locale routing config
βββ messages/
βββ en.json # English translations
βββ es.json # Spanish translations
Locale routing config
// src/i18n/routing.ts
import { defineRouting } from "next-intl/routing";
export const routing = defineRouting({
locales: ["en", "es", "fr"],
defaultLocale: "en",
});
Middleware locale detection
// src/middleware.ts
import createMiddleware from "next-intl/middleware";
import { routing } from "@/i18n/routing";
export default createMiddleware(routing);
export const config = {
matcher: ["/((?!api|_next|.*\\..*).*)"],
};
Server Component with getTranslations
// src/app/[locale]/page.tsx
import { getTranslations } from "next-intl/server";
export default async function Page({
params,
}: {
params: Promise<{ locale: string }>;
}) {
const { locale } = await params;
const t = await getTranslations({ locale, namespace: "Home" });
return <h1>{t("title")}</h1>;
}
Client Component with useTranslations
"use client";
import { useTranslations } from "next-intl";
export function SearchBar() {
const t = useTranslations("Search");
return <input placeholder={t("placeholder")} />;
}
Locale-aware metadata
import { getTranslations } from "next-intl/server";
import type { Metadata } from "next";
export async function generateMetadata({
params,
}: {
params: Promise<{ locale: string }>;
}): Promise<Metadata> {
const { locale } = await params;
const t = await getTranslations({ locale, namespace: "Metadata" });
return { title: t("title"), description: t("description") };
}
Anti-pattern
// WRONG: client-side locale detection with useEffect (causes flash)
"use client";
export function LocaleSwitcher() {
const [locale, setLocale] = useState("en");
useEffect(() => {
setLocale(navigator.language.slice(0, 2));
}, []);
// Flash of wrong language on SSR!
}
// CORRECT: detect in middleware, read from params
import { useLocale } from "next-intl";
export function LocaleSwitcher() {
const locale = useLocale(); // Already resolved by middleware
}
Common Mistakes
- Detecting locale client-side with
useEffectβ causes flash of wrong language - Forgetting to
await paramsin[locale]pages (Next.js 15 Promise params) - Not wrapping
next-intl/middlewarematcher to exclude API routes - Hardcoding strings instead of using translation keys
- Missing
messagesdirectory or forgetting to load locale messages in layout
Checklist
- [ ]
[locale]route segment wraps all localized pages - [ ] Middleware detects and redirects to correct locale
- [ ] Server Components use
getTranslations(notuseTranslations) - [ ] Client Components use
useTranslationswith"use client" - [ ] Translation JSON files exist for all supported locales
- [ ]
generateMetadatauses locale-aware translations - [ ]
paramsis awaited before accessinglocale
Composes With
nextjs-routingβ[locale]is a route segmentnextjs-middlewareβ locale detection runs in middlewarenextjs-metadataβ metadata varies by localeseo-advancedβ hreflang tags and locale-specific structured data
# Supported AI Coding Agents
This skill is compatible with the SKILL.md standard and works with all major AI coding agents:
Learn more about the SKILL.md standard and how to use these skills with your preferred AI coding agent.