.claude/skills/i18n-nextintl/SKILL.md
Internationalization with next-intl for Next.js 15. Supports core/theme/entity message layers, namespace groups, and translation registry. Use this skill when adding translations, validating i18n, or working with localized content.
npx skillsauth add NextSpark-js/nextspark i18n-nextintlInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Internationalization patterns for Next.js 15 using next-intl with auto-generated translation registry.
┌─────────────────────────────────────────────────────────────────┐
│ TRANSLATION SOURCES │
├─────────────────────────────────────────────────────────────────┤
│ │
│ 1. CORE MESSAGES (Application-wide) │
│ core/messages/{locale}/ │
│ ├── index.ts # Re-exports all namespaces │
│ ├── common.json # Buttons, labels, etc. │
│ ├── auth.json # Authentication messages │
│ ├── dashboard.json # Dashboard UI │
│ └── ... │
│ │
│ 2. THEME MESSAGES (Theme-specific overrides) │
│ contents/themes/{theme}/messages/{locale}.json │
│ - Extends/overrides core translations │
│ - Custom roles (editor, moderator) ONLY here │
│ │
│ 3. ENTITY MESSAGES (Entity-specific) │
│ contents/themes/{theme}/entities/{entity}/messages/ │
│ - Field labels, placeholders, descriptions │
│ │
└─────────────────────────────────────────────────────────────────┘
en - English (default)es - SpanishThe system uses optimized namespace loading based on page context:
const NAMESPACE_GROUPS = {
// Public pages (includes auth for login/signup buttons)
PUBLIC_INITIAL: ['common', 'public', 'auth'],
// Dashboard (authenticated users)
DASHBOARD_AUTHENTICATED: ['common', 'dashboard', 'settings', 'public', 'teams'],
// Auth-specific pages
AUTH_ONLY: ['common', 'auth', 'validation'],
// Fallback (all namespaces)
ALL: ['common', 'dashboard', 'settings', 'auth', 'public', 'validation', 'teams']
}
Auto-generated at core/lib/registries/translation-registry.ts:
// ✅ CORRECT - Use registry functions
import { loadThemeTranslation } from '@/core/lib/registries/translation-registry'
const translations = await loadThemeTranslation(themeName, locale)
// ❌ NEVER - Runtime string interpolation
const translations = await import(`@/contents/themes/${theme}/messages/${locale}.json`)
import { getTranslations } from 'next-intl/server'
export default async function WelcomePage() {
const t = await getTranslations('welcome')
return (
<div>
<h1>{t('title')}</h1>
<p>{t('description')}</p>
</div>
)
}
'use client'
import { useTranslations } from 'next-intl'
export function WelcomeCard() {
const t = useTranslations('welcome')
return (
<div>
<h2>{t('title')}</h2>
<p>{t('description')}</p>
</div>
)
}
// Translation file
{
"welcome": {
"greeting": "Hello, {name}!",
"items": "{count, plural, =0 {No items} =1 {One item} other {# items}}"
}
}
// Component
const t = useTranslations('welcome')
<p>{t('greeting', { name: user.name })}</p>
<p>{t('items', { count: items.length })}</p>
Custom role translations MUST NEVER be in core/messages/. They belong ONLY in theme messages.
| Translation Key | Core (core/messages/) | Theme (contents/themes/*/messages/) |
|-----------------|-------------------------|---------------------------------------|
| teams.roles.owner | MUST define here | Can override |
| teams.roles.admin | MUST define here | Can override |
| teams.roles.member | MUST define here | Can override |
| teams.roles.viewer | MUST define here | Can override |
| teams.roles.editor | MUST NOT define | MUST define here |
| teams.roles.moderator | MUST NOT define | MUST define here |
// core/messages/en/teams.json - ONLY core roles
{
"teams": {
"roles": {
"owner": "Owner",
"admin": "Administrator",
"member": "Member",
"viewer": "Viewer"
}
}
}
// contents/themes/default/messages/en.json - Theme extends
{
"teams": {
"roles": {
"editor": "Editor",
"moderator": "Moderator"
}
}
}
// ✅ CORRECT - Hierarchical, descriptive
{
"auth": {
"login": {
"title": "Sign In",
"emailLabel": "Email Address",
"errors": {
"invalidCredentials": "Invalid email or password"
}
}
}
}
// ❌ FORBIDDEN - Flat, unclear keys
{
"login_title": "Sign In",
"email": "Email"
}
# Find hardcoded strings in components
python .claude/skills/i18n-nextintl/scripts/extract-hardcoded.py \
--path contents/themes/default/components/
# Preview without file details
python .claude/skills/i18n-nextintl/scripts/extract-hardcoded.py \
--path app/ \
--dry-run
# Compare EN and ES translations
python .claude/skills/i18n-nextintl/scripts/validate-translations.py
# Check theme-specific translations
python .claude/skills/i18n-nextintl/scripts/validate-translations.py \
--theme default
# Strict mode (exit with error if missing keys)
python .claude/skills/i18n-nextintl/scripts/validate-translations.py \
--strict
# Add key to both locales
python .claude/skills/i18n-nextintl/scripts/add-translation.py \
--key "settings.profile.title" \
--en "Profile Settings" \
--es "Configuracion de Perfil"
# Add to theme messages instead of core
python .claude/skills/i18n-nextintl/scripts/add-translation.py \
--key "teams.roles.editor" \
--en "Editor" \
--es "Editor" \
--theme default
# Preview without writing
python .claude/skills/i18n-nextintl/scripts/add-translation.py \
--key "new.key" \
--en "Value" \
--es "Valor" \
--dry-run
// ❌ NEVER: Hardcoded user-facing text
export function WelcomeCard() {
return <h1>Welcome to Dashboard</h1> // Wrong!
}
// ❌ NEVER: String concatenation
const message = "Welcome, " + userName + "!"
// ❌ NEVER: Runtime string interpolation in imports
const translations = await import(`@/core/messages/${locale}/`)
// ✅ CORRECT: Use translations
export function WelcomeCard() {
const t = useTranslations('dashboard')
return <h1>{t('welcome')}</h1>
}
// ✅ CORRECT: Use interpolation
const message = t('greeting', { name: userName })
| Type | Location | Who Modifies |
|------|----------|--------------|
| Core translations | core/messages/{locale}/ | Core maintainers |
| Theme translations | contents/themes/{theme}/messages/{locale}.json | Theme developers |
| Entity translations | Entity config i18n.loaders | Entity developers |
| Translation registry | core/lib/registries/translation-registry.ts | Auto-generated |
| i18n config | core/i18n.ts | Core maintainers |
Before committing i18n changes:
development
Zod validation patterns for this Next.js application. Covers schema definition, API validation, form integration, error formatting, and type inference. Use this skill when implementing validation for APIs, forms, or entity schemas.
development
Review UI code for Web Interface Guidelines compliance. Use when asked to "review my UI", "check accessibility", "audit design", "review UX", or "check my site against best practices".
testing
Test coverage metrics and registry system for this Next.js application. Covers FEATURE_REGISTRY, FLOW_REGISTRY, TAGS_REGISTRY, and coverage metrics interpretation. Use this skill when evaluating test coverage, identifying gaps, or planning testing priorities.
development
TanStack Query (React Query) patterns for data fetching in this Next.js application. Covers useQuery, useMutation, optimistic updates, cache invalidation, and anti-patterns. Use this skill when implementing data fetching or state management with server data.