A language code identifies a language (for example en, de, fr), while a locale code adds a region, script or variant (for example en-US, de-CH, zh-Hant-TW). Locale codes follow the BCP 47 standard, which builds on ISO 639 for languages, ISO 15924 for scripts and ISO 3166-1 for regions. Using the right code decides which translation, date format and currency a user sees.
If your app, website or translation files mix up "en_US", "en-us" and "eng", you will eventually ship the wrong text to the wrong market. This guide explains how locale codes work, shows the most common ones, and lists the format differences between platforms.
Language Codes vs Locale Codes
A language code says which language the content is in. A locale code says how that language is used in a specific place. English in the United States and English in the United Kingdom share a language code (en) but use different spelling, date order and currency, so they have different locales (en-US and en-GB). This is the core difference behind internationalization vs localization: developers prepare software to support many locales, and localization fills each locale with the right content.
The Standards Behind Locale Codes
Most modern systems rely on BCP 47, the "language tag" standard explained in the W3C article Language tags in HTML and XML. A tag is built from subtags, always in the same order: language, optional script, optional region, optional variant.
| Part | Standard | Example | Notes |
|---|---|---|---|
| Language | ISO 639-1 (two letters), ISO 639-2/3 (three letters) | de, fra, yue | Use the two-letter code when one exists |
| Script | ISO 15924 (four letters) | Latn, Cyrl, Hans, Hant | Needed when one language has several scripts |
| Region | ISO 3166-1 alpha-2, or UN M.49 numbers | US, BR, 419 | es-419 means Latin American Spanish |
| Variant | IANA registry | 1996, valencia | Rare, for orthography or dialect |
So zh-Hant-TW reads as Chinese, Traditional script, Taiwan, and sr-Latn-RS as Serbian written in Latin script in Serbia.
Common Locale Codes for Translation Projects
| Locale code | Language and region | Why it matters |
|---|---|---|
| en-US / en-GB | English (United States / United Kingdom) | Spelling, dates (MM/DD vs DD/MM), currency |
| de-DE / de-AT / de-CH | German (Germany / Austria / Switzerland) | Swiss German does not use the letter ß |
| fr-FR / fr-CA | French (France / Canada) | Different vocabulary and legal requirements |
| es-ES / es-MX / es-419 | Spanish (Spain / Mexico / Latin America) | Vocabulary and formal address differ |
| pt-BR / pt-PT | Portuguese (Brazil / Portugal) | Noticeable differences in grammar and terms |
| zh-Hans / zh-Hant | Chinese (Simplified / Traditional) | Different scripts, not just regions |
| ar-SA / ar-EG | Arabic (Saudi Arabia / Egypt) | Right-to-left layout and regional dialect |
| ja-JP | Japanese (Japan) | Date, name order and no spaces between words |
Locale Code Formats by Platform
The same locale is written differently depending on the system. This is the most common source of broken language switchers and missing translations.
| Platform | Portuguese (Brazil) | Separator and case |
|---|---|---|
| BCP 47, HTML lang, browsers | pt-BR | Hyphen, region uppercase |
| POSIX, Linux, gettext PO files | pt_BR.UTF-8 | Underscore, optional encoding |
| Android resource folders | values-pt-rBR | Prefix r before the region |
| iOS and macOS | pt-BR (folders use pt-BR.lproj) | Hyphen |
| Flutter ARB files | app_pt_BR.arb | Underscore in file names |
Platform guides such as our articles on Android localization, iOS localization and Flutter localization with ARB files show where each format is used.
Common Mistakes With Locale Codes
- Using the country as the language. "us", "gb" or "jp" are country codes. The language code for Japanese is ja, not jp.
- Using deprecated codes. Old tags such as iw (Hebrew), in (Indonesian) and ji (Yiddish) were replaced by he, id and yi.
- Mixing separators. Convert between en_US and en-US in one place, not across the codebase.
- Ignoring fallback. If de-AT is missing, the app should fall back to de, then to the default language, never to an empty string.
- Forgetting scripts. Chinese and Serbian need script information, not only a country.
How to Manage Locale Codes at Scale
Keep one canonical list of locales in a single configuration file, store it in BCP 47 format, and map it to the format each platform needs at build time. Test fallbacks and plural rules with ICU MessageFormat, and check that text is saved correctly with the right character encoding (UTF-8). A translation platform that reads locale codes from your files, such as a software localization workflow connected to your repository, removes most manual mapping errors.
Frequently Asked Questions
What is the difference between en and en-US?
The code en refers to English in general. The code en-US refers to English as used in the United States, with its own spelling, formats and vocabulary.
Should I use hyphens or underscores?
Use hyphens for web and BCP 47 (en-US). Use underscores only where a platform requires them, such as POSIX locales and some resource file names.
Are language codes case sensitive?
BCP 47 tags are case insensitive, but the convention is lowercase language, title case script and uppercase region, for example zh-Hant-TW.
Keep Every Locale Consistent With WordBeam
WordBeam reads locales from your files and repositories, applies translation memory and glossary to each one, and pushes approved translations back without manual copying. Explore the translation management system or start free with 14 days and 10,000 words.