This document maps the features defined in Unicode Technical Standard #35 (LDML) version 49 against the implementation status of the Localize library.
Two areas are explicitly out of scope:
Part 7 — Keyboards. Not relevant to a formatting library.
Part 8 — Person Names. Implemented as the separate localize_person_names package, which uses Localize's person-name locale data (stored under the :person_names key in each locale ETF) and implements the full TR35 Part 8 formatting algorithm.
Legend
Implemented — feature is present and tested.
Partial — core functionality exists but some sub-features are missing.
Calendar (ca), collation (co), currency (cu), number system (nu), hour cycle (hc), first day (fw), region override (rg), measurement system (ms), and others.
Localize.LanguageTag.add_likely_subtags/1 and remove_likely_subtags/2, including both the favor-script (default) and favor-region removal variants, verified against the CLDR likely-subtags test data.
Rendered as a subtag by Localize.Locale.LocaleDisplay.display_name/2 — de-1901 is "German (Traditional German orthography)", en-US-posix is "English (United States, Computer)".
Key/type display names
Implemented
Drives Localize.Locale.LocaleDisplay.display_name/2 — en-u-kn-true renders "English (Sort Digits Numerically)". type_value_name/2 returns the localized name of a boolean keyword value ("On"/"Off"), and key_name/2 and type_name/3 return the key and type names on their own for menu use.
Data ships and is readable — Localize.Locale.get(:ar, [:layout]) gives %{character_order: :rtl, line_order: :ttb} — but there is no dedicated accessor and nothing in the library consumes it.
Line order
Partial
Same :layout map; :ttb for every locale CLDR records.
Character Elements
Feature
Status
Notes
Exemplar characters
Not implemented
Ellipsis patterns
Implemented
Localize.ellipsis/2 with :initial, :medial, :final, :word_initial, :word_medial, :word_final styles.
Parse lenient characters
Implemented
Consumed by Localize.Number.Parser, which accepts the locale's lenient sets for the date, general and number scopes when parsing.
Delimiters
Feature
Status
Notes
Quotation marks
Implemented
Localize.quote/2 with locale-appropriate primary and alternate quotation marks.
Localize.Unit struct supports mixed units; formatting coverage not fully verified.
Duration unit patterns (hms)
Implemented
Localize.Duration.to_time_string/2 formats durations as "hh:mm:ss" with unbounded hours. to_string/2 formats as localized unit list (e.g., "11 months, 30 days").
Localize.affirmative_responses/1 and negative_responses/1 return CLDR's POSIX yesstr / nostr forms; affirmative?/2 and negative?/2 match a response, folding case.
Localize.MinimalPairs exposes the short phrases that demonstrate a locale's plural, ordinal, case and gender forms; format/3 picks the one a number selects.
Explicit 0 and 1
Partial
Standard plural categories used; explicit 0/1 override not independently verified.
Localize.Calendar.cyclic_years/2; U formats and parses the cyclic year name, y the year's place in the sixty-year cycle and G the cycle's number, which TR35 leaves open and ICU writes.
All date format pattern symbols (y, M, d, E, G, etc.)
Implemented
Full symbol set in Localize.DateTime.Formatter.
Invalid pattern fields
Implemented
A symbol at a width the Date Field Symbol Table does not list formats as U+FFFD; an undefined letter is an error.
Hour cycle (h, H, k, K)
Implemented
Including territory and locale preferences (hi_IN allows hB), the -u-hc- override, and the skeleton symbols j, J and C.
Day periods (a, b, B)
Implemented
a renders AM/PM; b renders noon/midnight at the exact points and AM/PM otherwise; B selects flexible day periods ("in the morning", "mittags") from the CLDR day-period rules, falling back to AM/PM for languages without rules. Noon and midnight are judged at the precision the pattern shows, so "h B" renders 12:05 as "12 noon".
Available formats (skeletons)
Implemented
Localize.DateTime.Format.Match for skeleton matching.
Interval formats
Implemented
Localize.Interval.to_string/3 for date/time/datetime intervals, in the formats of the endpoints' calendar, with an era difference shown as ICU shows it.
Append items (missing fields)
Implemented
Localize.DateTime.Format.AppendItems matches the closest format that is a subset of the request and appends the fields it lacks, so en renders :yMMMdQ as "Jul 6, 2024 (quarter: 3)".
The CLDR day-period rule sets (format and selection) are part of the supplemental data pipeline; the b and B format symbols select periods from them.
Time Zones
Feature
Status
Notes
Timezone format symbols (z, Z, O, v, V, X, x)
Implemented
Localize.DateTime.Formatter handles all timezone symbols.
GMT offset formatting
Implemented
gmtFormat with hourFormat for every known offset, zero included ("GMT+00:00", "GMT+0"), with a two-digit hour in the long format and the seconds of an offset that has them ("GMT-07:52:58"), and gmtUnknownFormat ("GMT+?") when the offset is unknown — the two styles TR35 defines. gmtZeroFormat is still in the data but no TR35 formatting rule uses it.
UTC designation (CLDR 49)
Implemented
CLDR 49's gmtFormat and gmtUnknownFormatalt="utc" forms, which spell the unambiguous designation for Coordinated Universal Time where gmtFormat may spell the London zone's "GMT". designation: :utc on Localize.DateTime.Timezone.gmt_format/3 writes them — "UTC+01:00" and "UTC+?" in en, "التوقيت العالمي+1:00" in ar against its "غرينتش+1:00" — and non_location_format/3 passes it to its GMT fallback. Both spellings read back through parse_offset/2. The pattern symbols (O, OOOO, ZZZZ) write the locale's gmtFormat, which is the designation TR35 gives them.
Dual offset format (CLDR 49)
Implemented
CLDR 49's dualOffsetFormat, joining the two offsets a zone keeps so the localized GMT format describes a zone that moves between them: offsets: :dual on Localize.DateTime.Timezone.gmt_format/3 writes Los Angeles as "GMT-8/-7" and Denver as "GMT-7/-6", where Phoenix keeps one offset and stays "GMT-7". The pair comes from the configured time zone database, sampled across the year around the value's time, so a value with no zone writes its single offset. It names a zone rather than a time, so it does not read back through parse_offset/2 and no pattern symbol writes it — TR35 defines none.
Metazone names
Implemented
The z and v symbols render the metazone's names — "Eastern Daylight Time" and "EDT", "Eastern Time" and "ET". Both formats qualify a metazone name with the zone's country or city unless the zone is the metazone's preferred zone for the locale's country, as TR35's steps for the non-location formats give it: "Pacific Time (Canada)" and "Pacific Standard Time (Canada)" for Vancouver in en. A zone's first metazone period that CLDR gives no beginning begins with 1970, as ICU begins it, and a zone is written by its offset and its location before it.
Exemplar cities
Implemented
VVV renders the exemplar city ("New York") and VVVV the generic location format ("New York Time"), which names the country of a zone that is the only one, or the primary one, in its country ("Italy Time"): by its short name where the locale has one, and by its code where the locale does not name it ("CU").
Timezone fallback formatting
Implemented
The generic format falls back from the zone's or metazone's name to the generic location format and then the localized GMT format, taking a standard name for a zone that keeps one offset for 184 days either side; the specific format falls back to the localized GMT format.
Time zone parsing
Implemented
Localize.DateTime.Timezone.parse_zone/2 and resolve/3 read every form TR35's parsing lists, in the order of its sample process, with the GMT format matched as leniently as it asks. Two departures from the sample, which TR35 calls only a sample: a country or city in parentheses is read only after a name the locale writes, where the sample reads "xxx (Italy)" as Rome whatever xxx is, and a country with several zones stands for its primary zone, which the sample leaves out.
Semantic Skeletons
Feature
Status
Notes
Semantic skeleton support
Partial
Localize.DateTime.SemanticSkeleton builds a skeleton from meaning ("YMDE", "MDTZ") with :length, :year_style, :zone_style, :hour_cycle, :time_precision and :alignment, taking the widths from the locale's date formats. It matches CLDR on all 240 conformance cases and rejects the field sets, and the options without their fields, that TR35 rules out; TR35's Auto zone style, which its mapping table leaves undefined, is not offered.
Supported Calendars
Feature
Status
Notes
Gregorian
Implemented
Primary calendar.
Japanese
Implemented
Era data and formatting.
Chinese
Implemented
Calendar data present.
Persian
Implemented
Calendar data present.
Coptic
Implemented
Calendar data present.
Ethiopic
Implemented
Including Amete Alem variant.
Dangi (Korean)
Implemented
Calendar data present.
Buddhist
Implemented
Era (BE), month, and day data tested.
Hebrew
Implemented
Era (AM), 13-month calendar with leap year variant tested.
Number-aware sorting via the :numeric option to Localize.Collation.sort/3 and compare/3, or the -u-kn locale extension.
Reorder (kr)
Implemented
Script reordering with weight remapping.
Max variable (kv)
Implemented
space, punct, symbol, currency.
Hiragana quaternary (kh)
Not implemented
Deprecated in recent UCA.
Collation Tailoring
Feature
Status
Notes
Locale-specific tailoring rules
Implemented
110 locale/type pairs covering 97 languages, extracted from CLDR XML.
Relation operators (<, <<, <<<, <<<<, =)
Implemented
Contractions (multi-character)
Implemented
Expansions (slash notation)
Implemented
e.g., ccs/cs in Hungarian.
Star syntax (<*)
Implemented
Used for CJK and other large character sets.
Context before (|)
Not implemented
[before N] positioning
Not implemented
[suppressContractions]
Implemented
Used by cu, sr, mk.
[optimize]
Not applicable
Advisory hint; intentionally ignored.
[import]
Implemented
Resolved at extraction time — imported rules are inlined into the ETF. Supports BCP47 tags (e.g., und-u-co-search, de-u-co-phonebk) and short locale tags (e.g., hr).
[strength] directive
Not implemented
Used by ja:private-kana only.
Collation Types
Feature
Status
Notes
Standard collation
Implemented
Default type for all locales.
Search collation
Implemented
Root search rules (Arabic form equivalences, Korean jamo decomposition, [suppressContractions]) extracted from CLDR XML. 20 locale-specific search types with resolved imports. Accessed via type: :search option.
Phonebook (de), Pinyin (zh), etc.
Partial
Some non-standard types extracted; not all verified.
Collation Features
Feature
Status
Notes
Alphabetic index characters
Not implemented
No UI bucketing support.
Collation type fallback chain
Partial
Falls back to standard; full 7-step chain not verified.
Delegates to Localize.Number.to_string/2. All numeric functions support signDisplay, minimumIntegerDigits, the significant-digit options, trailingZeroDisplay and roundingPriority; an unannotated numeric operand formats with the locale-aware :number default.
Draft. fields and length choose a semantic skeleton; the override options timeZone and calendar are supported, calendar through calendrical.
:time
Implemented
Draft. precision and timeZoneStyle choose a semantic skeleton; the override options timeZone, hour12 and calendar are supported.
:datetime
Implemented
Draft. dateFields, dateLength, timePrecision and timeZoneStyle choose a semantic skeleton; the override options are supported and inherited on re-annotation.
:offset
Implemented
Adjusts a numeric operand with the required add or subtract option (a non-negative integer) for both formatting and selection, per the MF2 :offset function. Used for patterns like "you and N other people".
Localize-specific MF2 functions (not in the spec)
Function
Notes
:list
Formats a list operand by delegating to Localize.List.to_string/2. Each element is itself formatted via Localize.Chars, so a list of dates, numbers, units, etc. picks up the message's locale and forwarded options. Supports a style (or type) option whose values map to CLDR list styles: "and", "and-short", "and-narrow", "or", "or-short", "or-narrow", "unit", "unit-short", "unit-narrow". Default is "and".
Unresolved variables error per spec; an unknown function is a Localize.FormatError with reason :unknown_function.
Data model errors
Implemented
All six rules are checked by Localize.Message.Validator.validate/1: duplicate declarations (including implicit-use-then-declare and self-reference), duplicate option names, duplicate variants (NFC-normalized keys), missing selector annotation, variant key mismatch, and missing fallback variant. Localize.Message.Parser.parse/1 checks syntax only; everything that formats or serializes a message runs both passes, reporting syntax errors first.
Function option and operand validation
Implemented
The select option must be a literal set directly on the expression; digit size options must be non-negative integers; string operands of the numeric functions must match the number-literal production; :currency, :unit and the date/time functions are rejected as selectors.
Literals keep all their code points; keys and a :string selector's value are compared in NFC (TR35 NormalizeKey), and names are compared as if normalized.
Bidirectional text handling
Partial
:bidi option (:none, :isolate, :auto) wraps placeholder output in Unicode isolate characters (FSI/PDI), and the @u:dir expression attribute overrides direction per expression. The u:dir / u:id expression options are not implemented, and the :isolate strategy isolates every placeholder where the WG default strategy leaves known-LTR placeholders unisolated.
MF2 known conformance gaps
The MessageFormat working group conformance suite — including the WG :test:function / :test:format / :test:select registry functions it uses to exercise selection mechanics — runs against both the parser and the formatter (test/localize/message/formatter_conformance_test.exs). The few cases the implementation cannot yet satisfy are excluded there, each with a documented reason:
The u:dir / u:id expression options are not implemented (the @u:dir attribute form is).
The :isolate bidi strategy isolates every placeholder where the WG default strategy leaves known-LTR placeholders unisolated (three cases).
Summary
Implemented (core functionality present and tested)
Language tag parsing and validation (BCP 47 / RFC 5646)
Locale management (get/put/default/with_locale)
Likely subtags and locale matching
Number formatting (decimal, percent, currency, accounting, compact, scientific, RBNF)
Number parsing
Date, time, and datetime formatting
Date, time, datetime and interval parsing
Interval formatting
Relative date/time formatting
Unit formatting, conversion, and preferences (also include basic math functions)