Intl API Compatibility

Copy Markdown View Source

This document tracks the compatibility between this Elixir Intl library and the JavaScript Intl API.

General Differences

The JS Intl API is object-oriented: you create a formatter instance with new Intl.NumberFormat(locale, options) and then call methods on it. This library is functional: options are passed directly to each function call as a keyword list.

All JS camelCase parameter names are converted to snake_case in this library. For example, minimumFractionDigits becomes minimum_fraction_digits.

Return values use Elixir's {:ok, result} / {:error, reason} convention. Bang variants (for example, format!/2) are provided for convenience.

Static Methods

JS Intl MethodElixir FunctionStatus
Intl.getCanonicalLocales()Intl.get_canonical_locales/1Compatible
Intl.supportedValuesOf()Intl.supported_values_of/1Partial — supports :calendar, :currency, :numbering_system, :unit. Does not support "collation" or "timeZone".

Intl.NumberFormat

JS MethodElixir FunctionStatus
format()Intl.NumberFormat.format/2Compatible
formatRange()Intl.NumberFormat.format_range/3Compatible — supports :decimal, :currency, and :percent styles. :unit ranges are not supported.
formatToParts()Not supported
formatRangeToParts()Not supported
resolvedOptions()Not supported
supportedLocalesOf()Use Localize.available_locale_id?/1 directly

NumberFormat Option Mapping

JS OptionElixir OptionNotes
style:style:decimal, :currency, :percent, :unit
currency:currencyPass-through
unit:unitUnit identifier string
unitDisplay:unit_display:long, :short, :narrow
notation:notation:standard, :scientific, :engineering, or :compact
compactDisplay:compact_display:short or :long. Compact currency always uses the short form (CLDR defines no long compact currency format).
minimumFractionDigits:minimum_fraction_digitsMapped to :min_fractional_digits in Localize
maximumFractionDigits:maximum_fraction_digitsMapped to :max_fractional_digits in Localize
minimumIntegerDigitsNot supported (Localize has no zero-padding option)
minimumSignificantDigits:minimum_significant_digitsPass-through; integer in 1..21
maximumSignificantDigits:maximum_significant_digitsPass-through; integer in 1..21
useGrouping:use_grouping:always, :auto, :min2, true, false. Mapped to Localize :minimum_grouping_digits.
signDisplay:sign_display:auto, :always, :except_zero, :negative, :never. Pass-through to Localize.
currencyDisplay:currency_display:symbol, :narrow_symbol, :code, :name. :name renders via the Localize :currency_long format, which formats the number as a decimal (no forced currency fraction digits).
currencySign:currency_sign:standard or :accounting. :accounting maps to the Localize :accounting format.
numberingSystem:numbering_systemMapped to Localize :number_system. Any valid CLDR numbering system may be used with any locale, including algorithmic systems. A -u-nu- locale extension is also honoured.
roundingIncrement:rounding_incrementMapped to Localize :round_nearest. Any positive integer is accepted (JS restricts the value set).
roundingMode:rounding_modePass-through to Localize
roundingPriorityNot supported
trailingZeroDisplayNot supported

When both fraction-digit and significant-digit options are given, significant digits take precedence (equivalent to the JS default roundingPriority: "auto").

Compact notation applies the ECMA-402 default precision of at most two significant digits on the mantissa, matching JS (1234 formats as "1.2K").

Intl.DateTimeFormat

JS MethodElixir FunctionStatus
format()Intl.DateTimeFormat.format/2Compatible
formatRange()Intl.DateTimeFormat.format_range/3Compatible
formatToParts()Not supported
formatRangeToParts()Not supported
resolvedOptions()Not supported
supportedLocalesOf()Use Localize.available_locale_id?/1 directly

DateTimeFormat Option Mapping

JS OptionElixir OptionNotes
dateStyle:date_style:full, :long, :medium, :short
timeStyle:time_style:full, :long, :medium, :short
weekday:weekdayComponent options build a CLDR skeleton
year:yearComponent option
month:monthComponent option
day:dayComponent option
hour:hourComponent option
minute:minuteComponent option
second:secondComponent option
timeZone:time_zonePass-through
calendar:calendarPass-through
hour12Not directly supported; use locale extensions instead
hourCycleNot supported
timeZoneNameNot supported
numberingSystemNot supported
eraNot supported as a standalone component
fractionalSecondDigitsNot supported
dayPeriodNot supported

DateTimeFormat Input Types

The JS API accepts Date objects. This library accepts Elixir Date, Time, DateTime, and NaiveDateTime structs. The appropriate Localize formatter is dispatched automatically based on the input type.

Intl.ListFormat

JS MethodElixir FunctionStatus
format()Intl.ListFormat.format/2Compatible
formatToParts()Not supported
resolvedOptions()Not supported
supportedLocalesOf()Use Localize.available_locale_id?/1 directly

ListFormat Option Mapping

JS OptionElixir OptionNotes
type:type:conjunction, :disjunction, :unit
style:style:long, :short, :narrow

