Setup
Read config.json in this skill directory (if it exists):
locales — target locale list; default ["en", "fr", "nl"]
default_locale — fallback locale; default "en"
library — i18n library preference; default "next-intl"
If the argument provides locales (e.g. /i18n-setup en,fr,de), override the config defaults.
If neither argument nor config provides locales, use AskUserQuestion:
"Which locales should this project support? (comma-separated BCP-47 codes, e.g. en,fr,nl)"
Overview
Adds internationalization (i18n) to a Next.js application supporting EN/FR/NL. Covers infrastructure setup, translation extraction, component integration, and optional CMS/MDX content migration.
Required References
Before starting, read references/frontend/i18n-conventions.md for locale file structure, key naming, and pluralization patterns.
Step 1: Discovery
- Analyze existing Next.js configuration (App Router vs Pages Router)
- Identify all user-facing strings in the codebase
- Check for existing i18n setup or library
- Determine content sources (hardcoded, CMS, MDX)
- Count translatable strings for scope estimation
Step 2: Infrastructure
- Install and configure i18n library (next-intl or similar)
- Set up locale routing (
/en/..., /fr/..., /nl/...)
- Create translation file structure (
messages/en.json, messages/fr.json, messages/nl.json)
- Add locale detection and switching
- Configure middleware for locale routing
Step 3: Translation Extraction (Parallel — 3 Agents)
Spawn 3 Explore agents to scan the codebase in parallel:
- Extract all hardcoded strings from components
- Generate translation keys following a consistent naming convention
- Create initial translation files with English as source
Step 4: Translation Quality Pass
After generating English source strings, translate to each target locale with these mandatory rules:
French (fr)
- All diacritics are required — never omit accents: é è ê ë à â ç ù û ô î ï œ æ
- Common mistakes to avoid:
- "évenement" → événement, "parametre" → paramètre, "creer" → créer
- "deja" → déjà, "a" (preposition) vs à, "ou" (or) vs où (where)
- Past participles: "termine" → terminé, "supprime" → supprimé
- Sentence structure: French uses spaces before
:, !, ?, ; (thin non-breaking space \u202F preferred)
- Use « guillemets » for quotes, not "English quotes"
Dutch (nl)
- Preserve diacritics where applicable: ë, ï, é, ü (e.g. "geïnteresseerd", "één", "reëel")
- Use correct compound words (Dutch compounds are written as one word)
Validation
After writing each locale file, re-read it and verify:
- No unaccented French words that require accents
- No English words left untranslated
- Interpolation placeholders (
{name}, {count}) are preserved exactly
- Pluralization keys match the locale's plural rules
Step 5: Component Integration
- Replace hardcoded strings with
useTranslations() calls
- Handle pluralization and interpolation
- Add locale-aware date/number formatting
- Update forms and validation messages
- Test language switching
Step 6: Content Migration (Conditional)
Only if CMS or MDX content exists.
- Add locale-specific content directories
- Migrate MDX content to locale-aware structure
- Set up locale-aware content fetching
Verification
Source: hamzaPixl/pixl-ai — distributed by TomeVault.
1---2name: i18n-setup3description: Add EN/FR/NL multi-language support to a Next.js application. Handles discovery, infrastructure, translation extraction, translation quality validation, component integration, and content migration through a 6-step AI workflow. Use when this capability is needed.4---56## Setup78Read `config.json` in this skill directory (if it exists):9- `locales` — target locale list; default ["en", "fr", "nl"]10- `default_locale` — fallback locale; default "en"11- `library` — i18n library preference; default "next-intl"1213If the argument provides locales (e.g. `/i18n-setup en,fr,de`), override the config defaults.14If neither argument nor config provides locales, use AskUserQuestion:15"Which locales should this project support? (comma-separated BCP-47 codes, e.g. en,fr,nl)"1617## Overview1819Adds internationalization (i18n) to a Next.js application supporting EN/FR/NL. Covers infrastructure setup, translation extraction, component integration, and optional CMS/MDX content migration.2021## Required References2223Before starting, read `references/frontend/i18n-conventions.md` for locale file structure, key naming, and pluralization patterns.2425## Step 1: Discovery26271. Analyze existing Next.js configuration (App Router vs Pages Router)282. Identify all user-facing strings in the codebase293. Check for existing i18n setup or library304. Determine content sources (hardcoded, CMS, MDX)315. Count translatable strings for scope estimation3233## Step 2: Infrastructure34351. Install and configure i18n library (next-intl or similar)362. Set up locale routing (`/en/...`, `/fr/...`, `/nl/...`)373. Create translation file structure (`messages/en.json`, `messages/fr.json`, `messages/nl.json`)384. Add locale detection and switching395. Configure middleware for locale routing4041## Step 3: Translation Extraction (Parallel — 3 Agents)4243Spawn 3 Explore agents to scan the codebase in parallel:44451. Extract all hardcoded strings from components462. Generate translation keys following a consistent naming convention473. Create initial translation files with English as source4849## Step 4: Translation Quality Pass5051After generating English source strings, translate to each target locale with these **mandatory rules**:5253### French (fr)5455- **All diacritics are required** — never omit accents: é è ê ë à â ç ù û ô î ï œ æ56- Common mistakes to avoid:57 - "évenement" → **événement**, "parametre" → **paramètre**, "creer" → **créer**58 - "deja" → **déjà**, "a" (preposition) vs **à**, "ou" (or) vs **où** (where)59 - Past participles: "termine" → **terminé**, "supprime" → **supprimé**60- Sentence structure: French uses spaces before `:`, `!`, `?`, `;` (thin non-breaking space `\u202F` preferred)61- Use « guillemets » for quotes, not "English quotes"6263### Dutch (nl)6465- Preserve diacritics where applicable: ë, ï, é, ü (e.g. "geïnteresseerd", "één", "reëel")66- Use correct compound words (Dutch compounds are written as one word)6768### Validation6970After writing each locale file, re-read it and verify:71721. No unaccented French words that require accents732. No English words left untranslated743. Interpolation placeholders (`{name}`, `{count}`) are preserved exactly754. Pluralization keys match the locale's plural rules7677## Step 5: Component Integration78791. Replace hardcoded strings with `useTranslations()` calls802. Handle pluralization and interpolation813. Add locale-aware date/number formatting824. Update forms and validation messages835. Test language switching8485## Step 6: Content Migration (Conditional)8687**Only if CMS or MDX content exists.**88891. Add locale-specific content directories902. Migrate MDX content to locale-aware structure913. Set up locale-aware content fetching9293## Verification9495- [ ] App builds without errors (`npx tsc --noEmit`)96- [ ] All 3 locales load correctly (`/en`, `/fr`, `/nl`)97- [ ] Language switcher navigates to the correct locale variant of the current page98- [ ] No untranslated strings visible in any locale99- [ ] French text has all required diacritics (spot-check 5 strings)100- [ ] Interpolation placeholders render correctly (not literal `{name}`)101102---103> Source: [hamzaPixl/pixl-ai](https://github.com/hamzaPixl/pixl-ai) — distributed by [TomeVault](https://tomevault.io).104<!-- tomevault:4.0:skill_md:2026-05-22 -->