[Unicode]  Technical Reports
 

Unicode Technical Standard #35

Locale Data Markup Language (LDML)

Version 1.2R1
Authors Mark Davis
Date 2004-12-02
This Version http://www.unicode.org/reports/tr35/tr35-4.html
Previous Version http://www.unicode.org/reports/tr35/tr35-3.html
Latest Version http://www.unicode.org/reports/tr35/
Latest Draft http://www.unicode.org/reports/tr35/draft.html
Namespace: http://www.unicode.org/cldr/
DTDs: http://www.unicode.org/cldr/dtd/1.2/ldml.dtd
http://www.unicode.org/cldr/dtd/1.2/ldmlSupplemental.dtd
Revision 4


Summary

This document describes an XML format (vocabulary) for the exchange of structured locale data.

Status

This document has been reviewed by Unicode members and other interested parties, and has been approved by the Unicode Locale Data Technical Committee as a Unicode Technical Standard. This is a stable document and may be used as reference material or cited as a normative reference by other specifications.

A Unicode Technical Standard (UTS) is an independent specification. Conformance to the Unicode Standard does not imply conformance to any UTS. Each UTS specifies a base version of the Unicode Standard. Conformance to the UTS requires conformance to that version or higher.

Please submit corrigenda and other comments with the online reporting form [Feedback]. Related information that is useful in understanding this document is found in the References. For the latest version of the Unicode Standard see [Unicode]. For a list of current Unicode Technical Reports see [Reports]. For more information about versions of the Unicode Standard, see [Versions]. For possible errata for this document, see [Errata].

Contents

1. Introduction

Not long ago, computer systems were like separate worlds, isolated from one another. The internet and related events have changed all that. A single system can be built of many different components, hardware and software, all needing to work together. Many different technologies have been important in bridging the gaps; in the internationalization arena, Unicode has provided a lingua franca for communicating textual data. But there remain differences in the locale data used by different systems.

Common, recommended practice for internationalization is to store and communicate language-neutral data, and format that data for the client. This formatting can take place on any of a number of the components in a system; a server might format data based on the user's locale, or it could be that a client machine does the formatting. The same goes for parsing data, and locale-sensitive analysis of data.

But there remain significant differences across systems and applications in the locale-sensitive data used for such formatting, parsing, and analysis. Many of those differences are simply gratuitous; all within acceptable limits for human beings, but resulting in different results. In many other cases there are outright errors. Whatever the cause, the differences can cause discrepancies to creep into a heterogeneous system. This is especially serious in the case of collation (sort-order), where different collation caused not only ordering differences, but also different results of queries! That is, with a query of customers with names between "Abbot, Cosmo" and "Arnold, James", if different systems have different sort orders, different lists will be returned. (For comparisons across systems formatted as HTML tables, see [Comparisons].)

There are a number of steps that can be taken to improve the situation. The first is to provide an XML format for locale data interchange. This provides a common format for systems to interchange data so that they can get the same results. The second is to gather up locale data from different systems, and compare that data to find any differences. The third is to provide an online repository for such data. The fourth is to have an open process for reconciling differences between the locale data used on different systems and validating the data, to come up with a useful, common, consistent base of locale data.

Note: There are many different equally valid ways in which data can be judged to be "correct" for a particular locale. The goal for the common locale data is to make it as consistent as possible with existing locale data, and acceptable to users in that locale.

This document describes one of those pieces, an XML format for the communication of locale data. With it, for example, collation rules can be exchanged, allowing two implementations to exchange a specification of collation. Using the same specification, the two implementations will achieve the same results in comparing strings.

For more information, see the Common XML Locale Repository project page [LocaleProject].

2. What is a locale?

Before diving into the XML structure, it is helpful to describe the model behind the structure. People do not have to subscribe to this model to use the data, but they do need to understand it so that the data can be correctly translated into whatever model their implementation uses.

The first issue is basic: what is a locale? In this document, a locale is an id that refers to a set of user preferences that tend to be shared across significant swaths of the world. Traditionally, the data associated with this id provides support for formatting and parsing of dates, times, numbers, and currencies; for measurement units, for sort-order (collation), plus translated names for timezones, languages, countries, and scripts. They can also include text boundaries (character, word, line, and sentence), text transformations (including transliterations), and support for other services.

Locale data is not cast in stone: the data used on someone's machine generally may reflect the US format, for example, but preferences can typically set to override particular items, such as setting the date format for 2002.03.15, or using metric vs. Imperial measurement units. In the abstract, locales are simply one of many sets of preferences that, say, a website may want to remember for a particular user. Depending on the application, it may want to also remember the user's timezone, preferred currency, preferred character set, smoker/non-smoker preference, meal preference (vegetarian, kosher, etc.), music preference, religion, party affiliation, favorite charity, etc.

Locale data in a system may also change over time: country boundaries change; governments (and currencies) come and go: committees impose new standards; bugs are found and fixed in the source data; and so on. Thus the data needs to be versioned for stability over time.

In general terms, the locale id is a parameter that is supplied to a particular service (date formatting, sorting, spell-checking, etc.). The format in this document does not attempt to collect together all the data that could conceivably be used by all possible services. Instead, it collects together data that is in common use in systems and internationalization libraries for basic services. The main difference among locales is in terms of language; there may also be some differences according to different countries or regions. However, the line between locales and languages, as commonly used in the industry, are rather fuzzy. For more information, see Appendix D: Language and Locale IDs.

We will speak of data as being "in locale X". That does not imply that a locale is a collection of data; it is simply shorthand for "the set of data associated with the locale id X". Each individual piece of data is called a resource, and a tag indicating the key of resource is called a resource tag.

3. Locale IDs

A CLDR locale id consists of the following format:

locale_id := base_locale_id options?

base_locale_id := language_code ("_" script_code)? ("_" territory_code)? ("_" variant_code)?

options := "@" key "=" type ("," key "=" type )*

As usual x? means that x is optional; x* means that x occurs zero or more times.

Note: The successor to RFC 3066 is being currently developed. Once that standard has been approved, the goal is to update this locale id definition to correspond to that. This would be a correspondence, not necessarily precisely the same syntax.

The latest draft for that successor is http://www.inter-locale.com/ID/draft-phillips-langtags-05.html. The latest draft of the registry corresponding to that draft is at http://users.adelphia.net/~dewell/lstreg.txt.

The field values are given in the following table. All field values are case-insensitive, except for the type, which is case-sensitive. However, customarily the language code is lowercase, the territory and variant codes are uppercase, and the script code is titlecase (that is, first character uppercase and other characters lowercase). The type may also be referred to as a key-value, for clarity.

Locale Field Definitions
Field Allowable Characters Allowable values
language_code ASCII letters [ISO639] 2-letter codes where they exist; otherwise 3-letter codes (the mapping between 2-letter codes and 3-letter codes is not part of this format.), or [RFC3066] codes that do not contain script / territory codes.
script_code ASCII letters [ISO15924] 4-letter codes. In most cases the script is not necessary, since the language is only customarily written in a single script. Examples of usage are:
az-Arab Azerbaijani in Arabic script
az-Cyrl Azerbaijani in Cyrillic script
az-Latn Azerbaijani in Latin script
zh-Hans Chinese, in simplified script
zh-Hant Chinese, in traditional script
territory_code ASCII letters [ISO3166] 2-letter codes. Also known as a country_code, although the territories may not be countries.
variant_code ASCII letters Values used in CLDR are listed below. For information on the process for adding new standard variants or element/type pairs, see [LocaleProject].
key ASCII letters and digits
type ASCII letters, digits, and "-"

Examples:

en
fr_BE
de_DE@collation=phonebook,currency=DDM

The locale id format generally follows the description in the OpenI18N Locale Naming Guideline [NamingGuideline], with some enhancements. The main differences from the those guidelines are that the locale id:

  1. does not include a charset (since the data in LDML format always provides a representation of all Unicode characters. The repository is stored in UTF-8, although that can be transcoded to other encodings as well.),
  2. adds the ability to have a variant, as in Java
  3. adds the ability to discriminate the written language by script (or script variant).
  4. is a superset of [RFC3066] codes.

Note: The language + script + territory code combination can itself be considered simply a language code: For more information, see Appendix D: Language and Locale IDs.

A locale that only has a language code (and possibly a script code) is called a language locale; one with both language and territory codes is called a territory locale (or country locale).

The variant codes specify particular variants of the locale, typically with special options. They cannot overlap with script or territory codes, so they must have either one letter or have more than 4 letters. The currently defined variants include:

Variant Definitions
variant Description
<RFC 3066 variants> As defined in RFC 3066
bokmal Bokmål, variant of Norwegian (deprecated: use nb)
nynorsk Nynorsk, variant of Norwegian (deprecated: use nn)
aaland Åland, variant of Swedish used in Finland (deprecated: use AX)
POSIX A POSIX-style invariant locale.
REVISED For revised orthography

Note: The first two of the above variants are for backwards compatibility. Typically the entire contents of these are defined by an <alias> element pointing at nb_NO (Norwegian Bokmål) and nn_NO(Norwegian Nynorsk) locale IDs. See also Appendix K: Valid Attribute Values.

The currently defined optional key/type combinations include the following. Additional type values are defined in the detail sections of this document or in Appendix K: Valid Attribute Values.

Key/Type Definitions
key type Description
collation phonebook For a phonebook-style ordering (used in German).
pinyin Pinyin ordering for Latin and for CJK characters (that is, an ordering for CJK characters based on a character-by-character transliteration into a pinyin)
traditional For a traditional-style sort (as in Spanish)
stroke Pinyin ordering for Latin, stroke order for CJK characters
direct Hindi variant
posix A "C"-based locale.
big5han Pinyin ordering for Latin, big5 charset ordering for CJK characters.
gb2312han Pinyin ordering for Latin, gb2312han charset ordering for CJK characters.
calendar* gregorian (default)
islamic

alias: arabic

Astronomical Arabic
chinese Traditional Chinese calendar
islamic-civil

alias: civil-arabic

Civil (algorithmic) Arabic calendar
hebrew Traditional Hebrew Calendar
japanese Imperial Calendar (same as Gregorian except for the year, with one era for each Emperor)
buddhist

alias: thai-buddhist

Thai Buddhist Calendar (same as Gregorian except for the year)
*For information on the calendar algorithms associated with the data used with these types, see [Calendars].
currency ISO 4217 code Currency value identified by ISO code, plus others in common use. See Appendix K: Valid Attribute Values and also [Data Formats]
timezone Olson ID Identification for timezone according to the Olson Database ID. See [Data Formats].

For more information on the allowed attribute values, see the specific elements below, and Appendix K: Valid Attribute Values.

Note: There is no standard system (or rather, there are many standard systems) for defining locale ID syntax. This definition of Locale IDs may not match the locale ID syntax used on a particular system, so some process of ID translation may be required.

4. Locale Inheritance

