| name | Internationalization |
| description | Designing and building software that can be adapted to various languages, regions, and cultures without engineering changes |
| license | MIT |
| compatibility | universal |
| audience | developers, designers, product managers |
| category | interdisciplinary |
Internationalization
What I Do
I prepare applications for global audiences by designing systems that support multiple languages, date/time formats, number formats, and cultural conventions. I separate locale-specific content from code to enable efficient localization.
When to Use Me
- Preparing applications for international markets
- Implementing multiple language support
- Handling locale-specific formatting (dates, numbers, currencies)
- Managing right-to-left (RTL) language layouts
- Creating translation workflows and management systems
- Adapting content for cultural preferences
Core Concepts
- Locale Identification: Language tags (en-US, zh-Hans, ar-EG)
- Message Formatting: ICU MessageFormat with plurals, gender, select
- Date/Time Formatting: Locale-aware date and time display
- Number Formatting: Locale-specific decimal/thousand separators
- Pluralization Rules: Language-specific plural categories
- Text Expansion: Languages that require more space than English
- RTL Support: Right-to-left layout for Arabic, Hebrew, Persian
- Cultural Adaptations: Date formats, currencies, address formats
- Translation Management: Workflows for handling translations
- Pseudo-localization: Testing for i18n before actual translations
Code Examples
Internationalization Provider
class I18nProvider {
constructor(locale, translations) {
this.locale = locale;
this.translations = translations;
this.fallbackLocale = 'en';
}
t(key, params = {}) {
const keys = key.split('.');
let message = this.translations[this.locale];
for (const k of keys) {
message = message?.[k] || this.translations[this.fallbackLocale]?.[k];
}
if (!message) return key;
return this.interpolate(message, params);
}
interpolate(message, params) {
return message.replace(/\{(\w+)\}/g, (_, key) => {
return params[key] !== undefined ? params[key] : `{${key}}`;
});
}
formatDate(date, options = {}) {
const localeDate = new (date);
.(., {
: ,
...options
}).(localeDate);
}
() {
.(., {
: ,
: ,
: ,
...options
}).(number);
}
() {
.(., {
: ,
currency
}).(amount);
}
}
ICU Message Formatter
class MessageFormatter {
constructor(locale) {
this.locale = locale;
this.plurals = {
en: (n) => n === 1 ? 'one' : 'other',
zh: () => 'other',
ar: (n) => {
if (n === 0) return 'zero';
if (n === 1) return 'one';
if (n === 2) return 'two';
if (n % 100 >= 3 && n % 100 <= 10) return 'few';
if (n % 100 >= 11) return 'many';
return 'other';
}
};
}
format(message, params) {
return message.replace(/\{(\w+)(,\s*\w+(?:,\s*[^}]+)?)?\}/g, (match, key, rest) => {
const value = params[key];
(value === ) match;
pluralFn = .[.] || ..;
(!rest) value;
[, type, options] = rest.() || [];
(type) {
:
category = (value);
optionMatch = options?.( ());
optionMatch ? optionMatch[] : options.().();
:
selectMatch = options?.( ());
selectMatch ? selectMatch[] : ;
:
value;
}
});
}
}
formatter = ();
message = formatter.(
,
{ : }
);
RTL Layout Manager
class RTLManager {
constructor() {
this.supportedRTL = ['ar', 'he', 'fa', 'ur'];
this.currentDir = 'ltr';
}
detectLocale(locale) {
const baseLocale = locale.split('-')[0];
return this.supportedRTL.includes(baseLocale) ? 'rtl' : 'ltr';
}
applyDirection(locale) {
const dir = this.detectLocale(locale);
this.currentDir = dir;
document.documentElement.dir = dir;
document.documentElement.lang = locale;
}
flipStyles(styles) {
if (this.currentDir !== 'rtl') return styles;
const flipMap = {
'margin-left': 'margin-right',
'margin-right': 'margin-left',
: ,
: ,
: ,
: ,
: ,
: ,
: ,
:
};
flipped = { ...styles };
.(styles).( {
(flipMap[key]) {
flipped[flipMap[key]] = value;
flipped[key];
}
});
flipped;
}
() {
. ===
? { : , : }
: { : , : };
}
}
Best Practices
- Externalize all user-facing strings from the beginning
- Use locale-aware formatting libraries (Intl API, i18next, react-intl)
- Design for text expansion (languages can be 300% longer)
- Test with pseudo-localization before real translations
- Support RTL languages from the start, not as an afterthought
- Store translations in structured files (JSON, YAML, XLIFF)
- Use ICU MessageFormat for complex pluralization and gender
- Consider date, time, number, and currency formatting per locale
- Maintain separate translation memories for consistency
- Involve native speakers in translation review