Understanding BCP 47 Locale Codes: The Modern Standard for Language and Region Tags
When building multilingual applications or websites, handling language codes correctly is essential—not just for translation, but also for date formatting, number formatting, sorting, and user experience personalization.
Among the available standards, BCP 47 (Best Current Practice 47) has emerged as the de facto standard for representing language and regional information in modern software systems.
🧩 What is BCP 47?
BCP 47 is a formal specification by the IETF (Internet Engineering Task Force). It defines the syntax for language tags, which identify human languages in a format like:
language-region (e.g., en-GB, de-DE, fr-CA)
These tags combine ISO language codes (from ISO 639) with country codes (from ISO 3166), and sometimes additional variants or scripts.
🔤 Components of a BCP 47 Tag
A typical BCP 47 tag looks like this:
[language code]-[script code]-[region code]-[variant]
But most applications only need the language and region parts:
**en-GB**
→ English, as used in the United Kingdom**de-DE**
→ German, as spoken in Germany**fr-CA**
→ French, Canadian variant**zh-Hans-CN**
→ Chinese, Simplified script, in China**sr-Cyrl-RS**
→ Serbian, Cyrillic script, in Serbia
✅ Why Use BCP 47 Instead of Just ISO Codes?
Here’s why BCP 47 is better than just en
, de
, or fr
:
Feature | ISO 639 Code (en ) |
BCP 47 (en-GB ) |
---|---|---|
Specifies region | ❌ | ✅ |
Locale-aware date formatting | ❌ | ✅ |
Number/currency formatting | ❌ | ✅ |
Spelling differences considered | ❌ | ✅ |
Preferred by modern APIs | ❌ | ✅ |
Example:en-US
→ "color", "center", "organize"en-GB
→ "colour", "centre", "organise"
🛠️ Where BCP 47 is Used
- Web development:
HTML supportslang="en-GB"
for screen readers and search engines. - APIs:
Headers likeAccept-Language: fr-CA
inform the server of the client’s preferred language/region. - CMS and Translation Systems:
Tools like gettext, Laravel, Symfony, and Next.js i18n use BCP 47 tags for locale switching. - Mobile apps:
Both iOS and Android use BCP 47 tags for regional settings.
JavaScript:
The Intl
object uses BCP 47 for locale-sensitive operations:
new Intl.DateTimeFormat('de-DE').format(new Date())
🔄 Fallback and Negotiation
If a specific tag like en-NZ
isn’t available, systems can fall back to:
en-AU
(close regional variant)en
(generic English)
You should design your system to support graceful fallback to avoid missing translations.
💡 Best Practices
- Always specify both language and region, unless region truly doesn’t matter.
- Normalize tags to lowercase-uppercase (e.g.,
en-GB
, noten-gb
). - Use user preferences or browser headers to detect preferred locale.
- When storing content per language, index by BCP 47 code (
en-GB
,id-ID
, etc.) - Be careful with default fallbacks—don’t assume
en
meansen-US
.
📚 Common BCP 47 Locale Codes
Language | BCP 47 Code |
---|---|
English (UK) | en-GB |
English (US) | en-US |
German (Germany) | de-DE |
French (France) | fr-FR |
French (Canada) | fr-CA |
Arabic (UAE) | ar-AE |
Indonesian | id-ID |
Chinese (Simplified) | zh-Hans-CN |
Chinese (Traditional) | zh-Hant-TW |
🧠 Finally
Using BCP 47 locale codes is no longer just a best practice—it is a requirement for developing truly global applications. They bring clarity, accuracy, and compatibility across modern platforms and standards.
If you're building multilingual interfaces, localization-aware APIs, or even date formatting utilities, adopting BCP 47 will future-proof your architecture and improve user satisfaction.
Pro tip: Store user locale preferences using full BCP 47 codes to allow granular control and better internationalization support.
Comments ()