i18n
SKILL.md
Internationalization (i18n)
Build applications that speak your users' language
When to Use This Skill
Use this skill when:
- Implementing multi-language support
- Formatting dates/numbers for different locales
- Handling RTL languages
- Managing translation files
Critical Patterns
Pattern 1: Basic Translation
When: Displaying translated text
Good:
// useTranslations hook
import { useTranslations } from 'next-intl';
export default function HomePage() {
const t = useTranslations('homepage');
return (
<div>
<h1>{t('title')}</h1>
<p>{t('subtitle')}</p>
</div>
);
}
// Translation file
// messages/en.json
{
"homepage": {
"title": "Welcome to Our Store",
"subtitle": "Find the best products"
}
}
Why: Centralized translations make it easy to support multiple languages.
Pattern 2: Variables in Translations
When: Including dynamic values
Good:
{
"welcome": "Welcome, {username}!",
"itemCount": "You have {count} items"
}
<p>{t('welcome', { username: 'Alice' })}</p>
<p>{t('itemCount', { count: 5 })}</p>
Why: ICU syntax allows flexible variable interpolation.
Pattern 3: Pluralization
When: Handling singular/plural forms
Good:
{
"items": "{count, plural, =0 {No items} =1 {1 item} other {# items}}"
}
<p>{t('items', { count: 0 })}</p> // "No items"
<p>{t('items', { count: 1 })}</p> // "1 item"
<p>{t('items', { count: 5 })}</p> // "5 items"
Why: Different languages have different pluralization rules.
Pattern 4: Date/Number Formatting
When: Displaying locale-specific formats
Good:
import { useFormatter } from 'next-intl';
export default function EventDate({ date, amount }) {
const format = useFormatter();
return (
<div>
{/* Date: "January 15, 2024" (en), "15 janvier 2024" (fr) */}
<p>{format.dateTime(date, { dateStyle: 'long' })}</p>
{/* Currency: "$99.99" (en-US), "99,99 €" (de-DE) */}
<p>{format.number(amount, {
style: 'currency',
currency: 'USD'
})}</p>
</div>
);
}
Why: Date and number formats vary by locale.
Pattern 5: RTL Support
When: Supporting Arabic, Hebrew, etc.
Good:
/* Use logical properties */
.card {
margin-inline-start: 1rem; /* Left in LTR, right in RTL */
padding-inline-end: 2rem;
}
/* Manual RTL handling */
[dir='rtl'] .arrow {
transform: scaleX(-1);
}
// Set dir attribute
<html lang={locale} dir={locale === 'ar' ? 'rtl' : 'ltr'}>
Why: RTL languages need flipped layouts.
Best Practices
Do's:
- ✅ Extract all user-facing text to translation files
- ✅ Use ICU syntax for complex messages
- ✅ Test with long German text (30% longer)
- ✅ Test RTL languages
- ✅ Format dates/numbers with locale-aware formatters
- ✅ Provide context in translation keys
Don'ts:
- ❌ Don't hardcode strings
- ❌ Don't concatenate translations
- ❌ Don't use locale for business logic
- ❌ Don't forget text expansion
Code Examples
Example 1: Basic Translation with Variables
// messages/en.json
{
"welcome": "Welcome, {username}!",
"cartItems": "You have {count, plural, =0 {no items} =1 {1 item} other {# items}} in your cart"
}
// Component
import { useTranslations } from 'next-intl';
export default function Header({ username, cartCount }: HeaderProps) {
const t = useTranslations();
return (
<header>
<h1>{t('welcome', { username })}</h1>
<p>{t('cartItems', { count: cartCount })}</p>
</header>
);
}
Example 2: Locale-Aware Date and Number Formatting
import { useFormatter } from 'next-intl';
export default function ProductCard({ product }: ProductCardProps) {
const format = useFormatter();
return (
<div>
<h3>{product.name}</h3>
<p>{format.number(product.price, {
style: 'currency',
currency: 'USD'
})}</p>
<time>{format.dateTime(product.releaseDate, {
year: 'numeric',
month: 'long',
day: 'numeric'
})}</time>
</div>
);
}
For comprehensive examples and detailed implementations, see the references/ folder.
Progressive Disclosure
For detailed implementations:
- next-intl Setup - Installation, middleware, layouts
- ICU Patterns - Variables, pluralization, rich text, formatting
References
Maintained by dsmj-ai-toolkit
Weekly Installs
3
Repository
dsantiagomj/dsm…-toolkitFirst Seen
Feb 16, 2026
Security Audits
Installed on
gemini-cli3
github-copilot3
codex3
amp3
kimi-cli3
opencode3