The combination of type and style is mapped to a Localize list format atom (for example, :standard, :or_short, :unit_narrow).

Intl.DisplayNames

JS MethodElixir FunctionStatus
of()Intl.DisplayNames.of/2Partial
resolvedOptions()Not supported
supportedLocalesOf()Use Localize.available_locale_id?/1 directly

DisplayNames Type Support

JS TypeElixir :typeStatus
"region":regionCompatible — delegates to Localize.Territory.display_name/2
"language":languageCompatible — delegates to Localize.Language.display_name/2
"currency":currencyCompatible — delegates to Localize.Currency.display_name/2
"script":scriptCompatible — delegates to Localize.Script.display_name/2
"calendar":calendarCompatible — delegates to Localize.Calendar.display_name/3
"dateTimeField":date_time_fieldCompatible — delegates to Localize.Calendar.display_name/3

Intl.RelativeTimeFormat

JS MethodElixir FunctionStatus
format()Intl.RelativeTimeFormat.format/3Compatible
formatToParts()Not supported
resolvedOptions()Not supported
supportedLocalesOf()Use Localize.available_locale_id?/1 directly

RelativeTimeFormat Option Mapping

JS OptionElixir OptionNotes
style:style:long, :short, :narrow. Mapped to Localize :format (:standard, :short, :narrow).
numeric:numeric:always or :auto. Currently Localize always uses :auto behavior.
localeMatcherNot supported

RelativeTimeFormat Differences

The JS API signature is format(value, unit) where both are required. The Elixir API is format(value, unit, options) with the unit as a separate argument rather than a string parameter.

The :numeric option with value :always is accepted but may not force numeric output in all cases, as the underlying Localize library defaults to auto-detection (using "yesterday"/"tomorrow" when the value is -1/+1).

Intl.PluralRules

JS MethodElixir FunctionStatus
select()Intl.PluralRules.select/2Compatible
selectRange()Not supported
resolvedOptions()Not supported
supportedLocalesOf()Use Localize.available_locale_id?/1 directly

PluralRules Differences

Returns {:ok, atom} (for example, {:ok, :one}) instead of a string like "one".

Intl.Collator

JS MethodElixir FunctionStatus
compare()Intl.Collator.compare/3Compatible (different return type)
resolvedOptions()Not supported
supportedLocalesOf()Use Localize.available_locale_id?/1 directly

Collator Differences

The JS compare() returns -1, 0, or 1. This library returns :lt, :eq, or :gt following Elixir conventions, making it compatible with Enum.sort/2.

An additional sort/2 convenience function is provided that is not present in the JS API.

Collator Option Mapping

JS OptionElixir OptionNotes
sensitivity:sensitivity:base, :accent, :case, :variant. Mapped to Localize :strength (:primary, :secondary, :tertiary, :quaternary).
caseFirst:case_firstPass-through to Localize
numeric:numericPass-through to Localize
ignorePunctuation:ignore_punctuationMapped to Localize alternate: :shifted
usageNot supported (Localize always uses sort semantics)
collationNot supported
localeMatcherNot supported

Intl.DurationFormat

JS MethodElixir FunctionStatus
format()Intl.DurationFormat.format/2Compatible
formatToParts()Not supported
resolvedOptions()Not supported
supportedLocalesOf()Use Localize.available_locale_id?/1 directly

DurationFormat Differences

The JS API accepts a plain object with years, months, days, hours, minutes, seconds properties. This library accepts both a Localize.Duration struct and a plain map with those keys (plural or singular forms).

DurationFormat Option Mapping

JS OptionElixir OptionNotes
style:style:long, :short, :narrow
Per-unit style options (hoursDisplay, etc.)Not supported

Intl.Segmenter

JS MethodElixir FunctionStatus
segment()Intl.Segmenter.segment/2Partial
resolvedOptions()Not supported
supportedLocalesOf()Use Localize.available_locale_id?/1 directly

Segmenter Granularity Support

JS GranularityElixir :granularityStatus
"grapheme":graphemeCompatible — uses String.graphemes/1 (always available)
"word":wordCompatible — requires optional unicode_string dependency
"sentence":sentenceCompatible — requires optional unicode_string dependency

Segmenter Differences

  • The JS API returns an iterable of {segment, index, input, isWordLike} objects. This library returns {:ok, [String.t()]} — a flat list of segment strings.

  • The isWordLike property from JS word segmentation is not replicated.

  • The :word and :sentence granularity require the optional unicode_string (~> 1.8) dependency. If not installed, these return {:error, reason}.

Features Not Supported Across All Modules

  • formatToParts — Not available in any module. The underlying Localize library does not expose structured format parts.

  • resolvedOptions — Not implemented. In the JS API this returns the effective options after locale negotiation and default resolution. Could be added in a future version.

  • supportedLocalesOf — Not wrapped. Use Localize.available_locale_id?/1 directly to check locale support.

  • localeMatcher — The JS localeMatcher option ("best fit" / "lookup") is not supported. Localize uses its own locale resolution strategy.