| name | multi-language-localization |
| description | Best practices for multi-language static websites with proper i18n and l10n support |
| license | Apache-2.0 |
Multi-Language Localization Skill
🔴 AI FIRST Quality Principle
Apply the AI FIRST principle: never accept first-pass quality. Minimum 2 iterations. Read all output, improve every section. No shortcuts.
Purpose
Implement proper internationalization (i18n) and localization (l10n) for static websites supporting multiple languages.
Core Principles
1. Language Declaration
<html lang="en">
<html lang="sv">
<html lang="ar" dir="rtl">
2. File Structure
index.html (en - English, default)
index_sv.html (sv - Swedish)
index_da.html (da - Danish)
index_no.html (no - Norwegian)
index_fi.html (fi - Finnish)
index_de.html (de - German)
index_fr.html (fr - French)
index_es.html (es - Spanish)
index_nl.html (nl - Dutch)
index_ar.html (ar - Arabic, RTL)
index_he.html (he - Hebrew, RTL)
index_ja.html (ja - Japanese)
index_ko.html (ko - Korean)
index_zh.html (zh - Chinese)
3. Language Switcher
<nav aria-label="Language selection">
<ul>
<li><a href="index.html" hreflang="en">English</a></li>
<li><a href="index_sv.html" hreflang="sv">Svenska</a></li>
<li><a href="index_ar.html" hreflang="ar">العربية</a></li>
</ul>
</nav>
4. RTL Support
[dir="rtl"] .element {
text-align: right;
direction: rtl;
}
.element {
margin-inline-start: 1rem;
padding-inline-end: 1rem;
}
5. Cultural Considerations
- Date formats (US: MM/DD/YYYY, EU: DD/MM/YYYY)
- Number formats (1,000.00 vs 1.000,00)
- Currency symbols
- Text direction (LTR vs RTL)
- Color meanings (cultural significance)
SEO Best Practices
Hreflang Tags
<link rel="alternate" hreflang="en" href="https://example.com/index.html">
<link rel="alternate" hreflang="sv" href="https://example.com/index_sv.html">
<link rel="alternate" hreflang="x-default" href="https://example.com/index.html">
Sitemap
<url>
<loc>https://example.com/index.html</loc>
<xhtml:link rel="alternate" hreflang="sv" href="https://example.com/index_sv.html"/>
</url>
Testing
- Native speaker review
- RTL layout testing
- Character encoding verification
- Cultural appropriateness check
- SEO validation (hreflang)
Remember
- Native Speakers: Use professional translation
- Cultural Context: Consider cultural differences
- RTL Support: Test right-to-left languages
- Consistent UX: Same experience across languages
- SEO: Proper hreflang and sitemap
References
Number and Date Formatting (Production Data)
This section provides validated formatting from actual translated news articles (Feb 2026).
Number Formatting by Language
Thousands Separator and Decimal Point:
| Language | Thousands | Decimal | Example | Usage |
|---|
| English (en) | comma (,) | period (.) | 1,000.50 | International standard |
| Swedish (sv) | space ( ) | comma (,) | 1 000,50 | Official Swedish standard |
| German (de) | space ( ) or period (.) | comma (,) | 1 000,50 or 1.000,50 | Space preferred |
| French (fr) | space ( ) | comma (,) | 1 000,50 | Official French standard |
| Spanish (es) | space ( ) or period (.) | comma (,) | 1 000,50 or 1.000,50 | Space preferred |
| Dutch (nl) | period (.) | comma (,) | 1.000,50 | Period for thousands |
| Danish (da) | period (.) | comma (,) | 1.000,50 | Period for thousands |
| Norwegian (no) | space ( ) | comma (,) | 1 000,50 | Official Norwegian standard |
| Finnish (fi) | space ( ) | comma (,) | 1 000,50 | Official Finnish standard |
| Japanese (ja) | comma (,) | period (.) | 1,000.50 | Western style |
| Korean (ko) | comma (,) | period (.) | 1,000.50 | Western style |
| Chinese (zh) | comma (,) | period (.) | 1,000.50 | Western style |
| Arabic (ar) | comma (,) | period (.) | ١٬٠٠٠٫٥٠ or 1,000.50 | Arabic-Indic optional |
| Hebrew (he) | comma (,) | period (.) | 1,000.50 | Western style |
Implementation:
function formatNumber(num, lang) {
const formats = {
'en': { thousands: ',', decimal: '.' },
'sv': { thousands: ' ', decimal: ',' },
'de': { thousands: ' ', decimal: ',' },
'fr': { thousands: ' ', decimal: ',' },
'es': { thousands: ' ', decimal: ',' },
'nl': { thousands: '.', decimal: ',' },
'da': { thousands: '.', decimal: ',' },
'no': { thousands: ' ', decimal: ',' },
'fi': { thousands: ' ', decimal: ',' },
'ja': { thousands: ',', decimal: '.' },
'ko': { : , : },
: { : , : },
: { : , : },
: { : , : }
};
fmt = formats[lang] || formats[];
isNegative = num < ;
absolute = .(num);
fixed = absolute.();
[intPart, fracPart] = fixed.();
intPart = intPart.(, fmt.);
fracPart = fracPart.(, );
result = intPart;
(fracPart. > ) {
result += fmt. + fracPart;
}
(isNegative) {
result = + result;
}
result;
}
Date Formatting by Language
From News Articles (Feb 2026):
| Language | Format | Example | Day-Month Order |
|---|
| English (en) | Month D, YYYY | February 15, 2026 | Month first |
| Swedish (sv) | D month YYYY | 15 februari 2026 | Day first |
| German (de) | D. Month YYYY | 15. Februar 2026 | Day first (with period) |
| French (fr) | D month YYYY | 15 février 2026 | Day first |
| Spanish (es) | D de month de YYYY | 15 de febrero de 2026 | Day first (with "de") |
| Dutch (nl) | D month YYYY | 15 februari 2026 | Day first |
| Danish (da) | D. month YYYY | 15. februar 2026 | Day first (with period) |
| Norwegian (no) | D. month YYYY | 15. februar 2026 | Day first (with period) |
| Finnish (fi) | D. monthkuuta YYYY | 15. helmikuuta 2026 | Day first (genitive case) |
| Japanese (ja) | YYYY年M月D日 | 2026年2月15日 | Year-Month-Day |
| Korean (ko) | YYYY년 M월 D일 | 2026년 2월 15일 | Year-Month-Day |
| Chinese (zh) | YYYY年M月D日 | 2026年2月15日 | Year-Month-Day |
| Arabic (ar) | D month YYYY | ١٥ فبراير ٢٠٢٦ | Day first (Arabic-Indic optional) |
| Hebrew (he) | D bmonth YYYY | 15 בפברואר 2026 | Day first (with ב prefix) |
Month Names:
| English | Swedish | German | French | Spanish | Dutch |
|---|
| January | januari | Januar | janvier | enero | januari |
| February | februari | Februar | février | febrero | februari |
| March | mars | März | mars | marzo | maart |
| April | april | April | avril | abril | april |
| May | maj | Mai | mai | mayo | mei |
| June | juni | Juni | juin | junio | juni |
| July | juli | Juli | juillet | julio | juli |
| August | augusti | August | août | agosto | augustus |
| September | september | September | septembre | septiembre | september |
| October | oktober | Oktober | octobre | octubre | oktober |
| November | november | November | novembre | noviembre | november |
| December | december | Dezember | décembre | diciembre | december |
Day of Week:
| English | Swedish | German | French | Spanish | Dutch | Finnish |
|---|
| Monday | måndag | Montag | lundi | lunes | maandag | maanantai |
| Tuesday | tisdag | Dienstag | mardi | martes | dinsdag | tiistai |
| Wednesday | onsdag | Mittwoch | mercredi | miércoles | woensdag | keskiviikko |
| Thursday | torsdag | Donnerstag | jeudi | jueves | donderdag | torstai |
| Friday | fredag | Freitag | vendredi | viernes | vrijdag | perjantai |
| Saturday | lördag | Samstag | samedi | sábado | zaterdag | lauantai |
| Sunday | söndag | Sonntag | dimanche | domingo | zondag | sunnuntai |
Time Formatting
24-hour vs. 12-hour:
| Language | Clock | Example | Note |
|---|
| English (en) | 12-hour | 2:30 PM | AM/PM required |
| Swedish (sv) | 24-hour | 14:30 | Period or colon separator |
| German (de) | 24-hour | 14:30 Uhr | "Uhr" suffix |
| French (fr) | 24-hour | 14h30 | "h" separator |
| Spanish (es) | 24-hour | 14:30 | Colon separator |
| Nordic (da, no, fi) | 24-hour | 14:30 or 14.30 | Period common |
| CJK (ja, ko, zh) | 24-hour | 14:30 | Colon separator |
| Arabic (ar) | 12-hour | ٢:٣٠ م | Arabic-Indic optional |
| Hebrew (he) | 24-hour | 14:30 | Colon separator |
Currency Formatting
Swedish Krona (SEK):
| Language | Format | Example | Note |
|---|
| English | SEK 1,000.50 or 1,000.50 kr | SEK 1,000.50 | Currency code preferred |
| Swedish | 1 000,50 kr | 1 000,50 kr | "kr" suffix standard |
| German | 1 000,50 SEK | 1 000,50 SEK | Currency code suffix |
| French | 1 000,50 SEK | 1 000,50 SEK | Currency code suffix |
Ordinal Numbers
| Language | Example | Pattern |
|---|
| English | 1st, 2nd, 3rd, 4th | -st, -nd, -rd, -th |
| Swedish | 1:a, 2:a, 3:e, 4:e | :a or :e |
| German | 1., 2., 3., 4. | Period suffix |
| French | 1er, 2e, 3e, 4e | -er for first, -e for rest |
| Spanish | 1.º, 2.º, 3.º, 4.º | Masculine ordinal |
Practical Implementation
Date Formatting Function:
function formatDate(date, lang) {
const months = {
en: ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'],
sv: ['januari', 'februari', 'mars', 'april', 'maj', 'juni', 'juli', 'augusti', 'september', 'oktober', 'november', 'december'],
de: ['Januar', 'Februar', 'März', 'April', 'Mai', 'Juni', 'Juli', 'August', 'September', 'Oktober', 'November', 'Dezember'],
fr: ['janvier', 'février', 'mars', 'avril', 'mai', 'juin', 'juillet', 'août', 'septembre', 'octobre', 'novembre', ],
: [, , , , , , , , , , , ],
: [, , , , , , , , , , , ],
: [, , , , , , , , , , , ],
: [, , , , , , , , , , , ],
: [, , , , , , , , , , , ]
};
d = date.();
m = date.();
y = date.();
(lang === ) ;
(lang === || lang === || lang === ) ;
(lang === ) ;
(lang === ) ;
(lang === ) ;
(lang === ) ;
(lang === ) ;
;
}
Validation Checklist
For each language version, verify:
Data Source: Validated against 81 news articles (Feb 2026)
Standards: Unicode CLDR, ISO 8601
Last Updated: 2026-02-15