Skip to content
Home / Blog / What is a locale? Codes, formats and platform differences

What is a locale? Codes, formats and platform differences

Product localization
Helmut Juskewycz
Content Marketer

Last updated

10/30/2026

Read time

6 min

Best for

Developers

Illustration of a globe surrounded by locale codes such as en-US, de-DE, pt-BR, and ja-JP, showing differences in date, number, and currency formatting across regions.

A locale is a language combined with the regional conventions software uses to show text, dates, times, numbers, prices and sorted lists to a group of people. It’s identified by a code such as pt-BR (Portuguese, Brazil) or fr-CA (French, Canada). Brazilian and European Portuguese share a language, but pt-BR and pt-PT are different locales.

Every platform writes that code its own way. The same Brazilian Portuguese locale is pt-BR on the web, pt_BR in Java’s toString(), pt_BR.UTF-8 on a Linux server and values-pt-rBR in an Android project. Our advice: store the hyphen form everywhere you control, and convert only where a platform insists on its own.

What does a locale control?

A locale decides how the same data reads to each user: the date order, the time format, the decimal and thousands separators, where the currency sign goes, which day starts the week, how many plural forms a sentence needs and how words sort. Translation changes the words. The locale changes everything around them.

We ran one date (5 March 2026, 14:30 UTC), one number (1234567.891) and one price (1,234.50 euros) through the JavaScript Intl API in eight locales. The formatting rules come from the Unicode Common Locale Data Repository (CLDR 48, Node.js 26.11).

Locale

Date

Time

Week starts

en-US

3/5/26

2:30 PM

Sunday

en-GB

05/03/2026

14:30

Monday

de-DE

05.03.26

14:30

Monday

fr-FR

05/03/2026

14:30

Monday

pt-BR

05/03/2026

14:30

Sunday

ja-JP

2026/03/05

14:30

Sunday

ar-EG

٥‏/٣‏/٢٠٢٦

٢:٣٠ م

Saturday

hi-IN

5/3/26

2:30 pm

Sunday

The number, the price and the plural forms came out like this:

Locale

Number

Price in euros

Plural forms

en-US

1,234,567.891

€1,234.50

one, other

en-GB

1,234,567.891

€1,234.50

one, other

de-DE

1.234.567,891

1.234,50 €

one, other

fr-FR

1 234 567,891

1 234,50 €

one, many, other

pt-BR

1.234.567,891

€ 1.234,50

one, many, other

ja-JP

1,234,567.891

€1,234.50

other

ar-EG

١٬٢٣٤٬٥٦٧٫٨٩١

‏١٬٢٣٤٫٥٠ €

zero, one, two, few, many, other

hi-IN

12,34,567.891

€1,234.50

one, other

A few rows are worth a second look. In en-US, 3/5/26 is March 5, while en-GB writes the same day as 05/03/2026, so a date format hard-coded into a template is wrong for one of them. In hi-IN, the number is grouped 12,34,567: three digits on the right, then pairs. And ar-EG writes Arabic-Indic digits and has six plural forms to English’s two, so a pluralization rule can’t be copied from one language to the next.

Sorting changes too. Sorted for German (de-DE), the letters z, ä, a, o and ö come out as a ä o ö z. Sorted for Swedish (sv-SE), the same letters come out as a o z ä ö.

What’s the difference between a language and a locale?

A language code names a language: pt is Portuguese, zh is Chinese. A locale adds a region, and sometimes a script. es-419 is Spanish for Latin America and the Caribbean, where 419 is a United Nations region code instead of a country. zh-Hans and zh-Hant are Chinese in simplified and traditional characters.

A person’s language and formatting locale can also differ: someone can read your app in English and still want dates and prices the Austrian way. If you have users like that, store their language and their formatting locale as two settings. For the language codes themselves, see our list of ISO 639 language codes.

How is a locale code written?

On the web and in most modern libraries, a locale code is a BCP 47 language tag (RFC 5646): short parts joined by hyphens.

Part

Standard

Example

Language

ISO 639, 2 or 3 letters

pt, es, sr

Script (optional)

ISO 15924, 4 letters

Latn, Hant

Region (optional)

ISO 3166-1 (2 letters) or UN M.49 (3 digits)

BR, RS, 419

Unicode extension (optional)

-u- keywords from CLDR

ar-u-nu-latn

The parts aren’t case-sensitive, but the convention is a lowercase language, a title-case script and an uppercase region: sr-Latn-RS is Serbian in Latin script for Serbia. The -u- extension carries preferences the region doesn’t settle: ca for the calendar, nu for the digits, fw for the first day of the week and hc for a 12- or 24-hour clock. ar-u-nu-latn, for example, is Arabic shown with the digits 0 to 9.

Is en_US the same as en-US?

Yes. It’s the same locale, written for different systems. BCP 47 uses a hyphen. Unix systems, Java’s older string form and Apple’s locale IDs use an underscore, and the Unicode CLDR treats the two separators as equivalent while preferring the hyphen. Here’s how Brazilian Portuguese is written in six places a product team ships to:

Where

How pt-BR is written

Web: HTML lang, JavaScript Intl

pt-BR (lang=“pt-BR”, new Intl.Locale(“pt-BR”))

Unicode CLDR and ICU

CLDR prefers pt-BR and accepts pt_BR; ICU’s own form is pt_BR

Linux and other POSIX systems

pt_BR.UTF-8 (language_territory.codeset)

Java

toString() gives pt_BR, toLanguageTag() gives pt-BR

Android resources

values-pt-rBR, or values-b+pt+BR on Android 7.0 and later

Apple platforms

locale ID pt_BR, language ID pt-BR, which also names the pt-BR.lproj folder

Two things here cause mistakes. Java’s toString() isn’t a BCP 47 tag, and Oracle’s own documentation says to rely on toLanguageTag() for a string that represents the complete locale. And on a Linux server, the C locale (also called POSIX) is the standard, portable locale, and it isn’t your users’ locale. A server that formats dates or sorts text should set the locale it needs instead of relying on its environment.

How should a team manage locales?

The hyphen form, BCP 47, belongs in your translation files, APIs, database and translation management system. Underscores and Android’s r prefix appear only where a platform asks for them: a Linux server, a Java call, an Android resource folder. Skip that rule and you’ll find pt_BR, pt-br and br-portuguese side by side for the same strings.

Write the fallback order down in configuration (pt-BR, then pt, then your source language) instead of letting each library guess. Watch the script when you do: zh-Hant falling back to plain zh may show simplified characters to a reader of traditional Chinese. Our guide to ISO and BCP 47 codes in software has a full fallback example.

LingoHub is a translation management system that syncs with GitHub, GitLab, Bitbucket, Azure DevOps and AWS CodeCommit, so the codes in your Android, iOS and web resource files stay the same ones your translators and reviewers see.

LingoHub is a translation management system that integrates with GitHub, GitLab, Bitbucket, Azure DevOps, and AWS CodeCommit, keeping your Android, iOS, and web resource files in sync with your translation workflows.

Ready to simplify software localization? Start your free 14-day trial or book a demo to see how LingoHub fits into your development workflow.

Related articles