Skip to content
Internationalization

Convert a locale code into every format

pt-BR, pt_BR.UTF-8, values-pt-rBR, pt-BR.lproj: one Brazilian Portuguese, four spellings, one per platform. Paste a code or a whole list and get every correct form, a check that the code is real and a live preview of how that locale writes dates, numbers and currency. Runs in your browser.

Updated on · by

Codes stay in your browser: conversion and preview use your device's Intl APIs.

Your result will appear here

How to use the converter

  1. 1

    Paste one or more codes

    Any spelling works: pt-BR, pt_BR.UTF-8, values-b+sr+Latn, zh_Hant_TW, es-419. Put one per line to convert many at once, or paste a full Accept-Language header.

  2. 2

    Read the breakdown

    Each code is split into language, script and region with their English names, plus the canonical form and the maximized one (zh-TW becomes zh-Hant-TW).

  3. 3

    Copy the form you need

    One row per platform: BCP 47 for HTML and JavaScript, POSIX and gettext for Linux and PHP, ICU and Java for backends, the Android resource qualifier, the Apple .lproj folder and the hreflang value.

  4. 4

    Check preview and warnings

    The preview shows date, time, numbers, currency, percentages and plural categories as your browser formats them for that locale. Warnings flag malformed codes, deprecated codes and values Google rejects in hreflang.

  5. 5

    Export

    A list of codes becomes a full table you can copy or download as CSV or JSON, ready for a config file.

Why one locale has so many spellings

A locale is the combination of language, optional script and region that software uses to pick translations and to format dates, numbers and money. Every ecosystem writes it differently. The web and JavaScript use BCP 47 tags with hyphens (pt-BR). Linux and C libraries use the POSIX form with an underscore and an encoding (pt_BR.UTF-8). Java and ICU use underscores without the encoding. Android wants a prefix and an r before the region (values-pt-rBR) and switches to a different syntax altogether as soon as a script is involved (values-b+sr+Latn). Apple names folders pt-BR.lproj.

On a single platform that is fine. When the same list of languages has to land in your HTML, your backend, your Android app and your iOS app, hand conversion produces errors that raise no error at all: the translation simply does not load and the user sees English.

Most online converters rebuild three forms and stop there. Here every code is first validated with the browser's Intl API, the same engine your JavaScript will rely on, then decomposed and rebuilt for each platform, hard cases included: scripts, variants, numeric region codes, deprecated codes. The preview tells you straight away whether you picked the right locale: if decimals come out with a dot instead of a comma, the code is wrong, not your formatter.

Each format, platform by platform

BCP 47 (RFC 5646). The web standard: lowercase language, title-case script, uppercase region, joined by hyphens. sr-Latn-RS is Serbian in Latin script, in Serbia. It goes in the HTML lang attribute, JavaScript's Intl APIs, HTTP headers and nearly every modern library.

POSIX and gettext. The form of the LANG and LC_ALL variables: sr_RS.UTF-8@latin. Language and region joined by an underscore, the encoding after a dot and the script as a modifier after the at sign. It is also the folder name for gettext translations in PHP, WordPress and countless open source projects.

ICU and Java. ICU writes sr_Latn_RS. Java accepts the same idea through Locale.forLanguageTag("sr-Latn-RS") and prints sr_RS_#Latn from toString. Going through forLanguageTag and toLanguageTag avoids most surprises.

Android. Resource folders use values-pt-rBR for language plus region. Scripts or three-letter codes require the BCP 47 syntax with the b+ prefix: values-b+sr+Latn+RS. Put a script in the old form and the folder is silently ignored.

Apple. iOS and macOS .lproj folders use Apple's language identifiers: pt-BR.lproj, zh-Hans.lproj. For Chinese, Apple folders name the script (Hans, Hant), not the region.

hreflang. Google expects an ISO 639-1 language code optionally followed by an ISO 3166-1 alpha-2 region. A valid BCP 47 tag can still be invalid there, and the converter says so.

The usual mistakes, and how they are flagged

en-UK instead of en-GB. The ISO code for the United Kingdom is GB, not UK. Browser Intl APIs quietly rewrite en-UK to en-GB, which is why the mistake survives testing. Wherever the code is compared as plain text (an hreflang value, an Android or iOS folder, a backend config file), en-UK matches nothing. You get the correct form and a warning.

