ISO 639 language codes are standardized codes for identifying languages. This comprehensive guide covers language codes essential for internationalization (i18n), localization, and multi-language applications.
Table of Contents
- What Are ISO 639 Language Codes?
- Language Code Types
- Language Tags (BCP 47)
- Most Common Languages
- Using Language Codes in Development
- Locale Codes
- Complete Language List
What Are ISO 639 Language Codes?
ISO 639 is the international standard for language codes maintained by the International Organization for Standardization (ISO). These codes are used for:
- Websites: Multi-language content (i18n/l10n)
- Browsers: Language preferences
- APIs: Content negotiation
- Operating Systems: Language settings
- Documents: Language metadata
- Translation: Content management systems
Standards Used: Most web development uses BCP 47 language tags, which combine ISO 639 language codes with ISO 3166 country codes to create locale identifiers like en-US, es-MX, or zh-CN.
Language Code Types
Alpha-2 Codes (2-Letter)
Format: Two lowercase letters
Example: en, es, fr, de
Standard: ISO 639-1
Most commonly used for:
- Web development (HTML lang attribute)
- URL paths (
/en/,/es/) - Browser language preferences
- Mobile apps
<!-- HTML language attribute -->
<html lang="en">
<!-- Spanish content -->
<html lang="es">
Alpha-3 Codes (3-Letter)
Format: Three lowercase letters
Example: eng, spa, fra, deu
Standard: ISO 639-2 and ISO 639-3
Used for:
- Bibliographic systems
- Academic applications
- Less common languages
- Historical languages
// Mapping alpha-2 to alpha-3
const languageMap = {
en: 'eng',
es: 'spa',
fr: 'fra',
de: 'deu'
};
| format | example | length | usage |
|---|---|---|---|
| Alpha-2 | en, es, fr | 2 letters | Web development |
| Alpha-3 (639-2) | eng, spa, fra | 3 letters | Bibliographic |
| Alpha-3 (639-3) | eng, spa, fra | 3 letters | Linguistics |
Language Tags (BCP 47)
BCP 47 defines language tags by combining ISO standards:
Format: language-REGION or language-Script-REGION
Basic Language Tags
// Language only
'en' // English (any region)
'es' // Spanish (any region)
'zh' // Chinese (any script/region)
// Language + Region
'en-US' // English (United States)
'en-GB' // English (United Kingdom)
'es-ES' // Spanish (Spain)
'es-MX' // Spanish (Mexico)
'pt-BR' // Portuguese (Brazil)
'pt-PT' // Portuguese (Portugal)
// Language + Script + Region
'zh-Hans-CN' // Chinese (Simplified, China)
'zh-Hant-TW' // Chinese (Traditional, Taiwan)
// Special cases
'en-US-x-custom' // With private use extension
Common Language Tag Patterns
const locales = {
'en-US': 'English (United States)',
'en-GB': 'English (United Kingdom)',
'en-CA': 'English (Canada)',
'en-AU': 'English (Australia)',
'es-ES': 'Spanish (Spain)',
'es-MX': 'Spanish (Mexico)',
'es-AR': 'Spanish (Argentina)',
'fr-FR': 'French (France)',
'fr-CA': 'French (Canada)',
'de-DE': 'German (Germany)',
'de-AT': 'German (Austria)',
'de-CH': 'German (Switzerland)',
'pt-BR': 'Portuguese (Brazil)',
'pt-PT': 'Portuguese (Portugal)',
'zh-CN': 'Chinese (Simplified, China)',
'zh-TW': 'Chinese (Traditional, Taiwan)',
'zh-HK': 'Chinese (Traditional, Hong Kong)'
};
Case Convention: Language codes are lowercase (en), country codes are uppercase (US), and scripts are title case (Hans). Always follow this convention: en-US, not EN-us or en-us.
Most Common Languages
Top 10 by Native Speakers
| Language | Alpha-2 | Alpha-3 | Native Speakers | Total Speakers |
|---|---|---|---|---|
| Mandarin Chinese | zh | zho | 918 million | 1.1 billion |
| Spanish | es | spa | 460 million | 543 million |
| English | en | eng | 379 million | 1.5 billion |
| Hindi | hi | hin | 341 million | 600 million |
| Bengali | bn | ben | 228 million | 265 million |
| Portuguese | pt | por | 221 million | 264 million |
| Russian | ru | rus | 154 million | 258 million |
| Japanese | ja | jpn | 128 million | 128 million |
| Western Punjabi | pa | pan | 93 million | 113 million |
| Marathi | mr | mar | 83 million | 95 million |
View English (en) | View Spanish (es) | View Chinese (zh)
Major World Languages
| Language | Alpha-2 | Alpha-3 | Common Regions |
|---|---|---|---|
| English | en | eng | US, GB, CA, AU, NZ |
| Spanish | es | spa | ES, MX, AR, CO |
| French | fr | fra | FR, CA, BE, CH |
| German | de | deu | DE, AT, CH |
| Italian | it | ita | IT, CH |
| Portuguese | pt | por | BR, PT, AO |
| Russian | ru | rus | RU, BY, KZ |
| Japanese | ja | jpn | JP |
| Korean | ko | kor | KR, KP |
| Chinese | zh | zho | CN, TW, HK, SG |
| Arabic | ar | ara | SA, EG, AE, MA |
| Hindi | hi | hin | IN |
| Dutch | nl | nld | NL, BE |
| Turkish | tr | tur | TR |
| Polish | pl | pol | PL |
| Swedish | sv | swe | SE |
| Indonesian | id | ind | ID |
| Thai | th | tha | TH |
| Vietnamese | vi | vie | VN |
European Languages
| Language | Alpha-2 | Alpha-3 | Speakers |
|---|---|---|---|
| German | de | deu | 95 million |
| French | fr | fra | 80 million |
| Italian | it | ita | 65 million |
| Spanish | es | spa | 47 million (in EU) |
| Polish | pl | pol | 40 million |
| Ukrainian | uk | ukr | 37 million |
| Romanian | ro | ron | 23 million |
| Dutch | nl | nld | 23 million |
| Greek | el | ell | 13 million |
| Czech | cs | ces | 10 million |
| Portuguese | pt | por | 10 million |
| Hungarian | hu | hun | 9 million |
| Swedish | sv | swe | 9 million |
| Bulgarian | bg | bul | 8 million |
| Danish | da | dan | 6 million |
| Finnish | fi | fin | 5 million |
| Slovak | sk | slk | 5 million |
| Norwegian | no | nor | 5 million |
Using Language Codes in Development
HTML Lang Attribute
<!-- Document language -->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>My Website</title>
</head>
<body>
<!-- English content -->
<p>Hello World</p>
<!-- Spanish section -->
<section lang="es">
<p>Hola Mundo</p>
</section>
<!-- French quote -->
<blockquote lang="fr">
<p>Bonjour le monde</p>
</blockquote>
</body>
</html>
HTTP Accept-Language Header
GET /page HTTP/1.1
Host: example.com
Accept-Language: en-US,en;q=0.9,es;q=0.8,fr;q=0.7
# Breakdown:
# en-US (quality 1.0 - default)
# en;q=0.9 (quality 0.9 - second preference)
# es;q=0.8 (quality 0.8 - third preference)
# fr;q=0.7 (quality 0.7 - fourth preference)
JavaScript Language Detection
// Get browser language
const browserLanguage = navigator.language || navigator.userLanguage;
console.log(browserLanguage); // "en-US"
// Get all preferred languages
const languages = navigator.languages;
console.log(languages); // ["en-US", "en", "es"]
// Parse language tag
function parseLocale(locale) {
const [language, region] = locale.split('-');
return {
language: language.toLowerCase(),
region: region?.toUpperCase(),
full: locale
};
}
const parsed = parseLocale('en-US');
console.log(parsed);
// { language: 'en', region: 'US', full: 'en-US' }
// Match user preference to supported languages
function getBestMatch(userLanguages, supportedLanguages) {
for (const userLang of userLanguages) {
// Try exact match first
if (supportedLanguages.includes(userLang)) {
return userLang;
}
// Try language without region
const lang = userLang.split('-')[0];
const match = supportedLanguages.find(s => s.startsWith(lang));
if (match) return match;
}
return supportedLanguages[0]; // Default to first supported
}
const supported = ['en-US', 'es-ES', 'fr-FR', 'de-DE'];
const userPrefs = navigator.languages;
const bestMatch = getBestMatch(userPrefs, supported);
console.log(bestMatch); // "en-US"
React i18n Example
import { useState, useEffect } from 'react';
// Initialize i18n
i18n
.use(initReactI18next)
.init({
resources: {
en: {
translation: {
welcome: "Welcome",
goodbye: "Goodbye"
}
},
es: {
translation: {
welcome: "Bienvenido",
goodbye: "Adiós"
}
},
fr: {
translation: {
welcome: "Bienvenue",
goodbye: "Au revoir"
}
}
},
lng: 'en',
fallbackLng: 'en'
});
// Language selector component
function LanguageSelector() {
const { i18n } = useTranslation();
const languages = [
{ code: 'en', name: 'English', flag: '🇺🇸' },
{ code: 'es', name: 'Español', flag: '🇪🇸' },
{ code: 'fr', name: 'Français', flag: '🇫🇷' },
{ code: 'de', name: 'Deutsch', flag: '🇩🇪' }
];
return (
<select
value={i18n.language}
onChange={(e) => i18n.changeLanguage(e.target.value)}
>
{languages.map(lang => (
<option key={lang.code} value={lang.code}>
{lang.flag} {lang.name}
</option>
))}
</select>
);
}
// Using translations
function App() {
const { t } = useTranslation();
return (
<div>
<LanguageSelector />
<h1>{t('welcome')}</h1>
<p>{t('goodbye')}</p>
</div>
);
}
Next.js Internationalization
// next.config.js
module.exports = {
i18n: {
locales: ['en-US', 'es-ES', 'fr-FR', 'de-DE'],
defaultLocale: 'en-US',
localeDetection: true
}
};
// Pages automatically get locale in URL
// /en-US/about
// /es-ES/about
// /fr-FR/about
// Access current locale
function MyPage() {
const router = useRouter();
const { locale, locales, defaultLocale } = router;
return (
<div>
<p>Current language: {locale}</p>
{locales.map(loc => (
<Link key={loc} href="/" locale={loc}>
{loc}
</Link>
))}
</div>
);
}
Locale Codes
Locale codes combine language and region for specific formatting:
Date Formatting
const date = new Date('2025-01-15');
// Different locales, different formats
console.log(date.toLocaleDateString('en-US'));
// "1/15/2025"
console.log(date.toLocaleDateString('en-GB'));
// "15/01/2025"
console.log(date.toLocaleDateString('de-DE'));
// "15.1.2025"
console.log(date.toLocaleDateString('ja-JP'));
// "2025/1/15"
console.log(date.toLocaleDateString('ar-SA'));
// "١٥/١/٢٠٢٥"
Number Formatting
const number = 1234567.89;
// Different locales, different separators
console.log(number.toLocaleString('en-US'));
// "1,234,567.89"
console.log(number.toLocaleString('de-DE'));
// "1.234.567,89"
console.log(number.toLocaleString('fr-FR'));
// "1 234 567,89"
console.log(number.toLocaleString('ja-JP'));
// "1,234,567.89"
console.log(number.toLocaleString('ar-EG'));
// "١٬٢٣٤٬٥٦٧٫٨٩"
Currency Formatting
const amount = 1234.56;
// US English with USD
console.log(amount.toLocaleString('en-US', {
style: 'currency', currency: 'USD'
}));
// "$1,234.56"
// German with EUR
console.log(amount.toLocaleString('de-DE', {
style: 'currency', currency: 'EUR'
}));
// "1.234,56 €"
// French with EUR
console.log(amount.toLocaleString('fr-FR', {
style: 'currency', currency: 'EUR'
}));
// "1 234,56 €"
// Japanese with JPY
console.log(amount.toLocaleString('ja-JP', {
style: 'currency', currency: 'JPY'
}));
// "¥1,235"
Complete Language List
A-E
| Language | Alpha-2 | Alpha-3 | Native Name |
|---|---|---|---|
| Arabic | ar | ara | العربية |
| Bengali | bn | ben | বাংলা |
| Bulgarian | bg | bul | български |
| Catalan | ca | cat | Català |
| Chinese | zh | zho | 中文 |
| Croatian | hr | hrv | Hrvatski |
| Czech | cs | ces | Čeština |
| Danish | da | dan | Dansk |
| Dutch | nl | nld | Nederlands |
| English | en | eng | English |
| Estonian | et | est | Eesti |
F-K
| Language | Alpha-2 | Alpha-3 | Native Name |
|---|---|---|---|
| Finnish | fi | fin | Suomi |
| French | fr | fra | Français |
| German | de | deu | Deutsch |
| Greek | el | ell | Ελληνικά |
| Hebrew | he | heb | עברית |
| Hindi | hi | hin | हिन्दी |
| Hungarian | hu | hun | Magyar |
| Icelandic | is | isl | Íslenska |
| Indonesian | id | ind | Bahasa Indonesia |
| Italian | it | ita | Italiano |
| Japanese | ja | jpn | 日本語 |
| Korean | ko | kor | 한국어 |
L-R
| Language | Alpha-2 | Alpha-3 | Native Name |
|---|---|---|---|
| Latvian | lv | lav | Latviešu |
| Lithuanian | lt | lit | Lietuvių |
| Malay | ms | msa | Bahasa Melayu |
| Norwegian | no | nor | Norsk |
| Persian | fa | fas | فارسی |
| Polish | pl | pol | Polski |
| Portuguese | pt | por | Português |
| Romanian | ro | ron | Română |
| Russian | ru | rus | Русский |
S-Z
| Language | Alpha-2 | Alpha-3 | Native Name |
|---|---|---|---|
| Serbian | sr | srp | Српски |
| Slovak | sk | slk | Slovenčina |
| Slovenian | sl | slv | Slovenščina |
| Spanish | es | spa | Español |
| Swedish | sv | swe | Svenska |
| Thai | th | tha | ไทย |
| Turkish | tr | tur | Türkçe |
| Ukrainian | uk | ukr | Українська |
| Urdu | ur | urd | اردو |
| Vietnamese | vi | vie | Tiếng Việt |
Best Practices
1. Use BCP 47 Language Tags
<!-- ✅ Good - Complete language tag -->
<html lang="en-US">
<!-- ✅ Acceptable - Language only -->
<html lang="en">
<!-- ❌ Bad - Wrong format -->
<html lang="EN_US">
<html lang="english">
2. Always Set Language Attribute
<!-- ✅ Good - Helps screen readers and SEO -->
<html lang="en">
<!-- ❌ Bad - Missing language -->
<html>
3. Use Lowercase for Language Codes
// ✅ Good
const language = 'en-US'; // Lowercase language, uppercase region
// ❌ Bad
const language = 'EN-US';
const language = 'en-us';
4. Provide Language Fallbacks
const translations = {
'en-US': { welcome: 'Welcome' },
'en-GB': { welcome: 'Welcome' },
'en': { welcome: 'Welcome' }, // Fallback for all English
'es-MX': { welcome: 'Bienvenido' },
'es': { welcome: 'Bienvenido' } // Fallback for all Spanish
};
function getTranslation(locale, key) {
// Try exact match
if (translations[locale]?.[key]) {
return translations[locale][key];
}
// Try language without region
const language = locale.split('-')[0];
if (translations[language]?.[key]) {
return translations[language][key];
}
// Final fallback
return translations['en'][key];
}
5. Store User Language Preference
// Save user's language choice
function setLanguage(locale) {
localStorage.setItem('preferredLanguage', locale);
document.documentElement.lang = locale;
}
// Load saved language on page load
function getLanguage() {
const saved = localStorage.getItem('preferredLanguage');
const browser = navigator.language;
return saved || browser || 'en';
}
// Usage
const userLanguage = getLanguage();
i18n.changeLanguage(userLanguage);
Summary
ISO 639 language codes are essential for internationalization and localization. Always use BCP 47 language tags, provide fallbacks, and respect user language preferences.
Key Takeaways:
✅ Use ISO 639 two-letter codes (en, es, fr)
✅ Combine with country codes for locales (en-US, es-MX)
✅ Always set HTML lang attribute
✅ Use lowercase for language, uppercase for region
✅ Provide language fallbacks (en-US → en)
✅ Detect and store user language preferences
✅ Use Intl API for locale-aware formatting