The XML format relies on an inheritance model, whereby the resources are collected into bundles, and the bundles organized into a tree. Data for the many Spanish locales does not need to be duplicated across all of the countries having Spanish as a national language. Instead, common data is collected in the Spanish language locale, and territory locales only need to supply differences. The parent of all of the language locales is a generic locale known as root. Wherever possible, the resources in the root are language & territory neutral. For example, the collation order in the root is the UCA (see UAX #10). Since English language collation has the same ordering, the 'en' locale data does not need to supply any collation data, nor does either the 'en_US' or the 'en_IE' locale data.

Given a particular locale id "en_US_someVariant", the search chain for a particular resource is the following.

en_US_someVariant
en_US
en
root

If a type and key are supplied in the locale id, then logically the chain from that id to the root is searched for a resource tag with a given type, all the way up to root. If no resource is found with that tag and type, then the chain is searched again without the type.

Thus the data for any given locale will only contain resources that are different from the parent locale. For example, most territory locales will inherit the bulk of their data from the language locale: "en" will contain the bulk of the data: "en_US" will only contain a few items like currency. All data that is inherited from a parent is presumed to be valid, just as valid as if it were physically present in the file. This provides for much smaller resource bundles, and much simpler (and less error-prone) maintenance.

Where this inheritance relationship does not match a target system, such as POSIX, the data logically should be fully resolved in converting to a format for use by that system, by adding all inherited data to each locale data set.

For a more complete description of how inheritance applies to data, and the use of keywords, see Inheritance_and_Validity.

The locale data does not contain general character properties that are derived from the Unicode Character Database [UCD]. That data being common across locales, it is not duplicated in the bundles. Constructing a POSIX locale from the following data requires use of UCD data. In addition, POSIX locales may also specify the character encoding, which requires the data to be transformed into that target encoding.

4.1 Multiple Inheritance

In clearly specified instances, resources may inherit from within the same locale. For example, currency format symbols inherit from the number format symbols; the Buddhist calendar inherits from the Gregorian calendar. This only happens where documented in this specification. In these special cases, the inheritance functions as normal, up to the root. If the data is not found along that path, then a second search is made, logically changing the element/attribute to the alternate values.

For example, for the locale "en_US" the month data in <calendar class="buddhist"> inherits first from <calendar class="buddhist"> in "en", then in "root". If not found there, then it inherits from <calendar type="gregorian"> in "en_US", then "en", then in "root".

5 XML Format

The following sections describe the structure of the XML format for locale data. The more precise syntax is in the DTD, listed at the top of this document. To start with, the root element is <ldml>, with the following DTD entry:

<!ELEMENT ldml (identity, (alias |(localeDisplayNames?, layout?, characters?, delimiters?, measurement?, dates?, numbers?, collations?, posix?, special*))) >

That element contains the following elements:

The structure of each of these elements and their contents will be described below. The first few elements have little structure, while dates, numbers, and collations are more involved.

In general, all translatable text in this format is in element contents, while attributes are reserved for types and non-translated information (such as numbers or dates). The reason that attributes are not used for translatable text is that spaces are not preserved, and we cannot predict where spaces may be significant in translated material.

There are two kinds of elements in LDML: rule elements and structure elements. For structure elements, there are restrictions to allow for effective inheritance and processing:

  1. There is no "mixed" content: if an element has textual content, then it cannot contain any elements.
  2. The XPath leading to the content is unique; no two different pieces of textual content have the same XPath.

Structure elements do not have this restriction, but also do not inherit, except as an entire block. In this version of LDML, the collation <rules> elements is a rules element; all others are structure elements. See also Appendix I: Inheritance and Validity.

Note that the data in examples given below is purely illustrative, and doesn't match any particular language. For a more detailed example of this format, see [Example]. There is also a DTD for this format, but remember that the DTD alone is not sufficient to understand the semantics, the constraints, nor  the interrelationships between the different elements and attributes. You may wish to have copies of each of these to hand as you proceed through the rest of this document.

In particular, all elements allow for draft versions to coexist in the file at the same time. Thus certain elements, which otherwise must only occur once within their parent, are marked in the DTD as allowing multiple instances. These are:

There must be only one instance of these per parent that doesn't have an alternate attribute.

5.1 Common Elements

At any level in any element, two special elements are allowed.

<special xmlns:yyy="xxx">

This element is designed to allow for arbitrary additional annotation and data that is product-specific. It has one required attribute, which specifies the XML namespace of the special data. For example, the following used the version 1.0 POSIX special element.

<!DOCTYPE ldml SYSTEM "http://www.unicode.org/cldr/dtd/1.0/ldml.dtd" [
    <!ENTITY % posix SYSTEM "http://www.unicode.org/cldr/dtd/1.0/ldmlPOSIX.dtd">
%posix;
]>
<ldml>
...
<special xmlns:posix="http://www.opengroup.org/regproducts/xu.htm">
        <!-- old abbreviations for pre-GUI days -->
        <posix:messages>
            <posix:yesstr>Yes</posix:yesstr>
            <posix:nostr>No</posix:nostr>
            <posix:yesexpr>^[Yy].*</posix:yesexpr>
            <posix:noexpr>^[Nn].*</posix:noexpr>
        </posix:messages>
    </special>
</ldml>

<alias source="<locale_ID>" path="..."/>

The contents of any element can be replaced by an alias, which points to another source for the data. The elements in that source are to be fetched from the corresponding location in the other source. Normal resource searching is to be used; take the following example:

<ldml>
  <collations>
    <collation type="phonebook">
      <alias source="de_DE">
    </collation>
  </collations>
</ldml>

The resource bundle at "de_DE" will be searched for a resource element at the same position in the tree with type "collation". If not found there, then the resource bundle at "de" will be searched, etc.

If the path attribute is present, then its value is an XPath that points to a different node in the tree. For example:

<alias source="root" path="../monthWidth[@type='wide']"/>

The default value if the path is not present is the same position in the tree. For more details, see Appendix I: Inheritance and Validity.

It is an error to have a circular chain of aliases. That is, a collection of LDML XML documents must not have situations where a sequence of alias lookups (including inheritance and multiple inheritance) can be followed indefinitely without terminating.

<displayName>

Many elements can have a display name. This is a translated name that can be presented to users when discussing the particular service. For example, a number format, used to format numbers using the conventions of that locale, can have translated name for presentation in GUIs.

  <numberFormat>
    <displayName>Prozentformat</displayName>
...
  <numberFormat>

Where present, the display names must be unique; that is, two distinct code would not get the same display name. Any translations should follow customary practice for the locale in question. For more information, see [Data Formats].

<default type="someID"/>

In some cases, a number of elements are present. The default element can be used to indicate which of them is the default, in the absence of other information. The value of the type attribute is to match the value of the type attribute for the selected item.

<timeFormats>
  <default type="medium" /> 
  <timeFormatLength type="full">
    <timeFormat type="standard">
      <pattern type="standard">h:mm:ss a z</pattern> 
    </timeFormat>
  </timeFormatLength>
  <timeFormatLength type="long">
    <timeFormat type="standard">
      <pattern type="standard">h:mm:ss a z</pattern> 
    </timeFormat>
  </timeFormatLength>
  <timeFormatLength type="medium">
    <timeFormat type="standard">
      <pattern type="standard">h:mm:ss a</pattern> 
    </timeFormat>
  </timeFormatLength>
...

Like all other elements, the <default> element is inherited. Thus, it can also refer to inherited resources. For example, suppose that the above resources are present in fr, and that in fr_BE we have the following:

<timeFormats>
  <default type="long"/>
</timeFormats>

In that case, the default time format for fr_BE would be the inherited "long" resource from fr. Now suppose that we had in fr_CA:

  <timeFormatLength type="medium">
    <timeFormat type="standard">
      <pattern type="standard">...</pattern> 
    </timeFormat>
  </timeFormatLength>

In this case, the <default> is inherited from fr, and has the value "medium". It thus refers to this new "medium" pattern in this resource bundle.

5.1.1 Escaping Characters

Unfortunately, XML does not have the capability to contain all Unicode code points. Due to this, extra syntax is required to represent those code points that cannot be otherwise represented in element content. This also must be used where spaces are significant (otherwise they can be stripped).

Escaping Characters
Code Point XML Example
U+0000 <cp hex="0">

Note: This is not necessary in XML 1.0 — except for NULL (U+0000), which is typically never used. However, for backwards compatibility with XML 1.0 systems it is best for some time to come to use these special escapes. These escapes are only allowed in certain elements, according to the DTD.

5.2 Common Attributes

<... type="stroke" ...>

The attribute type is also used to indicate an alternate resource that can be selected with a matching type=option in the locale id modifiers, or be referenced by a default element. For example:

<ldml>
  ...
  <currencies>
    <currency>...</currency>
    <currency type="preEuro">...</currency>
  </currencies>
</ldml>

<... draft="true" ...>

If this attribute is present, it indicates the status of all the data in this element and any subelements (unless they have a contrary draft value).

If an element has the attribute draft="true", then the data is not known to be valid. ("Not known to be" because it may actually be valid, but it has not been vetted.). But it is a bit more complicated than that, since draft="true" is inherited by subelements, and sublocales. For a more formal description of how elements are inherited, and what their draft status is, see Inheritance_and_Validity.

<... alt="proposed" ...>

This attribute should only be present if draft="true". It indicates that the data is proposed replacement data that has been added provisionally until the differences between it and the other data can be vetted. For example, suppose that the translation for September for some language is "Settembru", and a bug report is filed that that should be "Settembro". The new data can be entered in, but marked as alt until it is vetted.

...
<month type="9">Settembru</month>
<month type="9" draft="true" alt="proposed">Settembro</month>
<month type="10">...

The allowable values for alt at this time are "proposed" and "variant". This may be expanded in the future.

<... validSubLocales="de_AT de_CH de_DE" ...>

The attribute validSubLocales allows sublocales in a given tree to be treated as though a file for them were present when there isn't one. It can be applied to any element. It only has an effect for locales that inherit from the current file where a file is missing, and the elements wouldn't otherwise be draft.

For a more complete description of how draft applies to data, see Inheritance_and_Validity.

<... standard="..." ...>

The value of this attribute is a list of strings representing standards: international, national, organization, or vendor standards. The presence of this attribute indicates that the data in this element is compliant with the indicated standards. Where possible, for uniqueness, the string should be a URL that represents that standard. The strings are separated by commas; leading or trailing spaces on each string are not significant. Examples:

<collation standard="MSA 200:2002">
...
<dateFormatStyle standard=”http://www.iso.ch/iso/en/CatalogueDetailPage.CatalogueDetail?CSNUMBER=26780&ICS1=1&ICS2=140&ICS3=30”>

<... references="..." ...>

The value of this attribute is a list of strings representing background information about the element, other than standards. The strings are separated by commas; leading or trailing spaces on each string are not significant.


5.3 <identity>

<!ELEMENT identity (alias | (version, generation, language, script?, territory?, variant?, special*) ) >

The identity element contains information identifying the target locale for this data, and general information about the version of this data.

<version number="1.1">

The version element provides, in an attribute, the version of this file.  The contents of the element can contain textual notes about the changes between this version and the last. For example:

<version number="1.1">Various notes and changes in version 1.1</version>

<generation date="2002-08-28" />

The generation element contains the last modified date for the data. The data is in XML Schema format (yyyy-mm-dd).

<language type="en"/>

The language code is the primary part of the specification of the locale id, with values as described above.

<script type="Latn" />

The script field may be used in the identification of written languages, with values described above.

<territory type="US"/>

The territory code is a common part of the specification of the locale id, with values as described above.

<variant type="nynorsk"/>

The variant code is the tertiary part of the specification of the locale id, with values as described above.

5.4 <localeDisplayNames>

<!ELEMENT localeDisplayNames (alias | (languages?, scripts?, territories?, variants?, keys?, types?, special*)) >

Display names for scripts, languages, countries, and variants in this locale are supplied by this element. These supply localized names for these items for use in user-interfaces for displaying lists of locales and scripts. Examples are given below.

Where present, the display names must be unique; that is, two distinct code would not get the same display name. Any translations should follow customary practice for the locale in question. For more information, see [Data Formats].

<languages>

This contains a list of elements that provide the user-translated names for language codes from [ISO639], as described in Locale_IDs.

<language type="ab">Abkhazian</language>
<language type="aa">Afar</language>
<language type="af">Afrikaans</language>
<language type="sq">Albanian</language>

<scripts>

This element can contain an number of script elements. Each script element provides the localized name for a script, given by the value of the type attribute. The script IDs can be either the long or short forms from Scripts.txt in the UCD. (See UAX #24: Script Names [Scripts] for more information.) For example, in the language of this locale, the name for the Latin script might be "Romana", and for the Cyrillic script is "Kyrillica". That would be expressed with the following.

<script type="Latn">Romana</script>
<script type="Cyrl">Kyrillica</script>

<territories>

This contains a list of elements that provide the user-translated names for territory codes from [ISO3166], as described in Locale_IDs.

<territory type="AF">Afghanistan</territory>
<territory type="AL">Albania</territory>
<territory type="DZ">Algeria</territory>
<territory type="AD">Andorra</territory>
<territory type="AO">Angola</territory>
<territory type="US">United States</territory>

<variants>

This contains a list of elements that provide the user-translated names for the variant_code values described in Locale_IDs.

<variant type="nynorsk">Nynorsk</variant>

<keys>

This contains a list of elements that provide the user-translated names for the key values described in Locale_IDs.

<key type="collation">Sortierung</key>

<types>

This contains a list of elements that provide the user-translated names  for the type values described in Locale_IDs. Since the translation of an option name may depend on the key it is used with, the latter is optionally supplied.

<type type="phonebook" key="collation">Telefonbuch</type>

5.5 <layout>

<!ELEMENT layout ( alias | (orientation?, special*) ) >

This top-level element specifies general layout features. It currently only has one possible element (other than <special>, which is always permitted).

<orientation lines="top-to-bottom" characters="left-to-right" />

The lines and characters attributes specify the default general ordering of lines within a page, and characters within a line. The values are:

Orientation Attributes
Vertical top-to-bottom
bottom-to-top
Horizontal left-to-right
right-to-left

If the lines value is one of the vertical attributes, then the characters value must be one of the horizontal attributes, and vice versa. For example, for English the lines are top-to-bottom, and the characters are left-to-right. For Mongolian the lines are right-to-left, and the characters are top to bottom. This does not override the ordering behavior of bidirectional text; it does, however, supply the paragraph direction for that text (for more information, see UAX #9: The Bidirectional Algorithm [BIDI]).

5.6 <characters>

<!ELEMENT characters (alias | (exemplarCharacters*, mapping*, special*)) >

The <characters> element provides optional information about characters that are in common use in the locale, and information that can be helpful in picking resources or data appropriate for the locale, such as when choosing among character encodings that are typically used to transmit data in the language of the locale. It typically only occurs in a language locale, not in a language/territory locale.

<exemplarCharacters>[a-zåæø]</exemplarCharacters>

The exemplar character set contains the commonly used letters for a given modern form of a language, which can be for testing and for determining the appropriate repertoire of letters for charset conversion or collation. ("Letter is interpreted broadly, as in the Unicode General Category, and also includes syllabaries and ideographs.) It is not a complete set of letters used for a language, nor should it be considered to apply to multiple languages in a particular country. Punctuation and other symbols should not be included. In general, the test to see whether or not a letter belongs in the set is based on whether it is acceptable in that language to always use spellings that avoid that character. For example, the exemplar character set for en (English) is the set [a-z]. This set does not contain the accented letters that are sometimes seen in words like "résumé" or "naïve", because it is acceptable in common practice to spell those words without the accents. The exemplar character set for fr (French), on the other hand, must contain those characters: [a-z é è ù ç à â ê î ô û æ œ ë ï ÿ].

The list of characters is in the Unicode Set format, which allows boolean combinations of sets of letters, including those specified by Unicode properties.

Sequences of characters that act like a single letter in the language — especially in collation — are included within braces, such as [a-z á é í ó ú ö ü ő ű {cs} {dz} {dzs} {gy} ...]. The characters should be in normalized form (NFC). Where combining marks are used generatively, and apply to a large number of base characters (such as in Indic scripts), the individual combining marks should be included. Where they are used with only a few base characters, the specific combinations should be included. Wherever there is not a precomposed character (e.g. single codepoint) for a given combination, that must be included within braces. For example, to include sequences from the Where is my Character? page on the Unicode site, one would write: [{ch} {tʰ} {x̣} {ƛ̓} {ą́} {i̇́} {ト゚}], but for French one would just write [a-z é è ù ...]. When in doubt use braces, since it does no harm to included them around single code points: e.g. [a-z {é} {è} {ù} ...].

The exemplar character set for Han characters is composed somewhat differently. It is even harder to draw a clear line for Han characters, since usage is more like a frequency curve that slowly trails off to the right in terms of decreasing frequency. So for this case, the exemplar characters simply contain a set of reasonably frequent characters for the language.

The letters do not necessarily form a complete set (especially for languages using large character sets, such as CJK). Nor does the list necessarily include letters that are used in common foreign words used in that language. This set is case insensitive; this means it only needs lower case characters. The ordering of these characters are irrelevant. For the special case of Turkish, the dotted capital I should be included. For more information, see [Data Formats].

There can be more than two exemplarCharacters elements, with the second having the type "auxiliary". This element can be used for additional characters that are used in common foreign words, dictionaries, etc. used in the locale.

<characters>
    <exemplarCharacters>[a-zñç]</exemplarCharacters>
    <exemplarCharacters type="auxiliary">[ä ö ü ß]</exemplarCharacters> 
</characters>

<mapping registry="iana" type="windows-1252"/>

There can be multiple mapping elements. Each indicates the character conversion mapping table name for a character encoding that may be commonly used to encode data in the language of this locale. The version field of the mapping table is omitted. The ordering among the mapping elements is not significant. The mapping elements themselves are not inherited from parents.

The registry indicates the source of the encoding. Currently the only registry that can be used is "iana", which specifies use of  an IANA name.  Note: while IANA names are not precise for conversion (see UTR #22: Character Mapping Tables [CharMapML]), they are sufficient for this purpose.

5.7 <delimiters>

<!ELEMENT delimiters (alias | (quotationStart*, quotationEnd*, alternateQuotationStart*, alternateQuotationEnd*, special*)) >

The delimiters supply common delimiters for bracketing quotations. The quotation marks are used with simple quoted text, such as:

He said, “Don’t be absurd!”

The alternate marks are used with embedded quotations, such as:

He said, “Remember what the Mad Hatter said: ‘Not the same thing a bit! Why you might just as well say that “I see what I eat” is the same thing as “I eat what I see”!’”

<quotationStart></quotationStart>
<quotationEnd></quotationEnd>
<alternateQuotationStart></alternateQuotationStart>
<alternateQuotationEnd></alternateQuotationEnd>

5.8 <measurement>

<!ELEMENT measurement (alias | (measurementSystem?, paperSize?, special*)) >

<measurementSystem type="US"/>

The measurement system is the normal measurement system in common everyday use (except for date/time). The values are "metric" (= ISO 1000), "US", or "UK"; others may be added over time. The "US" value indicates the customary feet, inches, pints, quarts, etc. system. The "UK" value is also called the Imperial system: the pint, quart, etc. are different sizes than in "US".

Note: In the future, we may need to add display names for the particular measurement units (millimeter vs millimetre vs whatever the Greek, Russian, etc are), and a message format for position those with respect to numbers. E.g. "{number} {unitName}" in some languages, but "{unitName} {number}" in others.

Note: Numbers indicating measurements should never be interchanged without known dimensions. You never want the number 3.51 interpreted as 3.51 feet by one user and 3.51 meters by another. However, this element can be used to convert dimensioned numbers into the user's desired notation: so the value of 3.51 meters can be formatted as 11.52 feet on a particular user's system.

<paperSize>

The paperSize element gives the height and width of paper used for normal business letters. The units for the numbers are always in millimeters. For example, the paperSize in the root (the default) is A4:

<paperSize>
  <height>297</height>
  <width>210</width>
</paperSize>

An example of locale data that differs from this would be en-US:

<paperSize>
  <height>279</height>
  <width>216</width>
</paperSize>

5.9 <dates>

<!ELEMENT dates (alias | (localizedPatternChars*, calendars?, timeZoneNames?, special*)) >

This top-level element contains information regarding the format and parsing of dates and times. The data is based on the Java/ICU format. Most of these are fairly self-explanatory, except the week elements, localizedPatternChars, and the meaning of the pattern characters. For information on this, and more information on other elements and attributes, see Appendix F: Date Format Patterns.

5.9.1 <calendars>

<!ELEMENT calendar (alias | (months?, monthNames?, monthAbbr?, days?, dayNames?, dayAbbr?, week?, am?, pm?, eras?, dateFormats?, timeFormats?, dateTimeFormats?, fields*, special*))>

This element contains multiple <calendar> elements, each of which specifies the fields used for formatting and parsing dates and times according to the given calendar. The month names are identified numerically, starting at 1. The day names are identified with short strings, since there is no universally-accepted numeric designation.

Many calendars will only differ from the Gregorian Calendar in the year and era values. For example, the Japanese calendar will have many more eras (one for each Emperor), and the years will be numbered within that era. All calendar data inherits from the Gregorian calendar in the same locale data (if not present in the chain up to root), so only the differing data will be present. See Multiple Inheritance.

<!ELEMENT months ( alias | (default?, monthContext*, special*)) >
<!ELEMENT monthContext ( alias | (default?, monthWidth*, special*)) >
<!ELEMENT monthWidth ( alias | (month*, special*)) >

<!ELEMENT days ( alias | (default?, dayContext*, special*)) >
<!ELEMENT dayContext ( alias | (default?, dayWidth*, special*)) >
<!ELEMENT dayWidth ( alias | (day*, special*)) >

Both month and day names may vary along two axes: the width and the context. The context is either format (the default), the form used within a date format string (such as "Saturday, November 12th", or stand-alone, the form used independently, such as in Calendar headers. The width can be wide (the default), abbreviated, or narrow. The latter is the shortest possible width: it is typically used in calendar headers. The values in formats must be distinct; that is, "S" could not be used both for Saturday and for Sunday. The same is not true for stand-alone values; they might only be distinguished by context, especially in the narrow format.

If the stand-alone form does not exist (in the chain up to root), then it inherits from the format form. See Multiple Inheritance.

The older monthNames, dayNames, and monthAbbr, dayAbbr are maintained for backwards compatibility. They are equivalent to: using the months element with the context type="format" and the width type="wide" (for ...Names) and type="narrow" (for ...Abbr), respectively.

Example:

  <calendar type="gregorian">
    <months>
      <default type="format"/>
      <monthContext type="format">
         <default type="wide"/>
         <monthWidth type="wide">
            <month type="1">January</month>
            <month type="2">February</month>
...
            <month type="11">November</month>
            <month type="12">December</month>
        </monthWidth>
        <monthWidth type="abbreviated">
            <month type="1">Jan</month>
            <month type="2">Feb</month>
...
            <month type="11">Nov</month>
            <month type="12">Dec</month>
        </monthWidth>
       <monthContext type="stand-alone">
         <default type="wide"/>
         <monthWidth type="wide">
            <month type="1">Januaria</month>
            <month type="2">Februaria</month>
...
            <month type="11">Novembria</month>
            <month type="12">Decembria</month>
        </monthWidth>
        <monthWidth type="narrow">
            <month type="1">J</month>
            <month type="2">F</month>
...
            <month type="11">N</month>
            <month type="12">D</month>
        </monthWidth>
       </monthContext>
    </months>

    <days>
      <default type="format"/>
      <dayContext type="format">
         <default type="wide"/>
         <dayWidth type="wide">
            <day type="sun">Sunday</day>
            <day type="mon">Monday</day>
...
            <day type="fri">Friday</day>
            <day type="sat">Saturday</day>
        </dayWidth>
        <dayWidth type="abbreviated">
            <day type="sun">Sun</day>
            <day type="mon">Mon</day>
...
            <day type="fri">Fri</day>
            <day type="sat">Sat</day>
        </dayWidth>
        <dayWidth type="narrow">
            <day type="sun">Su</day>
            <day type="mon">M</day>
...
            <day type="fri">F</day>
            <day type="sat">Sa</day>
        </dayWidth>
      </dayContext>
      <dayContext type="stand-alone">
        <dayWidth type="narrow">
            <day type="sun">S</day>
            <day type="mon">M</day>
...
            <day type="fri">F</day>
            <day type="sat">S</day>
        </dayWidth>
      </dayContext>
    </days>
    <week>
        <minDays count="1"/>
        <firstDay day="sun"/>
        <weekendStart day="fri" time="18:00"/>
        <weekendEnd day="sun" time="18:00"/>
    </week>

    <am>AM</am>
    <pm>PM</pm>

    <eras>
       <eraAbbr>
        <era type="0">BC</era>
        <era type="1">AD</era>
       </eraAbbr>
       <eraName>
        <era type="0">Before Christ</era>
        <era type="1">Anno Domini</era>
       </eraName>
    </eras>

<dateFormats>

<!ELEMENT dateFormats (alias | (default?, dateFormatLength*, special*)) >
<!ELEMENT dateFormatLength (alias | (default?, dateFormat*, special*)) >
<!ELEMENT dateFormat (alias | (pattern*, displayName?, special*)) >

Date formats have the following form:

    <dateFormats>
      <default type=”medium”/>
      <dateFormatLength type=”full”>
        <dateFormat>
          <pattern>EEEE, MMMM d, yyyy</pattern>
        </dateFormat>
       </dateFormatLength>
     <dateFormatLength type="medium">
       <default type="DateFormatsKey2">
       <dateFormat type="DateFormatsKey2">
        <pattern>MMM d, yyyy</pattern>
       </dateFormat>
       <dateFormat type="DateFormatsKey3">
         <pattern>MMM dd, yyyy</pattern>
        </dateFormat>
      </dateFormatLength>
    <dateFormats>

<timeFormats>

<!ELEMENT timeFormats (alias | (default?, timeFormatLength*, special*)) >
<!ELEMENT timeFormatLength (alias | (default?, timeFormat*, special*)) >
<!ELEMENT timeFormat (alias | (pattern*, displayName?, special*)) >

Time formats have the following form:

     <timeFormats>
       <default type="medium"/>
       <timeFormatLength type=”full”>
         <timeFormat>
           <displayName>DIN 5008 (EN 28601)</displayName>
           <pattern>h:mm:ss a z</pattern>
         </timeFormat>
       </timeFormatLength>
       <timeFormatLength type="medium">
         <timeFormat>
           <pattern>h:mm:ss a</pattern>
         </timeFormat>
       </timeFormatLength>
     </timeFormats>

     <dateTimeFormats>
       <default type="medium"/>
       <dateTimeFormatLength type=”full”>
         <dateTimeFormat>
            <pattern>{0} {1}</pattern>
         </dateTimeFormat>
       </dateTimeFormatLength>
     </dateTimeFormats>
  </calendar>

  <calendar class="buddhist">
    <eras>
        <era type="0">BE</era>
    </eras>
  </calendar>

<week>

<!ELEMENT week (alias | (minDays?, firstDay?, weekendStart?, weekendEnd?, special*))>

The weekendStart time defaults to "00:00:00" (midnight at the start of the day). The weekendEnd time defaults to "24:00:00" (midnight at the end of the day). (That is, Friday at 24:00:00 is the same time as Saturday at 00:00:00.) Thus the following are equivalent:

<weekendStart day="sat"/>
<weekendEnd day="sun"/>
<weekendStart day="sat" time="00:00"/>
<weekendEnd day="sun" time="24:00"/>
<weekendStart day="fri" time="24:00"/>
<weekendEnd day="mon" time="00:00"/>

For information on the other fields, see Appendix F: Date Format Patterns.


Calendar Fields

<!ELEMENT fields ( alias | (field*, special*)) >
<!ELEMENT field ( alias | (displayName?, relative*, special*)) >

Translations may be supplied for names of calendar fields, and for relative values of those fields.

<calendars>
  <fields>
   <field type='day'>
    <displayName>Tag</displayName>
    <relative type='-2'>Vorgestern</relative>
    <relative type='-1'>Gestern</relative>
    <relative type='0'>Heute</relative>
    <relative type='1'>Morgen</relative>
    <relative type='2'>Übermorgen</relative>
   </field>
  </fields>
</calendars>

5.9.2 <timeZoneNames>

<!ELEMENT timeZoneNames (alias | (hourFormat?, hoursFormat?, gmtFormat?, regionFormat?, fallbackFormat?, abbreviationFallback?, preferenceOrdering?, default?, zone*, special*)) >
<!ELEMENT zone (alias | ( long*, short*, exemplarCity*, special*)) >

The timezone IDs are language-independent, and follow the Olson Data [Olson]. However, the display names for those IDs can vary by locale. The generic time is so-called wall-time; what clocks use when they are correctly switched from standard to daylight time at the mandated time of the year.

Note: The type field for each zone is the identification of that zone. It is not to be translated.

<zone type="America/Los_Angeles" >
    <long>
        <generic>Pacific Time</generic>
        <standard>Pacific Standard Time</standard>
        <daylight>Pacific Daylight Time</daylight>
    </long>
    <short>
        <generic>PT</generic>
        <standard>PST</standard>
        <daylight>PDT</daylight>
    </short>
    <exemplarCity>San Francisco</exemplarCity>
</zone>

<zone type="Europe/London">
     <long>
        <generic>British Time</generic>
        <standard>British Standard Time</standard>
        <daylight>British Daylight Time</daylight>
    </long>
    <exemplarCity>York</exemplarCity>
</zone>

Note: Transmitting "14:30" with no other context is incomplete unless it contains information about the time zone. Ideally one would transmit neutral-format date/time information, commonly in UTC, and localize as close to the user as possible. (For more about UTC, see [UTCInfo].)

The conversion from local time into UTC depends on the particular time zone rules, which will vary by location. The standard data used for converting local time (sometimes called wall time) to UTC and back is the Olson Data [Olson], used by UNIX, Java, ICU, and others. The data includes rules for matching the laws for time changes in different countries. For example, for the US it is:

"During the period commencing at 2 o'clock antemeridian on the first Sunday of April of each year and ending at 2 o'clock antemeridian on the last Sunday of October of each year, the standard time of each zone established by sections 261 to 264 of this title, as modified by section 265 of this title, shall be advanced one hour..." (United States Law - 15 U.S.C. §6(IX)(260-7)).

Each region that has a different timezone or daylight savings time rules, either now or at any time in the past, is given a unique internal ID, such as Europe/Paris. As with currency codes, these are internal codes that should be localized if exposed to a user (such as in the Windows Control Panels>Date/Time>Time Zone).

Unfortunately, laws change over time, and will continue to change in the future, both for the boundaries of timezone regions and the rules for daylight savings. Thus the Olson data is continually being augmented. Any two implementations using the same version of the Olson data will get the same results for the same IDs (assuming a correct implementation). However, if implementations use different versions of the data they may get different results. So if precise results are required then both the Olson ID and the Olson data version must be transmitted between the different implementations.

For more information, see [Data Formats].

The following subelements of timezoneNames are used to control the fallback process described in Appendix J: Time Zone Fallback.

Element Name Data Examples Results/Comment
hour-format "+HHmm;-HHmm" "+1200"
"-1200"
hours-format "{0}/{1}" "-0800/-0700"
gmt-format "GMT{0}" "GMT-0800"
"{0}ВпГ" "-0800ВпГ"
region-format "{0} Time" "Japan Time"
"Tiempo de {0}" "Tiempo de Japón"
fallback-format "Tiempo de «{0}»" "Tiempo de «Tokyo»"
abbreviationFallback type="GMT" causes any "long" match to be skipped in Timezone fallbacks
preferenceOrdering type="America/Mexico_City America/Chihuahua America/New_York" a preference ordering among modern zones


5.10 <numbers>

<!ELEMENT numbers (alias | (symbols?, decimalFormats?, scientificFormats?, percentFormats?, currencyFormats?, currencies?, special*)) >

The numbers element supplies information for formatting and parsing numbers and currencies. It has the following sub-elements: <symbols>, <decimalFormats>, <scientificFormats>, <percentFormats>, <currencyFormats>, and <currencies>. The currency IDs are from [ISO4217] (plus some additional common-use codes). For more information, including the pattern structure, see Appendix G: Number Pattern Format.

<!ELEMENT symbols (alias | (decimal?, group?, list?, percentSign?, nativeZeroDigit?, patternDigit?, plusSign?, minusSign?, exponential?, perMille?, infinity?, nan?, special*)) >

<symbols>
      <decimal>.</decimal>
      <group>,</group>
      <list>;</list>
      <percentSign>%</percentSign>
      <nativeZeroDigit>0</nativeZeroDigit>
      <patternDigit>#</patternDigit>
      <plusSign>+</plusSign>
      <minusSign>-</minusSign>
      <exponential>E</exponential>
      <perMille></perMille>
      <infinity></infinity>
      <nan></nan>
</symbols>

<!ELEMENT decimalFormats (alias | (default?, decimalFormatLength*, special*))>
<!ELEMENT decimalFormatLength (alias | (default?, decimalFormat*, special*))>
<!ELEMENT decimalFormat (alias | (pattern*, special*)) >
(scientificFormats, percentFormats, and currencyFormats have the same structure)

<decimalFormats>
  <decimalFormatLength type="long">
    <decimalFormat>
      <pattern>#,##0.###</pattern>
    </decimalFormat>
  </decimalFormatLength>
</decimalFormats>
<scientificFormats>
  <default type="long"/>
  <scientificFormatLength type="long">
    <scientificFormat>
      <pattern>0.000###E+00</pattern>
    </scientificFormat>
  </scientificFormatLength>
  <scientificFormatLength type="medium">
    <scientificFormat>
      <pattern>0.00##E+00</pattern>
    </scientificFormat>
  </scientificFormatLength>
</scientificFormats>
<percentFormats>
  <percentFormatLength type="long">
    <percentFormat>
      <pattern>#,##0%</pattern>
    </percentFormat>
  </percentFormatLength>
</percentFormats>
<currencyFormats>
  <currencyFormatLength type="long">
    <currencyFormat>
      <pattern>¤ #,##0.00;(¤ #,##0.00)</pattern>
    </currencyFormat>
  </currencyFormatLength>
</currencyFormats>

<!ELEMENT currency (alias | (displayName?, symbol?, pattern*, decimal?, group?, special*)) >

<currencies>
    <currency type="USD">
        <displayName>Dollar</displayName>
        <symbol>$</symbol>
    </currency>
    <currency type ="JPY">
        <displayName>Yen</displayName>
        <symbol>¥</symbol>
    </currency>
    <currency type ="INR">
        <displayName>Rupee</displayName>
        <symbol choice="true">0≤Rf|1≤Ru|1&lt;Rf</symbol>
    </currency>
    <currency type="PTE">
        <displayName>Escudo</displayName>
        <symbol>$</symbol>
    </currency>
</currencies>

In formatting currencies, the currency number format is used with the appropriate symbol from <currencies>, according to the currency code. The <currencies> list can contain codes that are no longer in current use, such as PTE. The choice attribute can be used to indicate that the value uses a pattern interpreted as in Appendix H: Choice Patterns.

Currencies can also contain optional grouping, decimal data, and pattern elements. This data is inherited from the <symbols> in the same locale data (if not present in the chain up to root), so only the differing data will be present. See Multiple Inheritance.

Note: Currency values should never be interchanged without a known currency code. You never want the number 3.5 interpreted as $3.5 by one user and ¥3.5 by another. Locale data contains localization information for currencies, not a currency value for a country. A currency amount logically consists of a numeric value, plus an accompanying currency code (or equivalent). The currency code may be implicit in a protocol, such as where USD is implicit. But if the raw numeric value is transmitted without any context, then it has no definitive interpretation.

Notice that the currency code is completely independent of the end-user's language or locale. For example, RUR is the code for Russian Rubles. A currency amount of <RUR, 1.23457×10³> would be localized for a Russian user into "1 234,57р." (using U+0440 (р) cyrillic small letter er). For an English user it would be localized into the string "Rub 1,234.57" The end-user's language is needed for doing this last localization step; but that language is completely orthogonal to the currency code needed in the data. After all, the same English user could be working with dozens of currencies.Notice also that the currency code is also independent of whether currency values are inter-converted, which requires more interesting financial processing: the rate of conversion may depend on a variety of factors.

Thus logically speaking, once a currency amount is entered into a system, it should be logically accompanied by a currency code in all processing. This currency code is independent of whatever the user's original locale was. Only in badly-designed software is the currency code (or equivalent) not present, so that the software has to "guess" at the currency code based on the user's locale.

Note: The number of decimal places and the rounding for each currency is not locale-specific data, and is not contained in the Locale Data Markup Language format. Those values override whatever is given in the currency numberFormat. For more information, see Supplemental Data.

For background information on currency names, see [CurrencyInfo].

5.11 <posix>

<!ELEMENT posix (alias | (messages*, special*)) >
<!ELEMENT messages (alias | ( yesstr?, nostr?, yesexpr?, noexpr?)) >

The following are included for compatibility with POSIX.

 <posix>
       <posix:messages>
            <posix:yesstr>Yes</posix:yesstr>
            <posix:nostr>No</posix:nostr>
            <posix:yesexpr>^[Yy].*</posix:yesexpr>
            <posix:noexpr>^[Nn].*</posix:noexpr>
        </posix:messages>
 <posix>

5.12 <collations>

<!ELEMENT collations (alias | (default?, collation*, special*)) >

This section contains one or more collation elements, distinguished by type. Each collation contains rules that specify a certain sort-order, as a tailoring of the UCA table defined in UTS #10: Unicode Collation Algorithm [UCA]. (For a chart view of the UCA, see Collation Chart [UCAChart].) This syntax is an XMLized version of the Java/ICU syntax. For illustration, the rules are accompanied by the corresponding basic ICU rule syntax [ICUCollation] (used in ICU and Java) and/or the ICU parameterizations, and the basic syntax may be used in examples.

Note: ICU provides a concise format for specifying orderings, based on tailorings to the UCA. For example, to specify that k and q follow 'c', one can use the rule: "& c < k < q". The rules also allow people to set default general parameter values, such as whether uppercase is before lowercase or not. (Java contains an earlier version of ICU, and has not been updated recently. It does not support any of the basic syntax marked with [...], and its default table is not the UCA.)

However, it is not necessary for ICU to be used in the underlying implementation. The features are simply related to the ICU capabilities, since that supplies more detailed examples. Note: there is an on-line demonstration of collation at [LocaleExplorer] (pick the locale and scroll to "Collation Rules").

Version

The version attribute is used in case a specific version of the UCA is to be specified. It is optional, and is specified if the results are to be identical on different systems. If it is not supplied, then the version is assumed to be the same as the Unicode version for the system as a whole.

Note: For version 3.1.1 of the UCA, the version of Unicode must also be specified with any versioning information; an example would be "3.1.1/4.0" for version 3.1.1 of the UCA, for version 3.2 of Unicode. This has been changed by decision of the UTC, so that it will no longer be necessary as of UCA 4.0. So for 4.0 and beyond, the version just has a single number.

5.12.1 <collation>

<!ELEMENT collation (alias | (base?, settings?, suppress_contractions?, optimize?, rules?, special*)) >

Like the ICU rules, the tailoring syntax is designed to be independent of the actual weights used in any particular UCA table. That way the same rules can be applied to UCA versions over time, even if the underlying weights change. The following describes the overall document structure of a collation:

<collation>
 <settings caseLevel="on"/>
 <rules>
  <!-- rules go here -->
 </rules>
</collation>

The optional base element <base>...</base>, contains an alias element that points to another data source that defines a base collation. If present, it indicates that the settings and rules in the collation are modifications applied on top of the respective elements in the base collation. That is, any successive settings, where present, override what is in the base as described in Setting Options. Any successive rules are concatenated to the end of the rules in the base. The results of multiple rules applying to the same characters is covered in Orderings.

Setting Options

In XML, these are attributes of <settings>. For example, <setting strength="secondary"> will only compare strings based on their primary and secondary weights.

If the attribute is not present, the default (or for the base url's attribute, if there is one) is used. The default is listed in italics.

Collation Settings
Attribute Options Basic Example   XML Example Description
strength primary (1)
secondary (2)
tertiary (3)
quarternary (4)
identical (5)
[strength 1] strength = "primary" Sets the default strength for comparison, as described in the UCA.
alternate non-ignorable
shifted
[alternate non-ignorable] alternate = "non-ignorable" Sets alternate handling for variable weights, as described in UCA
backwards on
off
[backwards 2]   backwards = "on" Sets the comparison for the second level to be backwards ("French"), as described in UCA
normalization on
off
[normalization on]  normalization = "off" If on, then the normal UCA algorithm is used. If off, then all strings that are in [FCD] will sort correctly, but others won't. So should only be set off if the the strings to be compared are in FCD.
caseLevel on
off
[caseLevel on] caseLevel = "off" If set to on, a level consisting only of case characteristics will be inserted in front of tertiary level. To ignore accents but take cases into account, set strength to primary and case level to on
caseFirst upper
lower
off
[caseFirst off] caseFirst = "off" If set to upper, causes upper case to sort before lower case. If set to lower, lower case will sort before upper case. Useful for locales that have already supported ordering but require different order of cases. Affects case and tertiary levels.
hiraganaQ on
off
[hiraganaQ on] hiragana­Quarternary = "on" Controls special treatment of Hiragana code points on quaternary level. If turned on, Hiragana codepoints will get lower values than all the other non-variable code points. The strength must be greater or equal than quaternary if you want this attribute to take effect.
numeric on
off
[numeric on] numeric = "on" If set to on, any sequence of Decimal Digits (General_Category = Nd in the [UCD]) is sorted at a primary level with its numeric value. For example, "A-21" < "A-123".

 

Collation Rule Syntax

<!ELEMENT rules (alias | ( reset, ( reset | p | pc | s | sc | t | tc | q | qc | i | ic | x)* )) >

The goal for the collation rule syntax is to have clearly expressed rules with a concise format, that parallels the Basic syntax as much as possible.  The rule syntax uses abbreviated element names for primary (level 1), secondary (level 2), tertiary (level 3), and identical, to be as short as possible. The reason for this is because the tailorings for CJK characters are quite large (tens of thousands of elements), and the extra overhead would have been considerable. Other elements and attributes do not occur as frequently, and have longer names.

Note: The rules are stated in terms of actions that cause characters to change their ordering relative to other characters. This is for stability; assigning characters specific weights would not work, since the exact weight assignment in UCA (or ISO 14651) is not required for conformance — only the relative ordering of the weights. In addition, stating rules in terms of relative order is much less sensitive to changes over time in the UCA itself.

Orderings

The following are the normal ordering actions used for the bulk of characters. Each rule contains a string of ordered characters that starts with an anchor point or a reset value. The reset value is an absolute point in the UCA that determines the order of other characters. For example, the rule & a < g, places "g" after "a" in a tailored UCA: the "a" does not change place. Logically, subsequent rule after a reset indicates a change to the ordering (and comparison strength) of the characters in the UCA. For example, the UCA has the following sequence (abbreviated for illustration):

... a <3 a <3 ⓐ <3 A <3 A <3 Ⓐ <3 ª <2 á <3 Á <1 æ <3 Æ <1 ɐ <1 ɑ <1 ɒ <1 b <3 b <3 ⓑ <3 B <3 B <3 ℬ ...

Whenever a character is inserted into the UCA sequence, it is inserted at the first point where the strength difference will not disturb the other characters in the UCA. For example, & a < g puts g in the above sequence with a strength of L1. Thus the g must go in after any lower strengths,  as follows:

... a <3 a <3 ⓐ <3 A <3 A <3 Ⓐ <3 ª <2 á <3 Á <1 g <1 æ <3 Æ <1 ɐ <1 ɑ <1 ɒ <1 b <3 b <3 ⓑ <3 B <3 B <3 ℬ ...

The rule & a << g, which uses a level-2 strength, would produce the following sequence:

... a <3 a <3 ⓐ <3 A <3 A <3 Ⓐ <3 ª <2 g <2 á <3 Á <1 æ <3 Æ <1 ɐ <1 ɑ <1 ɒ <1 b <3 b <3 ⓑ <3 B <3 B <3 ℬ ...

And the rule & a <<< g, which uses a level-3 strength, would produce the following sequence:

... a <3 g <3 a <3 ⓐ <3 A <3 A <3 Ⓐ <3 ª <2 á <3 Á <1 æ <3 Æ <1 ɐ <1 ɑ <1 ɒ <1 b <3 b <3 ⓑ <3 B <3 B <3 ℬ ...

Since resets always work on the existing state, the rule entries must be are in the proper order. A character or sequence may occur multiple times; each subsequent occurrence causes a different change. The following shows the result of serially applying a three rules.

  Rules   Result Comment  
1 & a < g ... a <1 g ... Put g after a.
2 & a < h < k ... a <1 h <1 k <1 g ... Now put h and k after a (inserting before the g).
3 & h << g ... a <1 h <1 g <1 k ... Now put g after h (inserting before k).

Notice that characters can occur multiple times, and thus override previous rules.

Except for the case of expansion sequence syntax, every sequence after a reset is equivalent in action to breaking up the sequence into an atomic rule: a reset + relation pair. The tailoring is then equivalent to applying each of the atomic rules to the UCA in order, according to the above description.

Example:

Rules Equivalent Atomic Rules
& b < q <<< Q
& a < x <<< X << q <<< Q < z
& b < q
& q <<< Q
& a < x
& x <<< X
& X << q
& q <<< Q
& Q < z

In the case of expansion sequence syntax, the equivalent atomic sequence can be derived by first transforming the expansion sequence syntax into normal expansion syntax. (See Expansions.)

<!ELEMENT reset ( #PCDATA | cp | ... )* >
<!ELEMENT p ( #PCDATA | cp | last_variable )* >
(Elements pc, s, sc, t, tc, q, qc, i, and ic have the same structure as p.)

Specifying Collation Ordering
Basic Symbol Basic Example XML Symbol XML Example Description
&   & Z   <reset> <reset>Z</reset> Don't change the ordering of Z, but place subsequent characters relative to it.
<   & a
< b  
<p> <reset>a<reset>
<p>b</p>
Make 'b' sort after 'a', as a primary (base-character) difference
<<   & a
<< ä  
<s> <reset>a<reset>
<s>ä</s>
Make 'ä' sort after 'a' as a secondary (accent) difference
<<<   & a
<<< A  
<t> <reset>a<reset>
<t>A</t>
Make 'A' sort after 'a' as a tertiary (case/variant) difference
=   & x
= y  
<i> <reset>v<reset>
<i>w</i>
Make 'w' sort identically to 'v'

Resets only need to be at the start of a sequence, to position the characters relative a character that is in the UCA (or has already occurred in the tailoring). For example: <reset>z</reset><p>a</p><p>b</p><p>c</p><p>d</p>.

Some additional elements are provided to save space with large tailorings. The addition of a 'c' to the element name indicates that each of the characters in the contents of that element are to be handled as if they were separate elements with the corresponding strength:

Abbreviating Ordering Specifications
XML Symbol XML Example Equivalent
<pc> <pc>bcd</pc> <p>b</p><p>c</p><p>d</p>
<sc> <sc>àáâã</sc> <s>à</s><s>á</s><s>â</s><s>ã</s>
<tc> <tc>PpP</tc> <t>P</t><t></t><t></t>
<ic> <ic>VwW</ic> <i>V</i><i>w</i><i>W</i>

Contractions

To sort a sequence as a single item (contraction), just use the sequence, e.g.

Specifying Contractions
BASIC Example XML Example Description
& k
< ch
<reset>k<reset>
<p>ch</p>
Make the sequence 'ch' sort after 'k', as a primary (base-character) difference

Expansions

<!ELEMENT x (context?, ( p | pc | s | sc | t | tc | q | qc | i | ic )*, extend? ) >

There are two ways to handle expansions (where a character sorts as a sequence) with both the basic syntax and the XML syntax. The first method is to reset to the sequence of characters. This is called sequence expansion syntax. The second is to use the extension sequence. Both are equivalent in practice (unless the reset sequence happens to be a contraction). This is called normal expansion syntax.

Specifying Expansions
Basic XML Description
& c 
<< k / h
<reset>c</reset>
<x><s>k</s> <extend>h</extend></x>
normal expansion syntax:
Make 'k' sort after the sequence 'ch'; thus 'k' will behave as if it expands to a character after 'c' followed by an 'h'.
& ch
<< k
<reset>ch</reset>
<s>k</s>
sequence expansion syntax:
Make 'k' sort after the sequence 'ch'; thus 'k' will behave as if it expands to a character after 'c' followed by an 'h'.

(unless 'ch' is defined beforehand as a contraction).

If an <extend> element is necessary, it requires the rule to be embedded in an <x> element.

The sequence expansion syntax can be quite tricky, so it should be avoided where possible. In particular:

Each extension replaces the one before it; it does not append to it. So

& ab << c
& cd << e

is equivalent to:

& a << c / b << e / d

and produces the following weights (where p(x) is the primary weight and s(a) is the secondary weight):

Character Weights
c p(a), p(b); s(a)+1, s(b); ...
e p(a), p(d); s(a)+2, s(d); ...

When expressing rules as atomic rules, the sequences must first be transformed into normal expansion syntax:

Expansion Sequence Normal Expansion Equivalent Atomic Rules
& ab << q <<< Q
& ad <<< AD < x <<< X
& a << q / b <<< Q / b
& a <<< AD / d < x <<< X
& b << q / b
& q <<< Q / b
& a < AD / d
& AD < x
& x<<< X

Context Before

The context before a character can affect how it is ordered, such as in Japanese. This could be expressed with a combination of contractions and expansions, but is faster using a context. (The actual weights produced are different, but the resulting string comparisons are the same.) If a context element occurs, it must be the first item in the rule.

Specifying Previous Context
Basic XML
&[before 3] ァ
<<< ァ|ー
= ァ |ー
= ぁ|ー
<reset before="tertiary"></reset>
<x><context></context><s></s></x>
<x><context></context><i></i></x>
<x><context></context><i></i></x>

If an <extend> element is necessary, it requires the rule to be embedded in an <x> element. There can also be a <context> at the same time. For example, the following are allowed:

Placing Characters Before Others

There are certain circumstances where characters need to be placed before a given character, rather than after. This is the case with Pinyin, for example, where certain accented letters are positioned before the base letter. That is accomplished with the following syntax.

Placing Characters Before Others
Item Options Basic Example   XML Example
before  primary
secondary
tertiary
& [before 2] a
<< à
<reset before="secondary">a</reset>
<s>à</s>

It is an error if the strength of the before relation is not identical to the relation after the reset. Thus the following are errors, since the value of the before attribute does not agree with the relation <s>.

Basic Example   XML Example
& [before 2] a
< à
<reset before="primary">a</reset>
<s>à</s>
Error
& [before 2] a
<<< à
<reset before="tertiary">a</reset>
<s>à</s>
Error

Logical Reset Positions

<!ELEMENT reset ( ... | first_variable| last_variable | first_tertiary_ignorable | last_tertiary_ignorable | first_secondary_ignorable | last_secondary_ignorable | first_primary_ignorable | last_primary_ignorable | first_non_ignorable | last_non_ignorable | first_trailing | last_trailing )* >

The UCA has the following overall structure for weights, going from low to high.

Specifying Logical Positions
Name Description UCA Examples
first tertiary ignorable
...
last tertiary ignorable
p, s, t = ignore Control Codes
Format Characters
Hebrew Points
Tibetan Signs
...
first secondary ignorable
...
last secondary ignorable
p, s = ignore None in UCA
first primary ignorable
...
last primary ignorable
p = ignore Most combining marks
first variable
...
last variable
if alternate = non-ignorable
p != ignore,
if alternate = shifted
p, s, t = ignore
Whitespace,
Punctuation,
Symbols
first non-ignorable
...
last non-ignorable
p != ignore Small number of exceptional symbols
[e.g. U+02D0 MODIFIER LETTER TRIANGULAR COLON]
Numbers
Latin
Greek
...
implicits p != ignore, assigned automatically CJK, CJK compatibility (those that are not decomposed)
CJK Extension A, B
Unassigned
first trailing
...
last trailing
p != ignore,
used for trailing syllable components
Jamo Trailing
Jamo Leading

Each of the above Names (except implicits) can be used with a reset to position characters relative to that logical position. That allows characters to be ordered before or after a logical position rather than a specific character.

Note: The reason for this is so that tailorings can be more stable. A future version of the UCA might add characters at any point in the above list. Suppose that you set character X to be after Y. It could be that you want X to come after Y, no matter what future characters are added; or it could be that you just want Y to come after a given logical position, e.g. after the last primary ignorable.

Here is an example of the syntax:

Sample Logical Position
Basic XML
& [first tertiary ignorable]
<< à 
<reset><first_tertiary_ignorable/></reset>
<s>à</s>

For example, to make a character be a secondary ignorable, one can make it be immediately after (at a secondary level) a specific character (like a combining dieresis), or one can make it be immediately after the last secondary ignorable.

The last-variable element indicates the "highest" character that is treated as punctuation with alternate handling. Unlike the other logical positions, it can be reset as well as referenced. For example, it can be reset to be just above spaces if all visible punctuation are to be treated as having distinct primary values.

Specifying Last-Variable
Attribute Options Basic Example   XML Example
variableTop at & x
= [last variable]
<reset>x</reset>
<i><last_variable/></i>
after & x
< [last variable]
<reset>x</reset>
<p><last_variable/></p>
before & [before 1] x
< [last variable]
<reset before="primary">x</reset>
<p><last_variable/></p>

The default value for variable-top depends on the UCA setting. For example, in 3.1.1, the value is at:

U+1D7C3 MATHEMATICAL SANS-SERIF BOLD ITALIC PARTIAL DIFFERENTIAL

The <last_variable/> cannot occur inside an <x> element, nor can there be any element content. Thus there can be no <context> or <extend> or text data in the rule. For example, the following are all disallowed:

Special-Purpose Commands

The suppress contractions tailoring command turns off any existing contractions that begin with those characters. It is typically used to turn off the Cyrillic contractions in the UCA, since they are not used in many languages and have a considerable performance penalty. The argument is a Unicode Set.

The optimize tailoring command is purely for performance. It indicates that those characters are sufficiently common in the target language for the tailoring that their performance should be enhanced.

Special-Purpose Commands
Basic XML
[suppress contractions [Љ-ґ]] <suppress_contractions>[Љ-ґ]</suppress_contractions>
[optimize [Ά-ώ]] <optimize>[Ά-ώ]</optimize>


The reason that these are not settings is so that their contents can be arbitrary characters.


Example Collation

The following is a simple example that takes portions of the Swedish tailoring plus part of a Japanese tailoring, for illustration. For more complete examples, see the actual locale data: Japanese, Chinese, Swedish, Traditional German are particularly illustrative.

<collation version="3.1.1">
  <settings caseLevel="on"/>
  <rules>
        <reset>Z</reset>
        <p>æ</p>
        <t>Æ</t>
        <p></p>
        <t></t>
        <t>aa</t>
        <t>aA</t>
        <t>Aa</t>
        <t>AA</t>
        <p></p>
        <t></t>
        <p></p>
        <t></t>
        <s></s>
        <t></t>
        <p></p>
        <t></t>
        <s>ø</s>
        <t>Ø</t>
        <reset>V</reset>
        <tc>wW</tc>
        <reset>Y</reset>
        <tc>üÜ</tc>
        <reset><last_non_ignorable/></reset>
        <!-- following is equivalent to <p>亜</p><p>唖</p><p>娃</p>... -->
        <pc>亜唖娃阿哀愛挨姶逢葵茜穐悪握渥旭葦芦</pc>
        <pc>鯵梓圧斡扱</pc>
  </rules>
</collation>

Appendix A: Sample Special Elements

The elements in this section are not part of the Locale Data Markup Language 1.0 specification. Instead, they are special elements used for application-specific data to be stored in the Common Locale Repository. They may change or be removed future versions of this document, and are present her more as examples of how to extend the format. (Some of these items may move into a future version of the Locale Data Markup Language specification.)

These DTDs use namespaces and the special element. To include one or more, use the following pattern to import the special DTDs that are used in the file:

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE ldml SYSTEM "http://www.unicode.org/cldr/dtd/1.1/ldml.dtd" [
    <!ENTITY % icu SYSTEM "http://www.unicode.org/cldr/dtd/1.1/ldmlICU.dtd">
    <!ENTITY % openOffice SYSTEM "http://www.unicode.org/cldr/dtd/1.1/ldmlOpenOffice.dtd">
%icu;
%openOffice;
]>

Thus to include just the ICU DTD, one uses:

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE ldml SYSTEM "http://www.unicode.org/cldr/dtd/1.1/ldml.dtd" [
    <!ENTITY % icu SYSTEM "http://www.unicode.org/cldr/dtd/1.1/ldmlICU.dtd">
%icu;
]>

Note: A previous version of this document contained a special element for ISO TR 14652 compatibility data. That element has been withdrawn, pending further investigation. Warning: 14652 is a Type 1 TR: "when the required support cannot be obtained for the publication of an International Standard, despite repeated effort". See the ballot comments on 14652 Comments for details on the 14652 defects. For example, most of these patterns make little provision for substantial changes in format when elements are empty, so are not particularly useful in practice. Compare, for example, the mail-merge capabilities of production software such as Microsoft Word or OpenOffice.

A.1 ICU

There are three main areas where ICU has capabilities that go beyond what is shown above.

A.1.1 <icu:ruleBasedNumberFormat>

The rule-based number format (RBNF) encapsulates a set of rules for mapping binary numbers to and from a readable representation. They are typically used for spelling out numbers, but can also be used for other number systems like roman numerals, or for ordinal numbers (1st, 2nd, 3rd,...). The rules are fairly sophisticated; for details see Rule-Based Number Formatter [RBNF].

Example:

    <special xmlns:icu="http://oss.software.ibm.com/icu/">
        <icu:ruleBasedNumberFormats>
            <icu:ruleBasedNumberFormat type="spellout">
                %%and:
                    and =%default=;
                    100: =%default=;
                %%commas:
                    ' and =%default=;
                    100: , =%default=;
                    1000: ,
            </icu:ruleBasedNumberFormat>
            <icu:ruleBasedNumberFormat type="ordinal">
                %main:
                    =#,##0==%%abbrev=;
                %%abbrev:
                    th; st; nd; rd; th;
                    20: &gt;&gt;;
                    100: &gt;&gt;;
            </icu:ruleBasedNumberFormat>
            <icu:ruleBasedNumberFormat type="duration">
            %with-words:
                0 seconds; 1 second; =0= seconds;
                60/60:
            </icu:ruleBasedNumberFormat>
        </icu:ruleBasedNumberFormats>

A.1.2 <icu:boundaries>

Boundaries provide rules for grapheme-cluster ("user-character"), word, line, and sentence breaks. This format is the Java/ICU syntax, at the top level. For a description of that, see Rule-Based Break Iterator [RBBI]. The enclosing special element is a sub-element of <ldml>.

    <special xmlns:icu="http://oss.software.ibm.com/icu/">
        <icu:boundaries>
            <!-- Boundary rules.
            Selected samples are given with no attempt to make them work.
            This format is the Java/ICU syntax, at the top level.
            For real data, see http://oss.software.ibm.com/developerworks/opensource/cvs/icu4j
            in BreakIteratorRules.java
            displayName attributes removed for now
            -->
            <icu:grapheme type="RuleBased" append="true">
                <!-- in addition to the normal rules, treat CH and RR as graphemes. -->
                [cC][hH];[rR][rR]
            </icu:grapheme>
            <icu:word type="Dictionary" import="thaiDict.dat" >
                <!-- When doing Thai word break, check the normal word break rules first. -->
                digit=[[:Nd:][:No:]];
                $digit [[:Pd:]&#xAD;&#x2027;&apos;.]
            </icu:word>
        </icu:boundaries>
    </special>

A.1.3 <icu:transforms>

There may be language-specific transformations, typically used in locale data for transliterations. Such transformations require far more than a simple list of matching characters, since the matches are highly context-sensitive. Each such transform is supplied in a <transform> element. The contents of the transform element is a list of rules, as described in the ICU documentation for [ICUTransforms]. The enclosing special element is a sub-element of <ldml>. The type value is either a script (long or short name) or a locale id, or a pair separated by "-".

Note: there is an on-line demonstration of transforms at [ICUTransforms].

Example: The following is an abbreviated example for Greek to Latin and back, in a Greek locale. The target value can be a script ID or a locale ID.

<ldml>
...
    <special xmlns:icu="http://oss.software.ibm.com/icu/">
        <icu:transforms>
            <icu:transform type="Latin">
                # variables
                $gammaLike = [ΓΚΞΧγκξχϰ] ;
                ...
                ::NFD (NFC) ; # convert everything to decomposed for simplicity
                ...
                α ↔ a ;   Α ↔ A ;
                β ↔ v ;   Β ↔ V ;
                γ } $gammaLike ↔ n } $egammaLike ; # contextual transform
                Γ } $gammaLike ↔ N } $egammaLike ; # contextual transform
                γ ↔ g ;   Γ ↔ G ;
                δ ↔ d ;   Δ ↔ D ;
                ε ↔ e ;   Ε ↔ E ;
                ζ ↔ z ;   Ζ ↔ Z ;
                Θ } $beforeLower ↔ Th ; # contextual transform
                θ ↔ th ;  Θ ↔ TH ;
                ι ↔ i ;   Ι ↔ I ;
                κ ↔ k ;   Κ ↔ K ;
                λ ↔ l ;   Λ ↔ L ;
                μ ↔ m ;   Μ ↔ M ;
                ν } $gammaLike → n\' ; # contextual transform
                Ν } $gammaLike ↔ N\' ; # contextual transform
                ν ↔ n ;   Ν ↔ N ;
                ...
                ::NFC (NFD) ; # convert back to composed
            </icu:transform>
        </icu:transforms>
    </special>

A.2 openoffice.org

A number of the elements above can have extra information for openoffice.org, such as the following example:

    <special xmlns:openOffice="http://www.openoffice.org">
        <openOffice:search>
            <openOffice:searchOptions>
                <openOffice:transliterationModules>IGNORE_CASE</openOffice:transliterationModules>
            </openOffice:searchOptions>
        </openOffice:search>
    </special>

Appendix B: Transmitting Locale Information

In a world of on-demand software components, with arbitrary connections between those components, it is important to get a sense of where localization should be done, and how to transmit enough information so that it can be done at that appropriate place. End-users need to get messages localized to their languages, messages that not only contain a translation of text, but also contain variables such as date, time, number formats, and currencies formatted according to the users' conventions. The strategy for doing the so-called JIT localization is made up of two parts:

  1. Store and transmit neutral-format data wherever possible.
    • Neutral-format data is data that is kept in a standard format, no matter what the local user's environment is. Neutral-format is also (loosely) called binary data, even though it actually could be represented in many different ways, including a textual representation such as in XML.
    • Such data should use accepted standards where possible, such as for currency codes.
    • Textual data should also be in a uniform character set (Unicode/10646) to avoid possible data corruption problems when converting between encodings.
  2. Localize that data as "close" to the end-user as possible.

There are a number of advantages to this strategy. The longer the data is kept in a neutral format, the more flexible the entire system is. On a practical level, if transmitted data is neutral-format, then it is much easier to manipulate the data, debug the processing of the data, and maintain the software connections between components.

Once data has been localized into a given language, it can be quite difficult to programmatically convert that data into another format, if required. This is especially true if the data contains a mixture of translated text and formatted variables. Once information has been localized into, say, Romanian, it is much more difficult to localize that data into, say, French. Parsing is more difficult than formatting, and may run up against different ambiguities in interpreting text that has been localized, even if the original translated message text is available (which it may not be).

Moreover, the closer we are to end-user, the more we know about that user's preferred formats. If we format dates, for example, at the user's machine, then it can easily take into account any customizations that the user has specified. If the formatting is done elsewhere, either we have to transmit whatever user customizations are in play, or we only transmit the user's locale code, which may only approximate the desired format. Thus the closer the localization is to the end user, the less we need to ship all of the user's preferences arond to all the places that localization could possibly need to be done.

Even though localization should be done as close to the end-user as possible, there will be cases where different components need to be aware of whatever settings are appropriate for doing the localization. Thus information such as a locale code or timezone needs to be communicated between different components.

Message Formatting and Exceptions

Windows (FormatMessage, String.Format), Java (MessageFormat) and ICU (MessageFormat, umsg) all provide methods of formatting variables (dates, times, etc) and inserting them at arbitrary positions in a string. This avoids the manual string concatenation that causes severe problems for localization. The question is, where to do this? It is especially important since the original code site that originates a particular message may be far down in the bowels of a component, and passed up to the top of the component with an exception. So we will take that case as representative of this class of issues.

There are circumstances where the message can be communicated with a language-neutral code, such as a numeric error code or mnemonic string key, that is understood outside of the component. If there are arguments that need to accompany that message, such as a number of files or a datetime, those need to accompany the numeric code so that when the localization is finally at some point, the full information can be presented to the end-user. This is the best case for localization.

More often, the exact messages that could originate from within the component are not known outside of the component itself; or at least they may not be known by the component that is finally displaying text to the user. In such a case, the information as to the user's locale needs to be communicated in some way to the component that is doing the localization. That locale information does not necessarily need to be communicated deep within the component; ideally, any exceptions should bundle up some language-neutral message ID, plus the arguments needed to format the message (e.g. datetime), but not do the localization at the throw site. This approach has the advantages noted above for JIT localization.

In addition, exceptions are often caught at a higher level; they don't end up being displayed to any end-user at all. By avoiding the localization at the throw site, it the cost of doing formatting, when that formatting is not really necessary. In fact, in many running programs most of the exceptions that are thrown at a low level never end up being presented to an end-user, so this can have considerable performance benefits.

Appendix C: Supplemental Data

The following represents the format for supplemental information. This is information that is important for proper formatting, but is not contained in the locale hierarchy. It is not localizable, nor is it overridden by locale data. It uses the following format, where the data here is solely for illustration:

<supplementalData>
  <currencyData>
    <fractions>
      <info iso4217="CHF" rounding="5"/>
      <info iso4217="ITL" digits="0"/>
      <info iso4217="FOO" digits="0" rounding="5"/>
    </fractions>
    <region iso3166="IT"> <!-- Italy -->
      <currency iso4217="EUR"/>
      <currency iso4217="EUR" before="2002-01-01">
        <alternate iso4217="ITL"/>
      </currency>
      <currency iso4217="ITL" before="2000-01-01"/>
    </region>
    <region iso3166="ET"> <!-- Ethiopia -->
       ...
      <currency iso4217="ITL" before="1945-03-01"/> 
    </region>
    <region iso3166="DE"> <!-- Germany -->
      <currency iso4217="EUR"/>
       ...
    </region>
    <region iso3166="US"> <!-- USA -->
      <currency iso4217="USD"/>
    </region>
    <region iso3166="EC"> <!-- Ecuador -->
      <currency iso4217="USD"/>
      <currency iso4217="ECS" before="2000-01-01"/>
       ...
    </region>
    <region iso3166="CH"> <!-- Switzerland -->
      <currency iso4217="CHF"/>
    </region>
  </currencyData>
</supplementalData>

The only data currently represented is currency data. Each currencyData element contains one fractions element followed by one or more region elements. The fractions element contains any number of info elements, with the following attributes:

Each region element contains one attribute:

And can have any number of currency elements, with the following attributes. (Each currency element can also contain zero or more alternate elements. These are a list of alternate currencies, in preference order.)

Each before value governs the time up to the previous before value. That is, suppose that we have the following data for the region code R:

  <region iso3166="R">
    <currency iso4217="C01" before="1942"/>
    <currency iso4217="C02"/>
    <currency iso4217="C03" before="1927"/>
    <currency iso4217="none" before="1937-02-13"/>
  </region>

Logically, the currency elements are treated in sorted order, according to the before value. The default value for the before element is logically +∞. This results in the following mapping for region R, using a set of half-open intervals:

Currency Condition (based on time t)
C02 1942-01-01 00:00:00 GMT ≤ t ≤ +∞
C01 1937-02-13 00:00:00 GMT t < 1942-01-01 00:00:00 GMT
C03 1927-01-01 00:00:00 GMT t < 1937-02-13 00:00:00 GMT
XXX -∞ t < 1927-01-01 00:00:00 GMT

Appendix D: Language and Locale IDs

People have very slippery notions of what distinguishes a language code vs. a locale code. The problem is that both are somewhat nebulous concepts.

In practice, many people use [RFC3066] codes to mean locale codes instead of strictly language codes. It is easy to see why this came about; because [RFC3066] includes an explicit region (territory) code, for most people it was sufficient for use as a locale code as well. For example, when typical web software receives an [RFC3066] code, it will use it as a locale code. Other typical software will do the same: in practice, language codes and locale codes are treated interchangeably. Some people recommend distinguishing on the basis of "-" vs "_" (e.g. zh-TW for language code, zh_TW for locale code), but in practice that does not work because of the free variation out in the world in the use of these separators. Notice that Windows, for example, uses "-" as a separator in its locale codes. So pragmatically one is forced to treat "-" and "_" as equivalent when interpreting either one on imput.

Another reason for the conflation of these codes is that very little data in most systems is distinguished by region alone; currency codes and measurement systems being some of the few. Sometimes date or number formats are mentioned as regional, but that really doesn't make much sense. If people see the sentence "You will have to adjust the value to १,२३४.५६७ from ૭૧,૨૩૪.૫૬" (using Indic digits), they would say that sentence is simply not English. Number format is far more closely associated with language than it is with region. The same is true for date formats: people would never expect to see intermixed a date in the format "2003年4月1日" (using Kanji) in text purporting to be purely English. There are regional differences in date and number format — differences which can be important — but those are different in kind than other language differences between regions.

As far as we are concerned — as a completely practical matter — two languages are different if they require substantially different localized resources. Distinctions according to spoken form are important in some contexts, but the written form is by far and away the most important issue for data interchange. Unfortunately, this is not the principle used in [ISO639], which has the fairly unproductive notion (for data interchange) that only spoken language matters (it is also not completely consistent about this, however).

[RFC3066] can express a difference if the use of written languages happens to correspond to region boundaries expressed as [ISO3166] region codes, and has recently added codes that allow it to express some important cases that are not distinguished by [ISO3166] codes. These include simplified and traditional Chinese (both used in Hong Kong S.A.R.); Latin Serbian, Azeri, and Uzbek in both Cyrillic and; Azeri in Arab.

Notice also that currency codes are different than currency localizations. The currency localizations should normally be in the language-based resource bundles, not in the territory-based resource bundles. Thus, the resource bundle en contains the localized mappings in English for a range of different currency codes: USD => $, RUR => Rub, etc. (In protocols, the currency codes should always accompany any currency amounts; otherwise the data is ambiguous, and software is forced to use the user's territory to guess at the currency. For some informal discussion of this, see JIT Localization.)

Written Language

Criteria for what makes a written language should be purely pragmatic; what would copy-editors say? If one gave them text like the following, they would respond that is far from acceptable English for publication, and ask for it to be redone:

  1. "Theatre Center News: The date of the last version of this document was 2003年3月20日. A copy can be obtained for $50,0 or 1.234,57 грн. We would like to acknowledge contributions by the following authors (in alphabetical order): Alaa Ghoneim, Behdad Esfahbod, Ahmed Talaat, Eric Mader, Asmus Freytag, Avery Bishop, and Doug Felt."

So one would change it to either B or C below, depending on which orthographic variant of English was the target for the publication:

  1. "Theater Center News: The date of the last version of this document was 3/20/2003. A copy can be obtained for $50.00 or 1,234.57 Ukrainian Hryvni. We would like to acknowledge contributions by the following authors (in alphabetical order): Alaa Ghoneim, Ahmed Talaat, Asmus Freytag, Avery Bishop, Behdad Esfahbod, Doug Felt, Eric Mader."
  2. "Theatre Centre News: The date of the last version of this document was 20/3/2003. A copy can be obtained for $50.00 or 1,234.57 Ukrainian Hryvni. We would like to acknowledge contributions by the following authors (in alphabetical order): Alaa Ghoneim, Ahmed Talaat, Asmus Freytag, Avery Bishop, Behdad Esfahbod, Doug Felt, Eric Mader."

Clearly there are many acceptable variations on this text. For example, copy editors might still quibble with the use of first vs. last name sorting in the list, but clearly the first list was not acceptable English alphabetical order. And in quoting a name, like "Theatre Centre News", one may leave it in the source orthography even if it differs from the publication target orthography. And so on. However, just as clearly, there limits on what is acceptable English, and "2003年3月20日", for example, is not.

Appendix E: Unicode Sets

A UnicodeSet is a set of Unicode characters (and possibly strings) determined by a pattern, following UTS #18: Unicode Regular Expressions [URegex]. For an example of a concrete implementation of this, see [ICUUnicodeSet].

Patterns are a series of characters bounded by square brackets that contain lists of characters and Unicode property sets. Lists are a sequence of characters that may have ranges indicated by a '-' between two characters, as in "a-z". The sequence specifies the range of all characters from the left to the right, in Unicode order. For example, [a c d-f m] is equivalent to [a c d e f m]. Whitespace can be freely used for clarity, as [a c d-f m] means the same as [acd-fm].

Unicode property sets are specified by any Unicode property, such as [:Letter:], using the PropertyAlias file and the PropertyValueAlias file. The syntax for specifying the property names is an extension of either POSIX or Perl syntax with the addition of "=value". For example, you can match letters by using the POSIX syntax [:Letter:], or by using the Perl-style syntax \p{Letter}. The type can be omitted for the Category and Script properties, but is required for other properties.

The table below shows the two kinds of syntax: POSIX and Perl style. Also, the table shows the "Negative", which is a property that excludes all characters of a given kind. For example, [:^Letter:] matches all characters that are not [:Letter:].

  Positive  Negative 
POSIX-style Syntax  [:type=value:]  [:^type=value:] 
Perl-style Syntax  \p{type=value}  \P{type=value} 

These following low-level lists or properties then can be freely combined with the normal set operations (union, inverse, difference, and intersection):

The binary operators '&' and '-' have equal precedence and bind left-to-right. Thus [[:letter:]-[a-z]-[\u0100-\u01FF]] is equivalent to [[[:letter:]-[a-z]]-[\u0100-\u01FF]]. Another example is the set [[ace][bdf] - [abc][def]], which is not the empty set, but instead the set [def].

Another caveat with the '&' and '-' operators is that they operate between sets. That is, they must be immediately preceded and immediately followed by a set. For example, the pattern [[:Lu:]-A] is illegal, since it is interpreted as the set [:Lu:] followed by the incomplete range -A. To specify the set of uppercase letters except for 'A', enclose the 'A' in a set: [[:Lu:]-[A]]. A multicharacter string can be in a Unicode set, to represent a tailored grapheme cluster for a particular language. The syntax uses curly braces for that case.

[a]  The set containing 'a' 
[a-z]  The set containing 'a' through 'z' and all letters in between, in Unicode order 
[^a-z]  The set containing all characters but 'a' through 'z', that is, U+0000 through 'a'-1 and 'z'+1 through U+FFFF 
[[pat1][pat2]]  The union of sets specified by pat1 and pat2 
[[pat1]&[pat2]]  The intersection of sets specified by pat1 and pat2 
[[pat1]-[pat2]]  The asymmetric difference of sets specified by pat1 and pat2 
[a{ab}{ac}] The character 'a' and the multicharacter strings "ab" and "ac"
[:Lu:]  The set of characters belonging to the given Unicode category, as defined by Character.getType(); in this case, Unicode uppercase letters. The long form for this is [:UppercaseLetter:]
[:L:]  The set of characters belonging to all Unicode categories starting with 'L', that is, [[:Lu:][:Ll:][:Lt:][:Lm:][:Lo:]]. The long form for this is [:Letter:]

In Unicode Sets, there are two ways to quote syntax characters and whitespace:

Single Quote

Two single quotes represents a single quote, either inside or outside single quotes. Text within single quotes is not interpreted in any way (except for two adjacent single quotes). It is taken as literal text (special characters become non-special).

Backslash Escapes

Outside of single quotes, certain backslashed characters have special meaning:

\uhhhh  Exactly 4 hex digits; h in [0-9A-Fa-f] 
\Uhhhhhhhh  Exactly 8 hex digits 
\xhh  1-2 hex digits 
\ooo  1-3 octal digits; o in [0-7]  
\a  U+0007 (BELL) 
\b  U+0008 (BACKSPACE) 
\t  U+0009 (HORIZONTAL TAB) 
\n  U+000A (LINE FEED) 
\v  U+000B (VERTICAL TAB) 
\f  U+000C (FORM FEED) 
\r  U+000D (CARRIAGE RETURN) 
\\  U+005C (BACKSLASH) 
\N{name} The Unicode character named "name".

Anything else following a backslash is mapped to itself, except in an environment where it is defined to have some special meaning. For example, \p{uppercase} is the set of uppercase letters in Unicode.

Any character formed as the result of a backslash escape loses any special meaning and is treated as a literal. In particular, note that \u and \U escapes create literal characters. (In contrast, Java treats Unicode escapes as just a way to represent arbitrary characters in an ASCII source file, and any resulting characters are not tagged as literals.)

Appendix F: Date Format Patterns

A date pattern is a string of characters, where specific strings of characters are replaced with date and time data from a calendar when formatting or used to generate data for a calendar when parsing. The following are the characters used in patterns to show the appropriate formats for a given locale. The following are examples:

Pattern Result (in a particular locale)
yyyy.MM.dd G 'at' HH:mm:ss zzz 1996.07.10 AD at 15:08:56 PDT
EEE, MMM d, ''yy Wed, July 10, '96
h:mm a 12:08 PM
hh 'o''clock' a, zzzz 12 o'clock PM, Pacific Daylight Time
K:mm a, z 0:00 PM, PST
yyyyy.MMMM.dd GGG hh:mm aaa 01996.July.10 AD 12:08 PM

Characters may be used multiple times. For example, if y is used for the year, 'yy' might produce '99', whereas 'yyyy' produces '1999'. For most numerical fields, the number of characters specifies the field width. For example, if h is the hour, 'h' might produce '5', but 'hh' produces '05'. For some characters, the count specifies whether an abbreviated or full form should be used, but may have other choices, as given below.

Note: the counter-intuitive use of 5 letters for the narrow form of weekdays and months is forced by backwards compatibility.

Field Sym. No. Example Description
era G 1 AD Era - Replaced with the Era string for the current date.
year y 1..n 1996 Year
Y 1..n 1997 Year (of "Week of Year"), used in ISO year-week calendar. May differ from calendar year.
u 1..n 4601 Extended year. This is a single number designating the year of this calendar system, encompassing all supra-year fields. For example, for the Julian calendar system, year numbers are positive, with an era of BCE or CE. An extended year value for the Julian calendar system assigns positive values to CE years and negative values to BCE years, with 1 BCE being year 0.
month M 1..2 09
 
Month - Use one or two for the numerical month, three for the abbreviation, or four for the full name, or 5 for the narrow name.
3 Sept
4 September
5 S
week w 1..2 27 Week of Year.
W 1 3 Week of Month
day d 1..2 1 Date - Day of the month
D 1..3 345 Day of year
F 1 2
 
Day of Week in Month. The example is for the 2nd Wed in July
g 1..n 2451334 Modified Julian day. This is different from the conventional Julian day number in two regards. First, it demarcates days at local zone midnight, rather than noon GMT. Second, it is a local number; that is, it depends on the local time zone. It can be thought of as a single number that encompasses all the date-related fields.
weekday E 1..2 3 Day of week - Use three for the short day, or four for the full name, or 5 for the narrow name. Sunday is always day 1
3 Tues
4 Tuesday
5 T
e 1..2 2 Local day of week. Same as E except numeric value will depend on the local starting day of the week. For this example, Monday is the first day of the week.
3 Tues
4 Tuesday
5 T
period a 1 AM AM or PM
hour h 1..2 11 Hour [1-12].
H 1..2 13 Hour [0-23].
K 1..2 0 Hour [0-11].
k 1..2 24 Hour [1-24].
minute m 1..2 59 Minute. Use one or two for zero padding.
second s 1..2 12 Second. Use one or two for zero padding.
S 1..n 3456 Fractional Second - rounds to the count of letters. (example is for 12.34567)
A 1..n 69540000 Milliseconds in day. This field behaves exactly like a composite of all time-related fields, not including the zone fields. As such, it also reflects discontinuities of those fields on DST transition days. On a day of DST onset, it will jump forward. On a day of DST cessation, it will jump backward. This reflects the fact that is must be combined with the offset field to obtain a unique local time value.
zone z 1 PT Timezone. Use 1 for short wall (generic) time, 2 for long wall time, 3 for the short timezone (i.e. PST) or 4 for the full name (Pacific Standard Time). If there's no name for the zone, fallbacks may be used, depending on available data.
2 Pacific Time
3 PDT
4 Pacific Daylight Time
Z 1 GMT-08:00 Use 1 for GMT format, 2 for RFC 822
2 -0800

All non-letter character represent themselves in a pattern, except for the single quote. It is used to 'escape' letters. Two single quotes in a row, whether inside or outside a quoted sequence, represent a 'real' single quote.

localizedPatternChars

These are characters that can be used when displaying a date pattern to an end user. This can occur, for example, when a spreadsheet allows users to specify date patterns. Whatever is in the string is substituted one-for-one with the characters "GyMdkHmsSEDFwWahKzYe", with the above meanings. Thus, for example, if "J" is to be used instead of "Y" to mean Year, then the string would be: "GyMdkHmsSEDFwWahKzJe".

[TBD: fix list. Consider changing to be more structured.]

AM / PM

Even for countries where the customary date format only has a 24 hour format, both the am and pm localized strings must be present and must be distinct from one another. Note that as long as the 24 hour format is used, these strings will normally never be used, but for testing and unusual circumstances they must be present.

Eras

There are only two values for an era in a Gregorian calendar, "BC" and "AD". These values can be translated into other languages, like "a.C." and and "d.C." for Spanish, but there are no other eras in the Gregorian calendar. Other calendars have a different numbers of eras. Care should be taken when translating the era names for a specific calendar.

Week of Year

Values calculated for the Week of Year field range from 1 to 53. Week 1 for a year is the first week that contains at least the specified minimum number of days from that year. Weeks between week 1 of one year and week 1 of the following year are numbered sequentially from 2 to 52 or 53 (if needed). For example, January 1, 1998 was a Thursday. If the first day of the week is MONDAY and the minimum days in a week is 4 (these are the values reflecting ISO 8601 and many national standards), then week 1 of 1998 starts on December 29, 1997, and ends on January 4, 1998. However, if the first day of the week is SUNDAY, then week 1 of 1998 starts on January 4, 1998, and ends on January 10, 1998. The first three days of 1998 are then part of week 53 of 1997.

Values are similarly calculated for the Week of Month.

Week Elements

firstDay
A number indicating which day of the week is considered the 'first' day, for calendar purposes. Because the ordering of days may vary between calendar, keywords are used for this value, such as sun, mon,... These values will be replaced by the localized name when they are actually used.
minDays (Minimal Days in First Week)
Minimal days required in the first week of a month or year. For example, if the first week is defined as one that contains at least one day, this value will be 1. If it must contain a full seven days before it counts as the first week, then the value would be 7.
weekendStart, weekendEnd
Indicates the day and time that the weekend starts or ends. As with firstDay, keywords are used instead of numbers.

Appendix G: Number Format Patterns

Number Patterns

The NumberElements resource affects how these patterns are interpreted in a localized context. Here are some examples, based on the French locale. The "." shows where the decimal point should go. The "," shows where the thousands separator should go. A "0" indicates zero-padding: if the number is too short, a zero (in the locale's numeric set) will go there. A "#" indicates no padding: if the number is too short, nothing goes there. A "¤" shows where the currency sign will go. The following illustrates the effects of different patterns for the French locale, with the number "1234.567". Notice how the pattern characters ',' and '.' are replaced by the characters appropriate for the locale.

Pattern Currency Text
#,##0.## n/a 1 234,57
#,##0.### n/a 1 234,567
###0.##### n/a 1234,567
###0.0000# n/a 1234,5670
00000.0000 n/a 01234,5670
# ##0.00 ¤ EUR 1 234,57 €
JAY 1 235 ¥

The number of # placeholder characters before the decimal do not matter, since no limit is placed on the maximum number of digits. There should, however, be at least one zero someplace in the pattern. In currency formats, the number of digits after the decimal also do not matter, since the information in the Appendix C: Supplemental Data is used to override the number of decimal places — and the rounding — according to the currency that is being formatted. That can be seen in the above chart, with the difference between Yen and Euro formatting.

Thus for consistency in the CLDR data, the following conventions should be observed:

Special Pattern Characters

Many characters in a pattern are taken literally; they are matched during parsing and output unchanged during formatting. Special characters, on the other hand, stand for other characters, strings, or classes of characters. For example, the '#' character is replaced by a localized digit. Often the replacement character is the same as the pattern character; in the U.S. locale, the ',' grouping character is replaced by ','. However, the replacement is still happening, and if the symbols are modified, the grouping character changes. Some special characters affect the behavior of the formatter by their presence; for example, if the percent character is seen, then the value is multiplied by 100 before being displayed.

To insert a special character in a pattern as a literal, that is, without any special meaning, the character must be quoted. There are some exceptions to this which are noted below.

Symbol Location Localized? Meaning
0 Number Yes Digit
1-9 Number Yes '1' through '9' indicate rounding.
@ Number No Significant digit
# Number Yes Digit, zero shows as absent
. Number Yes Decimal separator or monetary decimal separator
- Number Yes Minus sign
, Number Yes Grouping separator
E Number Yes Separates mantissa and exponent in scientific notation. Need not be quoted in prefix or suffix.
+ Exponent Yes Prefix positive exponents with localized plus sign. Need not be quoted in prefix or suffix.
; Subpattern boundary Yes Separates positive and negative subpatterns
% Prefix or suffix Yes Multiply by 100 and show as percentage

(\u2030)
Prefix or suffix Yes Multiply by 1000 and show as per mille
¤ (\u00A4) Prefix or suffix No Currency sign, replaced by currency symbol. If doubled, replaced by international currency symbol. If present in a pattern, the monetary decimal separator and grouping separators are used instead of the numeric ones.
' Prefix or suffix No Used to quote special characters in a prefix or suffix, for example, "'#'#" formats 123 to "#123". To create a single quote itself, use two in a row: "# o''clock".
* Prefix or suffix boundary Yes Pad escape, precedes pad character

A pattern contains a postive and negative subpattern, for example, "#,##0.00;(#,##0.00)". Each subpattern has a prefix, a numeric part, and a suffix. If there is no explicit negative subpattern, the negative subpattern is the localized minus sign prefixed to the positive subpattern. That is, "0.00" alone is equivalent to "0.00;-0.00". If there is an explicit negative subpattern, it serves only to specify the negative prefix and suffix; the number of digits, minimal digits, and other characteristics are ignored in the negative subpattern. That means that "#,##0.0#;(#)" has precisely the same result as "#,##0.0#;(#,##0.0#)".

The prefixes, suffixes, and various symbols used for infinity, digits, thousands separators, decimal separators, etc. may be set to arbitrary values, and they will appear properly during formatting. However, care must be taken that the symbols and strings do not conflict, or parsing will be unreliable. For example, either the positive and negative prefixes or the suffixes must be distinct for any parser using this data to be able to distinguish positive from negative values. Another example is that the decimal separator and thousands separator should be distinct characters, or parsing will be impossible.

The grouping separator is a character that separates clusters of integer digits to make large numbers more legible. It commonly used for thousands, but in some locales it separates ten-thousands. The grouping size is the number of digits between the grouping separators, such as 3 for "100,000,000" or 4 for "1 0000 0000". There are actually two different grouping sizes: One used for the least significant integer digits, the primary grouping size, and one used for all others, the secondary grouping size. In most locales these are the same, but sometimes they are different. For example, if the primary grouping interval is 3, and the secondary is 2, then this corresponds to the pattern "#,##,##0", and the number 123456789 is formatted as "12,34,56,789". If a pattern contains multiple grouping separators, the interval between the last one and the end of the integer defines the primary grouping size, and the interval between the last two defines the secondary grouping size. All others are ignored, so "#,##,###,####" == "###,###,####" == "##,#,###,####".

When parsing using a number format, a more lenient parse should be used where possible. In particular, it should implement at least the following rules.

Formatting

Formatting is guided by several parameters, all of which can be specified either using a pattern or using the API. The following description applies to formats that do not use scientific notation or significant digits.

Special Values

NaN is represented as a single character, typically (\uFFFD). This character is determined by the localized number symbols. This is the only value for which the prefixes and suffixes are not used.

Infinity is represented as a single character, typically (\u221E), with the positive or negative prefixes and suffixes applied. The infinity character is determined by the localized number symbols.

Scientific Notation

Numbers in scientific notation are expressed as the product of a mantissa and a power of ten, for example, 1234 can be expressed as 1.234 x 103. The mantissa is typically in the half-open interval [1.0, 10.0) or sometimes [0.0, 1.0), but it need not be. In a pattern, the exponent character immediately followed by one or more digit characters indicates scientific notation. Example: "0.###E0" formats the number 1234 as "1.234E3".

Significant Digits

There are two ways of controlling how many digits are shows: (a) significant digits counts, or (b) integer and fraction digit counts. Integer and fraction digit counts are described above. When a formatter is using significant digits counts, the number of integer and fraction digits is not specified directly, and the formatter settings for these counts are ignored. Instead, the formatter uses however many integer and fraction digits are required to display the specified number of significant digits. Examples:

Pattern Minimum significant digits Maximum significant digits Number Output
@@@ 3 3 12345 12300
@@@ 3 3 0.12345 0.123
@@## 2 4 3.14159 3.142
@@## 2 4 1.23004 1.23

Padding

Patterns support padding the result to a specific width. In a pattern the pad escape character, followed by a single pad character, causes padding to be parsed and formatted. The pad escape character is '*'. For example, "$*x#,##0.00" formats 123 to "$xx123.00", and 1234 to "$1,234.00".

Rounding

Patterns support rounding to a specific increment. For example, 1230 rounded to the nearest 50 is 1250. Mathematically, rounding to specific increments is performed by multiplying by the increment, rounding to an integer, then dividing by the increment. To take a more bizarre example, 1.234 rounded to the nearest 0.65 is 1.3, as follows:

Original: 1.234
Divide by increment (0.65): 1.89846...
Round: 2
Multiply by increment (0.65): 1.3

To specify a rounding increment in a pattern, include the increment in the pattern itself. "#,#50" specifies a rounding increment of 50. "#,##0.05" specifies a rounding increment of 0.05.

 
decimalFormats
The normal locale specific way to write a base 10 number.
currencyFormats
Use \u00A4 where the local currency symbol should be. Doubling the currency symbol (\u00A4\u00A4) will output the international currency symbol (a 3-letter code).
percentFormats
Pattern for use with percentage formatting
scientificFormats
Pattern for use with scientific (exponent) formatting.

Quoting rules

Single quotes, ('), enclose bits of the pattern that should be treated literally. Inside a quoted string, two single quotes ('') are replaced with a single one ('). For example: 'X '#' Q ' -> X 1939 Q (Literal strings underlined.)

Number Elements

Localized symbols used in number formatting and parsing.

decimal
- separates the integer and fractional part of the number.
group
- groups (for example) units of thousands: 106 = 1,000,000. The grouping separator is commonly used for thousands, but in some countries for ten-thousands. The interval is a constant number of digits between the grouping characters, such as 100,000,000 or 1,0000,0000. If you supply a pattern with multiple grouping characters, the interval between the last one and the end of the integer is the one that is used. So "#,##,###,####" == "######,####" == "##,####,####".
list
- separates lists of numbers
percentSign
- symbol used to indicate a percentage (1/100th) amount. (If present, the value is also multiplied by 100 before formatting. That way 1.23 => 123%)
nativeZeroDigit
- Symbol used to indicate a digit in the pattern, or zero if that place would otherwise be empty. For example, with the digit of '0', the pattern "000" would format "34" as "034", but the pattern "0" would format "34" as just "34". As well, the digits 1-9 are expected to follow the code point of this specified 0 value.
patternDigit
- Symbol used to indicate any digit value, typically #. When that digit is zero, then it is not shown.
minusSign
- Symbol used to denote negative value.
plusSign
- Symbol used to denote negative value.
exponential
- Symbol separating the mantissa and exponent values.
perMille
- symbol used to indicate a per-mille (1/1000th) amount. (If present, the value is also multiplied by 1000 before formatting. That way 1.23 => 1230 [1/000])
infinity
- The infinity sign. Corresponds to the IEEE infinity bit pattern.
nan - Not a number
- The NaN sign. Corresponds to the IEEE NaN bit pattern.
currencySeparator
This is used as the decimal separator in currency formatting/parsing, instead of the DecimalSeparator from the NumberElements list. This item is optional in the CLDR.
currencyGroup
This is used as the grouping separator in currency formatting/parsing, instead of the DecimalSeparator from the NumberElements list. This item is optional in the CLDR.

Appendix H: Choice Patterns

A choice pattern is a string that chooses among a number of strings, based on numeric value. It has the following form:

<choice_pattern> = <choice> ( '|' <choice> )*
<choice> = <number><relation><string>
<number> = ('+' | '-')? (
'∞' | [0-9]+ ('.' [0-9]+)?)
<relation> = '<' | '
≤'

The interpretation of a choice pattern is that given a number N, the pattern is scanned from right to left, for each choice evaluating <number> <relation> N. The first choice that matches results in the corresponding string. If no match is found, then the first string is used. For example:

Pattern N Result
0≤Rf|1≤Ru|1<Re -∞, -3, -1, -0.000001 Rf (defaulted to first string)
0, 0.01, 0.9999 Rf
1 Ru
1.00001, 5, 99, Re

Quoting is done using ' characters, as in date or number formats.

Appendix I: Inheritance and Validity

The following describes in more detail how to determine the exact inheritance of elements, and the validity of a given element in LDML.

When any of the following definitions are applied, it is assumed that all aliases are resolved: that is, everything behaves as if the all children of the alias's parent element element were replaced by all the children of the element it points to. If the path attribute of an alias element is not present, then it defaults to the XPath of the enclosing element. All of the attributes in the XPath must be distinguishing elements (see below).

Definitions

Attributes that serve to distinguish multiple elements at the same level are called distinguishing attributes. These currently consist of key, registry, alt, and type (except for the type attribute on the elements default and mapping).

Blocking elements are those whose subelements do not inherit from parent locales. For example, a <collation> element is a blocking element: everything in a <collation> element is treated as a single lump of data, as far as inheritance is concerned.

Certain elements are called attribute-information elements. They do not have element content; their information is carried in their attribute values. This is unlike the other elements, whose attributes are used to distinguish different types of data.

A list of blocking and attribute-information elements is found in Appendix K: Valid Attribute Values.

For any element in an XML file, an element chain is a resolved XPath leading from the root to an element, with attributes on each element in alphabetical order. So in, say, http://www.unicode.org/cldr/data/common/main/el.xml we have:

<ldml version="1.1">
  <identity>
    <version number="1.1" />
    <generation date="2004-06-04" />
    <language type="el" />
  </identity>
  <localeDisplayNames>
    <languages>
      <language type="ar">Αραβικά</language>
...

Which gives the following element chains (among others):

An element chain A is an extension of an element chain B if B is equivalent to an initial portion of A. For example, #2 below is an extension of #1. (Equivalent, depending on the tree, may not be "identical to". See below for an example.)

  1. //ldml[@version="1.1"]/localeDisplayNames
  2. //ldml[@version="1.1"]/localeDisplayNames/languages/language[@type="ar"]

An LDML file can be thought of as an ordered list of element pairs: <element chain, data>, where the element chains are all the chains for the end-nodes. (This works because of restrictions on the structure of LDML, including that it doesn't allow mixed content.) The ordering is the ordering that the element chains are found in the file, and thus determined by the DTD.

For example, some of those pairs would be the following. Notice that the first has the null string as element contents.

Note: There are two exceptions to this:

  1. Blocking nodes and their contents are treated as a single end note.
  2. For attribute-information elements, in terms of computing inheritance, the element pair consists of the element chain minus the attributes in the final element and the value is the list of attributes for that final element.

Thus instead of the element pair being (a) below, it is (b):

  1. <//ldml[@version="1.1"]/dates/calendars/calendar[@type='gregorian']/week/weekendStart[@day='sun'][@time='00:00'],
    "">
  2. <//ldml[@version="1.1"]/dates/calendars/calendar[@type='gregorian']/week/weekendStart,
    [@day='sun'][@time='00:00']>

Two LDML element chains are equivalent when they would be identical if all attributes and their values were removedexcept for distinguishing attributes. Thus the following are equivalent:

For any locale ID, an locale chain is an ordered list starting with the root and leading down to the ID. For example:

<root, de, de-DE, de-DE-xxx>

Resolved Data File

To produce fully resolved locale data file from CLDR for a locale ID L, you start with root, and replace/add items from the child locales until you get down to L. More formally, this can be expressed as the following procedure.

  1. Let Result be an empty LDML file.
  2. For each Li in the locale chain for L
    1. For each element pair P in the LDML file for Li:
      1. If Result has an element pair Q with an equivalent element chain, remove Q.
      2. Add P to Result.

Note: when adding an element pair to a result, it has to go in the right order for it to be valid according to the DTD.

Valid Data

The attribute draft='true' in LDML means that the data is not known to be valid or not. However, some data that is not explicitly marked as draft may be implicitly draft, either because it inherits it from a parent, or from an enclosing element.

Example 2. Suppose that a new locale is added for af (Afrikans). To indicate that all of the data is draft, that attribute can be added to the top level.

<ldml version="1.1" draft="true">
 <identity>
  <version number="1.1" />
  <generation date="2004-06-04" />
  <language type="af" />
 </identity>
</ldml>

Any data can be added to that file, and the status will all be draft. Once an item is vetted -- whether it is inherited or explicitly in the file -- then its status can be changed to non-draft. This can be done either by leaving draft="true" on the enclosing element and marking the child with draft="false", such as:

<ldml version="1.1" draft="true">
 <identity>
  <version number="1.1" />
  <generation date="2004-06-04" />
  <language type="af" />
 </identity>
 <characters draft="false"/>
 <localeDisplayNames/>
 <dates/>
 <numbers/>
 <collations/>
</ldml>

Or it can be done by removing the draft="false" from the enclosing element, and marking the other children as draft.

<ldml version="1.1">
 <identity>
  <version number="1.1" />
  <generation date="2004-06-04" />
  <language type="af" />
 </identity>
 <characters/>
 <localeDisplayNames/>
 <dates draft="true"/>
 <numbers draft="true"/>
 <collations draft="true"/>
</ldml>

Note: A missing draft attribute is not the same as either a true or false value. A missing attribute means instead: inherit the draft status from enclosing elements and parent locales.

The attribute validSubLocales allows sublocales in a given tree to be treated as though a file for them were present when there isn't one. It can be applied to any element. It only has an effect for locales that inherit from the current file where a file is missing, and the elements wouldn't otherwise be draft.

Example 1. Suppose that in a particular LDML tree, there are no region locales for German, e.g. there is a de.xml file, but no files for de_AT.xml, de_CH.xml, or de_DE.xml. Then no elements are valid for any of those region locales. If we want to mark one of those files as having valid elements, then we introduce an empty file, such as the following.

<ldml version="1.1">
 <identity>
  <version number="1.1" />
  <generation date="2004-06-04" />
  <language type="de" />
  <territory type="AT" />
 </identity>
</ldml>

With the validSubLocales attribute, instead of adding the empty files for de_AT.xml, de_CH.xml, and de_DE.xml, in the de file we can add to the parent locale a list of the child locales that should behave as if files were present.

<ldml version="1.1" validSubLocales="de_AT de_CH de_DE">
 <identity>
  <version number="1.1" />
  <generation date="2004-06-04" />
  <language type="de" />
 </identity>
...
</ldml>

More formally, here is how to determine whether data for an element chain E is implicitly or explicitly draft, given a locale L. Sections 1, 2, and 4 are simply formalizations of what is in LDML already. Item 3 adds the new element.

Checking for Draft Status:

  1. Parent Locale Inheritance
    1. Walk through the locale chain until you find a locale ID L' with a data file D. (L' may equal L).
    2. Produce the fully resolved data file D' for D.
    3. In D', find the first element pair whose element chain E' is either equivalent to or an extension of E.
    4. If there is no such E', return true
    5. If E' is not equivalent to E, truncate E' to the length of E.
  2. Enclosing Element Inheritance
    1. Walk through the elements in E', from back to front.
      1. If you ever encounter draft=x, return x
    2. If L' = L, return false
  3. Missing File Inheritance
    1. Otherwise, walk again through the elements in E', from back to front.
      1. If you encounter a validSubLocales attribute:
        1. If L is in the attribute value, return false
        2. Otherwise return true
  4. Otherwise
    1. Return true

The validSubLocales in the most specific (farthest from root file) locale file "wins" through the full resolution step (data from more specific files replacing data from less specific ones).

Keyword and Default Resolution

When accessing data based on keywords, the following process is used. Consider the following example:

The locale 'de' has collation types A, B, C, and no <default> element
The locale 'de_CH' has <default type='B'>

Here are the searches for various combinations.

1. de_CH not found
de not found
root not found: so get the default type in de_CH
de@collation=B found
2. de not found
root not found: so get the default type in de, which itself falls back to root
de@collation=standard not found
root@collation=standard found
3. de@collation=A found
4. de@collation=standard not found
root@collation=standard found


Note: It is an invariant that the default in root for a given element must
always be a value that exists in root. So you can't have the following in root:

<someElements>
  <default type='a'/>
  <someElement type='b'>...</someElement>
  <someElement type='c'>...</someElement>
  <!-- no 'a' -->
</someElements>

It is not necessary, but strongly encouraged, that the default type in root be
'standard'.

For identifiers, such as language codes, script codes, region codes, variant codes, types, keywords, currency symbols or curreny display names, the default value is the identifier itself whenever if no value is found in the root. Thus if there is no display name for the region code 'QA' in root, then the display name is simply 'QA'.

Appendix J: Time Zone Fallback

When a timezone is to be displayed, the following process is used. The starred items are skipped if <abbreviationFallback type='GMT'> is present in the resolved locale data.

  1. Canonicalize the Olson ID, mapping to one of the 407 "real" IDs.
    • America/Atka => America/Adak
    • [TBD: point to the exact data used to do this]
  2. If there is an exact translation in the resolved locale, use it. Note that this translation may not at all be literal, it would be what is most recognizable for people using the target language.
    • America/Los_Angeles => "Tampo de Pacifica"
  3. Else for non-wall-time, use GMT format
    1. America/Los_Angeles => "GMT-08:00"
  4. * Else if there is an exemplar city, use it with the region format. The exemplar city may not be the same as the Olson ID city, if another city is much more recognizable for whatever reason. However, it is very strongly recommended that the same city be used.
    • America/Los_Angeles => "Tampo de San Fransisko"
  5. * Else if there is a country for the time zone, and a translation in the locale for the country name, and the country only has one (modern) timezone, use it with the region format :
    • Africa/Monrovia => LR => "Tampo de Liberja"
  6. Else if it is a perpetual alias for a "real" ID, and if there is an exact translation for that, try #1..#4 with that alias.
    • Europe/San_Marino => Europe/Rome => ... => "Tampo de Roma"
  7. * Else fall back to the raw Olson ID (stripping off the prefix, and turning _ into space), using the fallback format. 
    • America/Goose_Bay => "Tampo de  «Goose Bay»"
  8. Else use the (possibly multi-offset) GMT format
    • America/Nome => "GMT-0900/-0800"

Many time zone IDs only represent differences that are important historically, but do not make any difference in modern times. The preferenceOrdering element can be used to select the preferred modern IDs when desired. (The choice of the interval to use when determining when two time zone IDs are equivalent is left to the implementation.

Whenever two timezone IDs are equivalent in effect and are in the same country, the preference ordering list is examined according to the following process:

  1. If x, y are in the list, then the earlier one in the list is preferred.
  2. Else if x is in the list and y isn't, then x is preferred
  3. Else if not in root, repeat #1 and #2 using the parent locale's list
  4. If all else fails, use a case-insensitive comparison of the timezone IDs.

For example, the following table lists the modern equivalents for Mexico on separate rows. If the preference ordering has one element: "America/Mexico_City", then the bolded items would be chosen as the preferred timezone IDs.

America/Merida, America/Mexico_City, America/Monterrey, America/Cancun
America/Chihuahua, America/Mazatlan
America/Hermosillo
America/Tijuana

 

Appendix K: Valid Attribute Values

The following list provides a list of the currently valid attributes and values, for all elements except collation <rules> and its subelements. For currency codes, this list only includes the ISO 4217 currency codes; however, there are other codes in common use that may occur in LDML data. A definitive list will be provided in the future. In addition, data marked draft="true" may use attribute values that are not in the following list, to allow for proposed additions, such as new variant codes.

In the following list, the attribute-information elements (alias, default, firstDay, mapping, measurementSystem, minDays, orientation, settings, weekendStart, weekendEnd) are marked with a *. These elements carry all of their information in attributes, and are to have empty element contents. There is currently only one blocking element: collation. The distinguishing attributes are not marked in the table, but currently consist of key, registry, alt, and type (except for the type attribute on the elements default and mapping).

Element Attribute Allowed Values
[any] alt "proposed", "variant"
draft "true", "false*"
references "<list of references>"
standard "<list of standards>"
validSubLocales "<list of sub-locales>"
abbreviationFallback type "standard", "GMT"
alias* path "<valid XPath within locale tree>"
source "<valid locale ID>"
calendar type "buddhist", "chinese", "gregorian", "hebrew", "islamic", "islamic-civil", "japanese", "arabic[alias]", "civil-arabic[alias]", "thai-buddhist[alias]"
collation type "phonebook", "traditional", "direct", "pinyin", "stroke", "posix", "big5han", "gb2312han"
currency type "ADP", "AED", "AFA", "ALL", "AMD", "ANG", "AON", "AOR", "ARS", "ATS", "AUD", "AWG", "AZM", "BAM", "BBD", "BDT", "BEF", "BGL", "BGN", "BHD", "BIF", "BMD", "BND", "BRL", "BSD", "BTN", "BWP", "BYR", "BZD", "CAD", "CDF", "CHF", "CLF", "CLP", "CNY", "COP", "CRC", "CUP", "CVE", "CYP", "CZK", "DEM", "DJF", "DKK", "DOP", "DZD", "ECS", "ECV", "EEK", "EGP", "ERN", "ESP", "ETB", "EUR", "FIM", "FJD", "FKP", "FRF", "GBP", "GEL", "GHC", "GIP", "GMD", "GNF", "GRD", "GTQ", "GWP", "GYD", "HI-THERE", "HKD", "HNL", "HRK", "HTG", "HUF", "IDR", "IEP", "ILS", "INR", "IQD", "IRR", "ISK", "ITL", "JMD", "JOD", "JPY", "KES", "KGS", "KHR", "KMF", "KPW", "KRW", "KWD", "KYD", "KZT", "LAK", "LBP", "LKR", "LRD", "LSL", "LTL", "LUF", "LVL", "LYD", "MAD", "MDL", "MGF", "MKD", "MMK", "MNT", "MOP", "MRO", "MTL", "MUR", "MVR", "MWK", "MXN", "MXV", "MYR", "MZM", "NAD", "NGN", "NIO", "NLG", "NOK", "NPR", "NZD", "OMR", "PAB", "PEN", "PGK", "PHP", "PKR", "PLN", "PTE", "PYG", "QAR", "ROL", "RUB", "RUR", "RWF", "SAR", "SBD", "SCR", "SDD", "SEK", "SGD", "SHP", "SIT", "SKK", "SLL", "SOS", "SRG", "STD", "SVC", "SYP", "SZL", "THB", "TJR", "TJS", "TMM", "TND", "TOP", "TPE", "TRL", "TTD", "TWD", "TZS", "UAH", "UGX", "USD", "USN", "USS", "UYU", "UZS", "VEB", "VND", "VUV", "WST", "XAF", "XAG", "XAU", "XBA", "XBB", "XBC", "XBD", "XCD", "XDR", "XFO", "XFU", "XOF", "XPD", "XPF", "XPT", "XTS", "XXX", "YER", "YUM", "ZAL", "ZAR", "ZMK", "ZRN", "ZWD"
currencyFormat type "standard", "<special-key>"
currencyFormatLength type "full", "long", "medium", "short"
dateFormat type "standard", "<special-key>"
dateFormatLength type "full", "long", "medium", "short"
dateTimeFormat type "standard", "<special-key>"
dateTimeFormatLength type "full"
day type "sun", "mon", "tue", "wed", "thu", "fri", "sat"
dayContext type "format", "stand-alone"
dayWidth type "abbreviated", "narrow", "wide"
decimalFormat type "standard", "<special-key>"
decimalFormatLength type "full", "long", "medium", "short"
default* type "<any type value legal for one of the peer elements>"
era type "<non-negative number>"
exemplarCharacters type "standard", "auxiliary"
field type "era", "year", "month", "week", "day", "weekday", "dayperiod", "hour", "minute", "second", "zone"
firstDay* day "sun", "mon", "tue", "wed", "thu", "fri", "sat"
generation date "<yyyy-MM-dd format>"
key type "<any element name having 'type' attribute>"
language type "aa", "ab", "ace", "ach", "ada", "ady", "ae", "af", "afa", "afh", "ak", "akk", "ale", "alg", "alt", "am", "an", "ang", "apa", "ar", "arc", "arn", "arp", "art", "arw", "as", "ast", "ath", "aus", "av", "awa", "ay", "az", "ba", "bad", "bai", "bal", "ban", "bas", "bat", "be", "bej", "bem", "ber", "bg", "bh", "bho", "bi", "bik", "bin", "bla", "bm", "bn", "bnt", "bo", "br", "bra", "bs", "btk", "bua", "bug", "byn", "ca", "cad", "cai", "car", "cau", "ce", "ceb", "cel", "ch", "chb", "chg", "chk", "chm", "chn", "cho", "chp", "chr", "chy", "cmc", "co", "cop", "cpe", "cpf", "cpp", "cr", "crh", "crp", "cs", "csb", "cu", "cus", "cv", "cy", "da", "dak", "dar", "day", "de", "del", "den", "dgr", "din", "doi", "dra", "dsb", "dua", "dum", "dv", "dyu", "dz", "ee", "efi", "egy", "eka", "el", "elx", "en", "enm", "eo", "es", "et", "eu", "ewo", "fa", "fan", "fat", "ff", "fi", "fil", "fiu", "fj", "fo", "fon", "fr", "frm", "fro", "fur", "fy", "ga", "gaa", "gay", "gba", "gd", "gem", "gez", "gil", "gl", "gmh", "gn", "goh", "gon", "gor", "got", "grb", "grc", "gu", "gv", "gwi", "ha", "hai", "haw", "he", "hi", "hil", "him", "hit", "hmn", "ho", "hr", "hsb", "ht", "hu", "hup", "hy", "hz", "ia", "iba", "id", "ie", "ig", "ii", "ijo", "ik", "ilo", "in", "inc", "ine", "inh", "io", "ira", "iro", "is", "it", "iu", "iw", "ja", "jbo", "ji", "jpr", "jrb", "jv", "ka", "kaa", "kab", "kac", "kam", "kar", "kaw", "kbd", "kg", "kha", "khi", "kho", "ki", "kj", "kk", "kl", "km", "kmb", "kn", "ko", "kok", "kos", "kpe", "kr", "krc", "kro", "kru", "ks", "ku", "kum", "kut", "kv", "kw", "ky", "la", "lad", "lah", "lam", "lb", "lez", "lg", "li", "ln", "lo", "lol", "loz", "lt", "lu", "lua", "lui", "lun", "luo", "lus", "lv", "mad", "mag", "mai", "mak", "man", "map", "mas", "mdf", "mdr", "men", "mg", "mga", "mh", "mi", "mic", "min", "mis", "mk", "mkh", "ml", "mn", "mnc", "mni", "mno", "mo", "moh", "mos", "mr", "ms", "mt", "mul", "mun", "mus", "mwl", "mwr", "my", "myn", "myv", "na", "nah", "nai", "nap", "nb", "nd", "nds", "ne", "new", "ng", "nia", "nic", "niu", "nl", "nn", "no", "nog", "non", "nr", "nso", "nub", "nv", "nwc", "ny", "nym", "nyn", "nyo", "nzi", "oc", "oj", "om", "or", "os", "osa", "ota", "oto", "pa", "paa", "pag", "pal", "pam", "pap", "pau", "peo", "phi", "phn", "pi", "pl", "pon", "pra", "pro", "ps", "pt", "qaa..qtz", "qu", "raj", "rap", "rar", "rm", "rn", "ro", "roa", "rom", "root", "ru", "rw", "sa", "sad", "sah", "sai", "sal", "sam", "sas", "sat", "sc", "scn", "sco", "sd", "se", "sel", "sem", "sg", "sga", "sgn", "sh", "shn", "si", "sid", "sio", "sit", "sk", "sl", "sla", "sm", "sma", "smi", "smj", "smn", "sms", "sn", "snk", "so", "sog", "son", "sq", "sr", "srr", "ss", "ssa", "st", "su", "suk", "sus", "sux", "sv", "sw", "syr", "ta", "tai", "te", "tem", "ter", "tet", "tg", "th", "ti", "tig", "tiv", "tk", "tkl", "tl", "tlh", "tli", "tmh", "tn", "to", "tog", "tpi", "tr", "ts", "tsi", "tt", "tum", "tup", "tut", "tvl", "tw", "ty", "tyv", "udm", "ug", "uga", "uk", "umb", "und", "ur", "uz", "vai", "ve", "vi", "vo", "vot", "wa", "wak", "wal", "war", "was", "wen", "wo", "xal", "xh", "yao", "yap", "yi", "yo", "ypk", "za", "zap", "zen", "zh", "znd", "zu", "zun"
ldml version "1.0", "1.1", "1.2"
mapping* registry "<any charset registry, iana preferred>"
type "<any valid charset from the given registry>"
measurementSystem* type "metric", "US", "UK"
minDays* count "1", "2", "3", "4", "5", "6", "7"
month type "1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13"
monthContext type "format", "stand-alone"
monthWidth type "abbreviated", "narrow", "wide"
orientation* characters "left-to-right", "right-to-left", "top-to-bottom", "bottom-to-top"
lines "left-to-right", "right-to-left", "top-to-bottom", "bottom-to-top"
pattern type "<valid pattern for format>"
percentFormat type "standard", "<special-key>"
percentFormatLength type "full", "long", "medium", "short"
preferenceOrdering type "<space-delimited list of timezone IDs>"
relative type "<integer>"
reset before "primary", "secondary", "tertiary"
scientificFormat type "standard", "<special-key>"
scientificFormatLength type "full", "long", "medium", "short"
script type "Arab", "Armn", "Bali", "Batk", "Beng", "Blis", "Bopo", "Brah", "Brai", "Bugi", "Buhd", "Cans", "Cham", "Cher", "Cirt", "Copt", "Cprt", "Cyrl", "Cyrs", "Deva", "Dsrt", "Egyd", "Egyh", "Egyp", "Ethi", "Geor", "Glag", "Goth", "Grek", "Gujr", "Guru", "Hang", "Hani", "Hano", "Hans", "Hant", "Hebr", "Hira", "Hmng", "Hrkt", "Hung", "Inds", "Ital", "Java", "Kali", "Kana", "Khar", "Khmr", "Knda", "Laoo", "Latf", "Latg", "Latn", "Lepc", "Limb", "Lina", "Linb", "Mand", "Maya", "Mero", "Mlym", "Mong", "Mymr", "Ogam", "Orkh", "Orya", "Osma", "Perm", "Phag", "Phnx", "Plrd", "Qaaa..Qabx", "Qaai", "Roro", "Runr", "Sara", "Shaw", "Sinh", "Sylo", "Syrc", "Syre", "Syrj", "Syrn", "Tagb", "Tale", "Talu", "Taml", "Telu", "Teng", "Tfng", "Tglg", "Thaa", "Thai", "Tibt", "Ugar", "Vaii", "Visp", "Xpeo", "Xsux", "Yiii", "Zxxx", "Zyyy", "Zzzz"
settings* alternate "non-ignorable", "shifted"
backwards "on", "off"
caseFirst "upper", "lower", "off"
caseLevel "on", "off"
hiraganaQuarternary "on", "off"
normalization "on", "off"
numeric "on", "off"
strength "primary", "secondary", "tertiary", "quaternary", "identical"
territory type "AA", "AD", "AE", "AF", "AG", "AI", "AL", "AM", "AN", "AO", "AQ", "AR", "AS", "AT", "AU", "AW", "AX", "AZ", "BA", "BB", "BD", "BE", "BF", "BG", "BH", "BI", "BJ", "BM", "BN", "BO", "BQ", "BR", "BS", "BT", "BU", "BV", "BW", "BY", "BZ", "CA", "CC", "CD", "CF", "CG", "CH", "CI", "CK", "CL", "CM", "CN", "CO", "CR", "CS", "CT", "CU", "CV", "CX", "CY", "CZ", "DD", "DE", "DJ", "DK", "DM", "DO", "DY", "DZ", "EC", "EE", "EG", "EH", "ER", "ES", "ET", "FI", "FJ", "FK", "FM", "FO", "FQ", "FR", "FX", "GA", "GB", "GD", "GE", "GF", "GH", "GI", "GL", "GM", "GN", "GP", "GQ", "GR", "GS", "GT", "GU", "GW", "GY", "HK", "HM", "HN", "HR", "HT", "HU", "HV", "ID", "IE", "IL", "IN", "IO", "IQ", "IR", "IS", "IT", "JM", "JO", "JP", "JT", "KE", "KG", "KH", "KI", "KM", "KN", "KP", "KR", "KW", "KY", "KZ", "LA", "LB", "LC", "LI", "LK", "LR", "LS", "LT", "LU", "LV", "LY", "MA", "MC", "MD", "MG", "MH", "MI", "MK", "ML", "MM", "MN", "MO", "MP", "MQ", "MR", "MS", "MT", "MU", "MV", "MW", "MX", "MY", "MZ", "NA", "NC", "NE", "NF", "NG", "NH", "NI", "NL", "NO", "NP", "NQ", "NR", "NT", "NU", "NZ", "OM", "PA", "PC", "PE", "PF", "PG", "PH", "PK", "PL", "PM", "PN", "PR", "PS", "PT", "PU", "PW", "PY", "PZ", "QA", "QM..QZ", "RE", "RH", "RO", "RU", "RW", "SA", "SB", "SC", "SD", "SE", "SG", "SH", "SI", "SJ", "SK", "SL", "SM", "SN", "SO", "SR", "ST", "SU", "SV", "SY", "SZ", "TC", "TD", "TF", "TG", "TH", "TJ", "TK", "TL", "TM", "TN", "TO", "TP", "TR", "TT", "TV", "TW", "TZ", "UA", "UG", "UM", "US", "UY", "UZ", "VA", "VC", "VD", "VE", "VG", "VI", "VN", "VU", "WF", "WK", "WS", "XA..XZ", "YD", "YE", "YT", "YU", "ZA", "ZM", "ZR", "ZW", "ZZ"
timeFormat type "standard", "<special-key>"
timeFormatLength type "full", "long", "medium", "short"
type key "<any element name having 'type' attribute>"
type "<any type value--with appropriate key>"
variant type "1901", "1996", "POSIX", "REVISED", "boont", "gaulish", "guoyu", "hakka", "lojban", "nedis", "rozaj", "scouse", "xiang", "bokmal", "nynorsk", "aaland"
version number "<n.m format>"
weekendEnd* day "sun", "mon", "tue", "wed", "thu", "fri", "sat"
time "<HH:mm (00:00..24:00)>"
weekendStart* day "sun", "mon", "tue", "wed", "thu", "fri", "sat"
time "<HH:mm (00:00..24:00)>"
zone type "Africa/Abidjan", "Africa/Accra", "Africa/Addis_Ababa", "Africa/Algiers", "Africa/Asmera", "Africa/Bamako", "Africa/Bangui", "Africa/Banjul", "Africa/Bissau", "Africa/Blantyre", "Africa/Brazzaville", "Africa/Bujumbura", "Africa/Cairo", "Africa/Casablanca", "Africa/Ceuta", "Africa/Conakry", "Africa/Dakar", "Africa/Dar_es_Salaam", "Africa/Djibouti", "Africa/Douala", "Africa/El_Aaiun", "Africa/Freetown", "Africa/Gaborone", "Africa/Harare", "Africa/Johannesburg", "Africa/Kampala", "Africa/Khartoum", "Africa/Kigali", "Africa/Kinshasa", "Africa/Lagos", "Africa/Libreville", "Africa/Lome", "Africa/Luanda", "Africa/Lubumbashi", "Africa/Lusaka", "Africa/Malabo", "Africa/Maputo", "Africa/Maseru", "Africa/Mbabane", "Africa/Mogadishu", "Africa/Monrovia", "Africa/Nairobi", "Africa/Ndjamena", "Africa/Niamey", "Africa/Nouakchott", "Africa/Ouagadougou", "Africa/Porto-Novo", "Africa/Sao_Tome", "Africa/Timbuktu", "Africa/Tripoli", "Africa/Tunis", "Africa/Windhoek", "America/Adak", "America/Anchorage", "America/Anguilla", "America/Antigua", "America/Araguaina", "America/Aruba", "America/Asuncion", "America/Barbados", "America/Belem", "America/Belize", "America/Boa_Vista", "America/Bogota", "America/Boise", "America/Buenos_Aires", "America/Cambridge_Bay", "America/Cancun", "America/Caracas", "America/Catamarca", "America/Cayenne", "America/Cayman", "America/Chicago", "America/Chihuahua", "America/Cordoba", "America/Costa_Rica", "America/Cuiaba", "America/Curacao", "America/Danmarkshavn", "America/Dawson", "America/Dawson_Creek", "America/Denver", "America/Detroit", "America/Dominica", "America/Edmonton", "America/Eirunepe", "America/El_Salvador", "America/Fortaleza", "America/Glace_Bay", "America/Godthab", "America/Goose_Bay", "America/Grand_Turk", "America/Grenada", "America/Guadeloupe", "America/Guatemala", "America/Guayaquil", "America/Guyana", "America/Halifax", "America/Havana", "America/Hermosillo", "America/Indiana/Knox", "America/Indiana/Marengo", "America/Indiana/Vevay", "America/Indianapolis", "America/Inuvik", "America/Iqaluit", "America/Jamaica", "America/Jujuy", "America/Juneau", "America/Kentucky/Monticello", "America/La_Paz", "America/Lima", "America/Los_Angeles", "America/Louisville", "America/Maceio", "America/Managua", "America/Manaus", "America/Martinique", "America/Mazatlan", "America/Mendoza", "America/Menominee", "America/Merida", "America/Mexico_City", "America/Miquelon", "America/Monterrey", "America/Montevideo", "America/Montreal", "America/Montserrat", "America/Nassau", "America/New_York", "America/Nipigon", "America/Nome", "America/Noronha", "America/North_Dakota/Center", "America/Panama", "America/Pangnirtung", "America/Paramaribo", "America/Phoenix", "America/Port-au-Prince", "America/Port_of_Spain", "America/Porto_Velho", "America/Puerto_Rico", "America/Rainy_River", "America/Rankin_Inlet", "America/Recife", "America/Regina", "America/Rio_Branco", "America/Santiago", "America/Santo_Domingo", "America/Sao_Paulo", "America/Scoresbysund", "America/St_Johns", "America/St_Kitts", "America/St_Lucia", "America/St_Thomas", "America/St_Vincent", "America/Swift_Current", "America/Tegucigalpa", "America/Thule", "America/Thunder_Bay", "America/Tijuana", "America/Tortola", "America/Vancouver", "America/Whitehorse", "America/Winnipeg", "America/Yakutat", "America/Yellowknife", "Antarctica/Casey", "Antarctica/Davis", "Antarctica/DumontDUrville", "Antarctica/Mawson", "Antarctica/McMurdo", "Antarctica/Palmer", "Antarctica/Rothera", "Antarctica/Syowa", "Antarctica/Vostok", "Asia/Aden", "Asia/Almaty", "Asia/Amman", "Asia/Anadyr", "Asia/Aqtau", "Asia/Aqtobe", "Asia/Ashgabat", "Asia/Baghdad", "Asia/Bahrain", "Asia/Baku", "Asia/Bangkok", "Asia/Beirut", "Asia/Bishkek", "Asia/Brunei", "Asia/Calcutta", "Asia/Choibalsan", "Asia/Chongqing", "Asia/Colombo", "Asia/Damascus", "Asia/Dhaka", "Asia/Dili", "Asia/Dubai", "Asia/Dushanbe", "Asia/Gaza", "Asia/Harbin", "Asia/Hong_Kong", "Asia/Hovd", "Asia/Irkutsk", "Asia/Jakarta", "Asia/Jayapura", "Asia/Jerusalem", "Asia/Kabul", "Asia/Kamchatka", "Asia/Karachi", "Asia/Kashgar", "Asia/Katmandu", "Asia/Krasnoyarsk", "Asia/Kuala_Lumpur", "Asia/Kuching", "Asia/Kuwait", "Asia/Macau", "Asia/Magadan", "Asia/Makassar", "Asia/Manila", "Asia/Muscat", "Asia/Nicosia", "Asia/Novosibirsk", "Asia/Omsk", "Asia/Oral", "Asia/Phnom_Penh", "Asia/Pontianak", "Asia/Pyongyang", "Asia/Qatar", "Asia/Qyzylorda", "Asia/Rangoon", "Asia/Riyadh", "Asia/Saigon", "Asia/Sakhalin", "Asia/Samarkand", "Asia/Seoul", "Asia/Shanghai", "Asia/Singapore", "Asia/Taipei", "Asia/Tashkent", "Asia/Tbilisi", "Asia/Tehran", "Asia/Thimphu", "Asia/Tokyo", "Asia/Ulaanbaatar", "Asia/Urumqi", "Asia/Vientiane", "Asia/Vladivostok", "Asia/Yakutsk", "Asia/Yekaterinburg", "Asia/Yerevan", "Atlantic/Azores", "Atlantic/Bermuda", "Atlantic/Canary", "Atlantic/Cape_Verde", "Atlantic/Faeroe", "Atlantic/Jan_Mayen", "Atlantic/Madeira", "Atlantic/Reykjavik", "Atlantic/South_Georgia", "Atlantic/St_Helena", "Atlantic/Stanley", "Australia/Adelaide", "Australia/Brisbane", "Australia/Broken_Hill", "Australia/Darwin", "Australia/Hobart", "Australia/Lindeman", "Australia/Lord_Howe", "Australia/Melbourne", "Australia/Perth", "Australia/Sydney", "Etc/GMT", "Etc/GMT+1", "Etc/GMT+10", "Etc/GMT+11", "Etc/GMT+12", "Etc/GMT+2", "Etc/GMT+3", "Etc/GMT+4", "Etc/GMT+5", "Etc/GMT+6", "Etc/GMT+7", "Etc/GMT+8", "Etc/GMT+9", "Etc/GMT-1", "Etc/GMT-10", "Etc/GMT-11", "Etc/GMT-12", "Etc/GMT-13", "Etc/GMT-14", "Etc/GMT-2", "Etc/GMT-3", "Etc/GMT-4", "Etc/GMT-5", "Etc/GMT-6", "Etc/GMT-7", "Etc/GMT-8", "Etc/GMT-9", "Etc/UCT", "Etc/UTC", "Europe/Amsterdam", "Europe/Andorra", "Europe/Athens", "Europe/Belfast", "Europe/Belgrade", "Europe/Berlin", "Europe/Bratislava", "Europe/Brussels", "Europe/Bucharest", "Europe/Budapest", "Europe/Chisinau", "Europe/Copenhagen", "Europe/Dublin", "Europe/Gibraltar", "Europe/Helsinki", "Europe/Istanbul", "Europe/Kaliningrad", "Europe/Kiev", "Europe/Lisbon", "Europe/Ljubljana", "Europe/London", "Europe/Luxembourg", "Europe/Madrid", "Europe/Malta", "Europe/Minsk", "Europe/Monaco", "Europe/Moscow", "Europe/Oslo", "Europe/Paris", "Europe/Prague", "Europe/Riga", "Europe/Rome", "Europe/Samara", "Europe/San_Marino", "Europe/Sarajevo", "Europe/Simferopol", "Europe/Skopje", "Europe/Sofia", "Europe/Stockholm", "Europe/Tallinn", "Europe/Tirane", "Europe/Uzhgorod", "Europe/Vaduz", "Europe/Vatican", "Europe/Vienna", "Europe/Vilnius", "Europe/Warsaw", "Europe/Zagreb", "Europe/Zaporozhye", "Europe/Zurich", "Indian/Antananarivo", "Indian/Chagos", "Indian/Christmas", "Indian/Cocos", "Indian/Comoro", "Indian/Kerguelen", "Indian/Mahe", "Indian/Maldives", "Indian/Mauritius", "Indian/Mayotte", "Indian/Reunion", "Pacific/Apia", "Pacific/Auckland", "Pacific/Chatham", "Pacific/Easter", "Pacific/Efate", "Pacific/Enderbury", "Pacific/Fakaofo", "Pacific/Fiji", "Pacific/Funafuti", "Pacific/Galapagos", "Pacific/Gambier", "Pacific/Guadalcanal", "Pacific/Guam", "Pacific/Honolulu", "Pacific/Johnston", "Pacific/Kiritimati", "Pacific/Kosrae", "Pacific/Kwajalein", "Pacific/Majuro", "Pacific/Marquesas", "Pacific/Midway", "Pacific/Nauru", "Pacific/Niue", "Pacific/Norfolk", "Pacific/Noumea", "Pacific/Pago_Pago", "Pacific/Palau", "Pacific/Pitcairn", "Pacific/Ponape", "Pacific/Port_Moresby", "Pacific/Rarotonga", "Pacific/Saipan", "Pacific/Tahiti", "Pacific/Tarawa", "Pacific/Tongatapu", "Pacific/Truk", "Pacific/Wake", "Pacific/Wallis", "Pacific/Yap"

 

References

Ancillary Information To properly localize, parse, and format data requires ancillary information, which is not expressed in Locale Data Markup Language. Some of the formats for values used in Locale Data Markup Language are constructed according to external specifications. The sources for this data and/or formats include the following:
 
[Charts] The online code charts can be found at http://www.unicode.org/charts/ An index to characters names with links to the corresponding chart is found at http://www.unicode.org/charts/charindex.html
[DUCET] The Default Unicode Collation Element Table (DUCET)
For the base-level collation, of which all the collation tables in this document are tailorings.
http://www.unicode.org/reports/tr10/#Default_Unicode_Collation_Element_Table
[FAQ] Unicode Frequently Asked Questions
http://www.unicode.org/faq/
For answers to common questions on technical issues.
[FCD] As defined in UTN #5 Canonical Equivalences in Applications
http://www.unicode.org/notes/tn5/
[Feedback] Reporting Errors and Requesting Information Online
http://www.unicode.org/reporting.html
[Glossary] Unicode Glossary
http://www.unicode.org/glossary/
For explanations of terminology used in this and other documents.
[JavaChoice] Java ChoiceFormat
http://java.sun.com/j2se/1.4.2/docs/api/java/text/ChoiceFormat.html
[Olson] The Olson Data
For timezone and daylight savings information.
ftp://elsie.nci.nih.gov/pub/
[Reports] Unicode Technical Reports
http://www.unicode.org/reports/
For information on the status and development process for technical reports, and for a list of technical reports.
[UCA] UTS #10: Unicode Collation Algorithm
http://www.unicode.org/reports/tr10/
[UCD] The Unicode Character Database (UCD)
For character properties, casing behavior, default line-, word-, cluster-breaking behavior, etc.
http://www.unicode.org/ucd/
[Unicode] The Unicode Consortium. The Unicode Standard, Version 4.0. Reading, MA, Addison-Wesley, 2003. 0-321-18578-1.
[Versions] Versions of the Unicode Standard
http://www.unicode.org/standard/versions
For information on version numbering, and citing and referencing the Unicode Standard, the Unicode Character Database, and Unicode Technical Reports.
Other Standards Various standards define codes that are used as keys or values in Locale Data Markup Language. These include:
[ISO639] ISO Language Codes
http://lcweb.loc.gov/standards/iso639-2/
Actual List:
http://www.loc.gov/standards/iso639-2/langcodes.html
[ISO3166] ISO Region Codes
http://www.iso.org/iso/en/prods-services/iso3166ma/index.html
Actual List
http://www.iso.org/iso/en/prods-services/iso3166ma/02iso-3166-code-lists/list-en1.html
[ISO4217] ISO Currency Codes
http://www.bsi-global.com/Portfolio+of+Products+and+Services/Books+Guides/Consumer/th42090.xalter
Actual List (may not work in the future, since BSI wants £205 for the list)
http://www.bsi-global.com/Technical+Information/Publications/_Publications/tig90x.doc
[ISO15924] ISO Script Codes
 http://www.evertype.com/standards/iso15924/
Older version with Actual List:
http://www.evertype.com/standards/iso15924/document/dis15924.pdf
[RFC3066] IETF Language Codes
http://www.ietf.org/rfc/rfc3066.txt
Registered Exception List (those not of the form language + region)
http://www.evertype.com/standards/iso639/iana-lang-assignments.html
General The following are general references from the text:
[BIDI] UAX #9: The Bidirectional Algorithm
http://www.unicode.org/reports/tr9/
[Calendars] Calendrical Calculations: The Millennium Edition by Edward M. Reingold, Nachum Dershowitz; Cambridge University Press; Book and CD-ROM edition (July 1, 2001); ISBN: 0521777526
[CharMapML] UTR #22: Character Mapping Tables
http://www.unicode.org/reports/tr22/
[Comparisons] Comparisons between locale data from different sources
http://www.unicode.org/cldr/data/diff/
[CurrencyInfo] Currency Names
http://nsdsa.phdnswc.navy.mil/mspecs/docs/styleman2000/chapter_txt-17.html#17t6
UNECE Currency Data
http://www.unece.org/etrades/unedocs/repository/codelists/xml/CurrencyCodeList.xml
[DataFormats] CLDR Data Formats
http://www.unicode.org/cldr/data_formats.html
[Example] A sample in Locale Data Markup Language
http://www.unicode.org/cldr/dtd/1.1/ldml-example.xml
[ICUCollation] ICU rule syntax:
http://oss.software.ibm.com/icu/userguide/Collate_Customization.html
[ICUTransforms] Transforms
http://oss.software.ibm.com/icu/userguide/Transformations.html
Transforms Demo
http://oss.software.ibm.com/cgi-bin/icu/tr
[ICUUnicodeSet] ICU UnicodeSet
http://oss.software.ibm.com/icu/userguide/unicodeSet.html
API:
http://oss.software.ibm.com/icu4j/doc/com/ibm/icu/text/UnicodeSet.html
[LocaleExplorer] ICU Locale Explorer
http://oss.software.ibm.com/cgi-bin/icu/lx
[LocaleProject] Common Locale Data Repository Project
http://www.unicode.org/cldr/
[NamingGuideline] OpenI18N Locale Naming Guideline
http://www.li18nux.org/docs/text/LocNameGuide-V10.txt
[RBNF] Rule-Based Number Format
http://oss.software.ibm.com/icu/apiref/classRuleBasedNumberFormat.html#_details
[RBBI] Rule-Based Break Iterator
http://oss.software.ibm.com/icu/userguide/boundaryAnalysis.html
[Scripts] UAX #24: Script Names
http://www.unicode.org/reports/tr24/
[UCAChart] Collation Chart
http://www.unicode.org/charts/collation/
[URegex] UTR #18: Unicode Regular Expression Guidelines
http://www.unicode.org/reports/tr18/
UTS #18: Unicode Regular Expressions (Proposed Update)
http://www.unicode.org/reports/tr18/tr18-7.html
[UTCInfo] NIST Time and Frequency Division Home Page
http://www.boulder.nist.gov/timefreq/
U.S. Naval Observatory: What is Universal Time?
http://aa.usno.navy.mil/AA/faq/docs/UT.html
[WindowsCulture] Windows Culture Info (with  mappings from [RFC3066]-style codes to LCIDs)
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpref/html/frlrfSystemGlobalizationCultureInfoClassTopic.asp

Acknowledgments

Thanks to the following people for their contributions to LDML and/or CLDR: Patrick Andries, Philips Benjamin, Avery Chan, Alexis Cheng, Helena Shih Chapman, Lee Collins, Simon Dean, Sivaraj Doddannan, Behdad Esfahbod, Michael Everson, Doug Ewell, Doug Felt, Tom Garland, Yun Fang Ge, Deborah Goldsmith, Chris Hansten, Andy Heninger, Hideki Hiura, Jarkko Hietaniemi, Alexander Kachur, Kent Karlsson, Walter Keutgen, Akio Kido, Yuri Kirghisov, Rici Lake, Antoine Leca, Peter Linsey, Alan Liu, Steven R Loomis, Eric Mader, Sasha Maric, Eric Muller, Kentaroh Noji, Peter Nugent, Sandra O'Donnell, Åke Persson, Eike Rathke, George Rhoten, Markus Scherer, Baldev Soor, Michael Twomey, Philippe Verdy, Ram Viswanadha, Vladimir Weinstein, Daniel Yacob.

Modifications

The following summarizes modifications from the previous version of this document.