Underscores in HTML. lang="en_US" is not a valid tag: the standard requires a hyphen. Browsers treat the page as an unknown language, which affects hyphenation, text to speech and spell checking.

Deprecated codes. Hebrew, Indonesian and Yiddish used to be iw, in and ji, later replaced by he, id and yi. Older Java versions kept returning the old forms, and many databases still store them. Plain Norwegian no should usually be nb (Bokmål) or nn (Nynorsk).

Chinese by region instead of script. zh_TW and zh_CN name a region, but what matters is the script: Traditional (zh-Hant) or Simplified (zh-Hans). The converter always shows the full form with the script.

Numeric regions in hreflang. es-419 (Latin American Spanish) is a perfectly good BCP 47 tag. In hreflang, though, Google accepts only two-letter region codes. Use es, or one tag per country.

Letter case. EN-us or pt-br work almost everywhere because tags are case-insensitive, yet string comparisons in code can still fail. The canonical form shown at the top is the one to store.

Glossary

Technical terms used on this page, briefly explained.

Locale #
The combination of language, script and region software uses to translate and format.
BCP 47 #
The IETF standard for language tags used on the web (RFC 5646 plus the subtag registry).
Script subtag #
Four letters naming the writing system: Latn (Latin), Cyrl (Cyrillic), Hans and Hant (Simplified and Traditional Chinese).
POSIX locale #
The form used by Linux and C libraries: language_REGION.encoding@modifier, for example en_US.UTF-8.
CLDR #
Unicode's Common Locale Data Repository: the data that defines how each language writes dates, numbers and plurals.
Maximized tag #
The tag completed with its most likely subtags: zh-TW becomes zh-Hant-TW, sr becomes sr-Cyrl-RS.
Accept-Language #
The HTTP header in which the browser lists preferred languages, each with a weight (q=0.9).
hreflang #
The attribute that tells Google which language versions of a page exist.

Frequently asked questions

What is the difference between pt-BR and pt_BR?
They mean the same thing, Brazilian Portuguese, in two conventions. pt-BR is the BCP 47 form used by the web and JavaScript; pt_BR is the POSIX, Java and ICU form. The converter gives you both, plus the Android and Apple ones.
Which form goes in the HTML lang attribute?
Always BCP 47 with a hyphen: lang="en" or lang="en-US". Underscores are invalid in HTML and make the page an unknown language.
How do I name an Android values folder with a script?
Use the b+ syntax: values-b+sr+Latn for Serbian in Latin script, values-b+zh+Hant+TW for Traditional Chinese in Taiwan. The r form (values-sr-rRS) cannot carry a script.
Is en-UK a valid code?
No, even though it is everywhere. The United Kingdom is GB in ISO, so the right tag is en-GB. Browsers fix it silently when it goes through Intl, but in string comparisons, app folders and hreflang en-UK stays wrong.
Can I use es-419 in hreflang?
No. es-419 is a valid BCP 47 tag for Latin American Spanish, but Google only accepts two-letter country codes in hreflang. Use es as the generic language or one tag per country, such as es-MX or es-AR.
What is the maximized form?
The tag completed with its most likely implied parts according to CLDR data. zh-TW becomes zh-Hant-TW because Taiwan writes Traditional Chinese. It shows what a short code actually means.
Why does the preview format dates differently from what I expected?
The preview comes from your browser, which uses the CLDR data bundled with its version. Different browsers and systems can differ slightly, for example in where the currency symbol goes. Check the preview before you ship.
Can it parse an Accept-Language header?
Yes. Paste it as is, for example en-US,en;q=0.9,it;q=0.7: the converter splits it into languages, keeps the order given by the weights and converts each one.
Does it handle dozens of codes at once?
Yes. Paste one code per line and you get a table with every form, ready to copy or download as CSV or JSON. Handy when the language list has to match across web, backend and apps.
Are the codes I paste sent anywhere?
No. Validation, conversion and preview use your browser's Intl APIs and run on your device. Nothing is sent to a server.

Sources used

Laws, official tables and reference implementations the logic of this tool was checked against.

Who builds these tools?

Maurizio Fonte, senior IT consultant with 20+ years in PHP, Laravel, unmanaged Linux infrastructure, applied cybersecurity and AI/LLM integration. Production backends, legacy code modernization, security audits, custom AI agents and MCP servers: the work behind every tool published here.

About Maurizio Fonte