
Internationalization I18n
- 339 installs
- 202 repo stars
- Updated August 4, 2026
- secondsky/claude-skills
internationalization-i18n is a development skill that assists internationalization workflows for developers who need to add localization, translation keys, and locale handling to an application.
About
internationalization-i18n is a developer skill for working on internationalization tasks in application codebases. internationalization-i18n is intended to help developers plan and apply changes such as extracting UI strings, defining translation keys, and wiring locale selection and formatting behaviors into the frontend. internationalization-i18n is typically used when a product expands to new regions or when developers need consistent localization patterns across multiple routes and components. Developers reach for internationalization-i18n when i18n work touches many files and requires repeatable transformations, such as converting hardcoded strings to translation lookups and ensuring date/number formatting is locale-safe.
- internationalization-i18n
Internationalization I18n by the numbers
- 339 all-time installs (skills.sh)
- +14 installs in the week ending Aug 5, 2026 (Skillselion tracking)
- Ranked #1,232 of 4,347 Backend & APIs skills by installs in the Skillselion catalog
- Data as of Aug 5, 2026 (Skillselion catalog sync)
npx skills add https://github.com/secondsky/claude-skills --skill internationalization-i18nAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 339 |
|---|---|
| repo stars | ★ 202 |
| Last updated | August 4, 2026 |
| Repository | secondsky/claude-skills ↗ |
How do I add i18n to my app?
Use internationalization-i18n for development tasks
Who is it for?
internationalization-i18n is best for developers implementing localization across a frontend codebase with repeated string and locale-handling changes.
Skip if: internationalization-i18n is not for codebases that do not require multiple locales or that already have a complete localization system in place.
When should I use this skill?
Invoke when a developer asks to add i18n, localize UI strings, introduce locale routing, or standardize translation keys across the frontend.
What you get
Translation key plan, localized string mappings, and code changes to support locale selection and formatting.
- translation key plan
- localization refactor
Files
Internationalization (i18n)
Implement multi-language support with proper translation management and formatting.
i18next Setup (React)
import i18n from 'i18next';
import { initReactI18next } from 'react-i18next';
import LanguageDetector from 'i18next-browser-languagedetector';
i18n
.use(LanguageDetector)
.use(initReactI18next)
.init({
fallbackLng: 'en',
interpolation: { escapeValue: false },
resources: {
en: { translation: { welcome: 'Welcome, {{name}}!' } },
es: { translation: { welcome: '¡Bienvenido, {{name}}!' } }
}
});
// Usage
const { t } = useTranslation();
<h1>{t('welcome', { name: 'John' })}</h1>Pluralization
// Translation file
{
"items": "{{count}} item",
"items_plural": "{{count}} items",
"items_zero": "No items"
}
// Usage
t('items', { count: 0 }) // "No items"
t('items', { count: 1 }) // "1 item"
t('items', { count: 5 }) // "5 items"Date/Number Formatting
// Dates
new Intl.DateTimeFormat('de-DE', {
dateStyle: 'long',
timeStyle: 'short'
}).format(new Date());
// Numbers
new Intl.NumberFormat('en-US', {
style: 'currency',
currency: 'USD'
}).format(1234.56); // "$1,234.56"
// Relative time
new Intl.RelativeTimeFormat('en', { numeric: 'auto' })
.format(-1, 'day'); // "yesterday"RTL Support
/* Use logical properties */
.container {
margin-inline-start: 1rem; /* margin-left in LTR, margin-right in RTL */
padding-inline-end: 1rem;
}
/* Direction attribute */
html[dir="rtl"] .icon {
transform: scaleX(-1);
}Additional Frameworks
See references/frameworks.md for:
- React-Intl (Format.js) complete implementation
- Python gettext with Flask/Babel
- RTL language support patterns
- ICU Message Format examples
Best Practices
- Extract all user-facing strings
- Use ICU message format for complex translations
- Test with pseudo-localization
- Support RTL from the start
- Never concatenate translated strings
- Use professional translators for production
React-Intl (Format.js) Implementation
Complete React internationalization with Format.js.
import { IntlProvider, FormattedMessage, FormattedNumber, FormattedDate, useIntl } from 'react-intl';
// Message definitions
const messages = {
en: {
greeting: 'Hello, {name}!',
items: '{count, plural, =0 {No items} one {# item} other {# items}}',
price: 'Price: {amount}',
lastUpdated: 'Last updated: {date}',
},
es: {
greeting: '¡Hola, {name}!',
items: '{count, plural, =0 {Sin artículos} one {# artículo} other {# artículos}}',
price: 'Precio: {amount}',
lastUpdated: 'Última actualización: {date}',
},
};
// Provider setup
function App() {
const [locale, setLocale] = useState('en');
return (
<IntlProvider locale={locale} messages={messages[locale]}>
<LocaleSwitcher onChange={setLocale} />
<Content />
</IntlProvider>
);
}
// Using FormattedMessage
function Content() {
const intl = useIntl();
const itemCount = 5;
return (
<div>
<h1>
<FormattedMessage id="greeting" values={{ name: 'John' }} />
</h1>
{/* Pluralization */}
<p>
<FormattedMessage id="items" values={{ count: itemCount }} />
</p>
{/* Currency formatting */}
<p>
<FormattedMessage
id="price"
values={{
amount: (
<FormattedNumber
value={99.99}
style="currency"
currency="USD"
/>
),
}}
/>
</p>
{/* Date formatting */}
<p>
<FormattedMessage
id="lastUpdated"
values={{
date: (
<FormattedDate
value={new Date()}
year="numeric"
month="long"
day="numeric"
/>
),
}}
/>
</p>
{/* Imperative API */}
<p>{intl.formatMessage({ id: 'greeting' }, { name: 'Jane' })}</p>
</div>
);
}
// Relative time
import { FormattedRelativeTime } from 'react-intl';
function TimeAgo({ date }) {
const diff = (date - Date.now()) / 1000;
return (
<FormattedRelativeTime
value={diff}
numeric="auto"
updateIntervalInSeconds={60}
/>
);
}Python gettext Implementation
import gettext
from babel.support import Translations
from flask import Flask, request, g
from functools import wraps
app = Flask(__name__)
# Supported languages
LANGUAGES = ['en', 'es', 'fr', 'de']
DEFAULT_LANGUAGE = 'en'
def get_locale():
"""Determine the best language for the user."""
# Check URL parameter
if 'lang' in request.args:
lang = request.args.get('lang')
if lang in LANGUAGES:
return lang
# Check cookie
lang = request.cookies.get('language')
if lang in LANGUAGES:
return lang
# Check Accept-Language header
return request.accept_languages.best_match(LANGUAGES, DEFAULT_LANGUAGE)
@app.before_request
def load_translations():
"""Load translations for the current locale."""
locale = get_locale()
g.locale = locale
translations_dir = 'translations'
g.translations = Translations.load(translations_dir, [locale])
def _(message):
"""Shorthand for gettext."""
return g.translations.ugettext(message)
def ngettext(singular, plural, n):
"""Handle pluralization."""
return g.translations.ungettext(singular, plural, n)
# Usage in templates
@app.route('/')
def index():
count = 5
return render_template('index.html',
greeting=_('Hello!'),
items=ngettext('%(num)d item', '%(num)d items', count) % {'num': count}
)
# Extract messages with Babel
# pybabel extract -F babel.cfg -o messages.pot .
# pybabel init -i messages.pot -d translations -l es
# pybabel compile -d translationsRTL Language Support
/* Use CSS logical properties */
.container {
/* Instead of margin-left/margin-right */
margin-inline-start: 1rem;
margin-inline-end: 2rem;
/* Instead of padding-left/padding-right */
padding-inline-start: 1rem;
padding-inline-end: 1rem;
/* Instead of text-align: left/right */
text-align: start;
}
/* Directional styles */
[dir="rtl"] .arrow-icon {
transform: scaleX(-1);
}
[dir="rtl"] .sidebar {
order: 1; /* Move to right side in RTL */
}// RTL detection and setup
const RTL_LANGUAGES = ['ar', 'he', 'fa', 'ur'];
function getDirection(locale: string): 'ltr' | 'rtl' {
return RTL_LANGUAGES.includes(locale) ? 'rtl' : 'ltr';
}
function LocaleProvider({ children }) {
const { locale } = useLocale();
const direction = getDirection(locale);
useEffect(() => {
document.documentElement.setAttribute('dir', direction);
document.documentElement.setAttribute('lang', locale);
}, [locale, direction]);
return children;
}ICU Message Format
// Complex messages with ICU format
const messages = {
taskStatus: `{count, plural,
=0 {No tasks}
one {# task}
other {# tasks}
} {count, plural,
=0 {}
other {remaining}
}`,
notification: `{type, select,
message {You have a new message from {sender}}
friend {You have a new friend request from {sender}}
like {{sender} liked your post}
other {You have a notification}
}`,
gender: `{gender, select,
male {He}
female {She}
other {They}
} liked your photo`,
};
// Usage
intl.formatMessage({ id: 'taskStatus' }, { count: 5 });
// "5 tasks remaining"
intl.formatMessage({ id: 'notification' }, { type: 'message', sender: 'John' });
// "You have a new message from John"Related skills
How it compares
Pick an i18n refactor helper when localization touches many files; pick a single-string translation helper when you only need a few isolated changes.
FAQ
What kind of changes does internationalization-i18n help with?
internationalization-i18n helps with codebase changes needed for localization such as extracting UI strings into translation keys, planning message catalogs, and wiring locale selection and formatting. internationalization-i18n is most useful when i18n work spans many components
When should I start i18n work in a project?
internationalization-i18n should be used when a project needs to support multiple locales or when hardcoded strings and formatting need to be standardized. internationalization-i18n fits a build-phase workflow where developers implement translation lookups and locale-safe formatt