# Locale Code

Key: `technology.code.locale_code`

Language tag in the IETF BCP 47 form of RFC 5646: a language subtag, an optional script subtag and an optional region subtag (e.g., en, en-US, zh-Hant-TW, es-419). The language subtag is drawn from ISO 639, the script subtag from ISO 15924, and the region subtag from ISO 3166-1 or the UN M.49 numeric codes; RFC 5646 gives es-419 as Spanish appropriate to the UN-defined Latin America and Caribbean region. One extended language subtag may follow the language (zh-yue); that slot is checked for shape only, with membership left to the substance guard. An underscore separator (pt\_BR), the POSIX and Java locale form, is accepted with a note. Variants, extensions, private-use and grandfathered tags are not accepted.

Page: <https://meridian.online/docs/projects/finetype/types/technology/code/locale_code>

Samples: `en`, `en-US`, `fr-FR`, `zh-Hans-CN`, `de-AT`

## Background

### Origin

RFC 5646 was edited by A. Phillips and M. Davis.[[1]](https://www.rfc-editor.org/info/rfc5646/) RFC 5646 replaces RFC 4646, which obsoleted RFC 3066, which in turn replaced RFC 1766.[[1]](https://www.rfc-editor.org/info/rfc5646/) RFC 5646, in combination with RFC 4647, comprises BCP 47.[[1]](https://www.rfc-editor.org/info/rfc5646/)

Under RFC 5646, a language tag is a sequence of one or more subtags separated by a hyphen.[[1]](https://www.rfc-editor.org/info/rfc5646/) The namespace of language tags and their subtags is administered by IANA, and the Language Subtag Registry it maintains is the source for valid subtags.[[1]](https://www.rfc-editor.org/info/rfc5646/) RFC 5646 says language tags form the basis for most implementations of locale identifiers, pointing to Unicode's CLDR as an example.[[1]](https://www.rfc-editor.org/info/rfc5646/)

Unicode Technical Standard \#35 defines Unicode locale identifiers, which inherit the design and the repertoire of subtags from BCP 47.[[2]](https://www.unicode.org/reports/tr35/) UTS \#35 allows the underscore as a field separator for backwards compatibility, though its canonical form uses the hyphen.[[2]](https://www.unicode.org/reports/tr35/) UTS \#35 notes that some people recommend distinguishing language codes from locale codes by hyphen versus underscore, but says pragmatically the two must be treated as equivalent on input.[[2]](https://www.unicode.org/reports/tr35/)

### Use

HTML uses language tags in the lang attribute and XML in the xml:lang attribute.[[3]](https://www.w3.org/International/articles/language-tags/) HTTP uses language tags in the Accept-Language and Content-Language headers.[[3]](https://www.w3.org/International/articles/language-tags/) The W3C advises keeping a language tag as short as possible, adding region or script subtags only where they add useful distinguishing information.[[3]](https://www.w3.org/International/articles/language-tags/)

The GNU C Library's locale names mostly follow XPG syntax: language, then optionally an underscore and territory, a dot and codeset, and an at sign and modifier.[[4]](https://sourceware.org/glibc/manual/latest/html_node/Locale-Names.html) The GNU C Library manual gives de\_AT.iso885915@euro as a German-language locale for Austria using ISO-8859-15 with the Euro as the currency symbol.[[4]](https://sourceware.org/glibc/manual/latest/html_node/Locale-Names.html) Java's Locale.toString joins its fields with underscores, giving strings such as de\_DE and zh\_CN\_\#Hans, and is documented as being for debugging.[[5]](https://docs.oracle.com/en/java/javase/21/docs/api/java.base/java/util/Locale.html) Java's Locale documentation says to use toLanguageTag() to represent a Locale as a string for interchange purposes.[[5]](https://docs.oracle.com/en/java/javase/21/docs/api/java.base/java/util/Locale.html) A column of locale codes may therefore mix BCP 47 tags with POSIX or Java-style strings, so look at the separators before deciding which convention a source follows. (Meridian's view)

RFC 5646 says language tags and their subtags are case insensitive, so mn-Cyrl-MN and MN-cYRL-mn mean the same thing.[[1]](https://www.rfc-editor.org/info/rfc5646/) RFC 5646 recommends writing language subtags in lowercase, script subtags in title case and two-letter region subtags in uppercase.[[1]](https://www.rfc-editor.org/info/rfc5646/) RFC 5646 warns that uppercasing the region subtag 'in' with Turkish locale rules produces a dotted capital I, and asks implementers to use a locale-neutral casing operation.[[1]](https://www.rfc-editor.org/info/rfc5646/) Compare locale codes case-insensitively, normalise the separator to a hyphen, and do any case folding with a locale-neutral function. (Meridian's view)

Java's Locale documentation notes that a well-formed tag is not necessarily valid, giving xx-YY as an example whose subtags are not registered in the IANA Language Subtag Registry.[[5]](https://docs.oracle.com/en/java/javase/21/docs/api/java.base/java/util/Locale.html) A pattern check only shows that a value is shaped like a tag; to know it names a real language and region, look its subtags up in the IANA registry. (Meridian's view)

## Sources

1. [RFC 5646: Tags for Identifying Languages \| RFC Editor](https://www.rfc-editor.org/info/rfc5646/) — standard
2. [Unicode Locale Data Markup Language (LDML)](https://www.unicode.org/reports/tr35/) — standard
3. [Language tags in HTML and XML](https://www.w3.org/International/articles/language-tags/) — secondary source
4. [Locale Names (The GNU C Library)](https://sourceware.org/glibc/manual/latest/html_node/Locale-Names.html) — documentation
5. [Locale (Java SE 21 \& JDK 21)](https://docs.oracle.com/en/java/javase/21/docs/api/java.base/java/util/Locale.html) — documentation
