Understanding BCP 47 Locale Codes: The Modern Standard for Language and Region Tags

Understanding BCP 47 Locale Codes: The Modern Standard for Language and Region Tags
Photo by Patrick Fore / Unsplash

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 supports lang="en-GB" for screen readers and search engines.
  • APIs:
    Headers like Accept-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

  1. Always specify both language and region, unless region truly doesn’t matter.
  2. Normalize tags to lowercase-uppercase (e.g., en-GB, not en-gb).
  3. Use user preferences or browser headers to detect preferred locale.
  4. When storing content per language, index by BCP 47 code (en-GB, id-ID, etc.)
  5. Be careful with default fallbacks—don’t assume en means en-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.

Support Us