JavaScript Intl vs Localize: Functional Comparison

Copy Markdown View Source

This document compares the functional coverage of the JavaScript Intl API and the Localize Elixir library. Both are built on the Unicode CLDR data set, but they expose different subsets of that data and offer different capabilities.

Summary

JavaScript Intl provides a focused set of formatting and comparison APIs for use in browsers and server-side JS. Localize provides a broader set of internationalization functions including everything Intl offers plus message formatting, unit conversion, number parsing, rule-based number formatting, territory and currency metadata, calendar locale data, Gettext integration, and more.

Feature-by-Feature Comparison

Number Formatting

CapabilityJS IntlLocalize
Decimal formattingIntl.NumberFormatLocalize.Number.to_string/2
Currency formattingIntl.NumberFormat (style: "currency")Localize.Number.to_string/2 (format: :currency)
Percent formattingIntl.NumberFormat (style: "percent")Localize.Number.to_string/2 (format: :percent)
Unit formattingIntl.NumberFormat (style: "unit")Localize.Unit.to_string/2
Scientific notationIntl.NumberFormat (notation: "scientific")Localize.Number.to_string/2 (format: :scientific)
Compact notation ("1.2K")Intl.NumberFormat (notation: "compact")Localize.Number.to_string/2 (format: :decimal_short / :decimal_long)
Format to partsformatToParts()Not available
Range formattingformatRange()Localize.Number.to_range_string/3
Number parsingNot availableLocalize.Number.Parser.parse/2
Number scanning in textNot availableLocalize.Number.Parser.scan/2
Approximate/at-least/at-mostNot availableto_approximately_string/2, to_at_least_string/2, to_at_most_string/2
Ratio/fraction formattingNot availableLocalize.Number.to_ratio_string/2
Rule-based formatting (spellout, Roman numerals)Not availableLocalize.Number.Rbnf.to_string/3
Number system transliterationNot availableLocalize.Number.Transliterate
Currency symbol resolution from textNot availableLocalize.Number.Parser.resolve_currency/2

Date and Time Formatting

CapabilityJS IntlLocalize
Date formattingIntl.DateTimeFormatLocalize.Date.to_string/2
Time formattingIntl.DateTimeFormatLocalize.Time.to_string/2
DateTime formattingIntl.DateTimeFormatLocalize.DateTime.to_string/2
Format to partsformatToParts()Not available
Date/time range formattingformatRange()Localize.Interval.to_string/3
Partial date formatting (year+month only, etc.)Not directlyLocalize.Date.to_string/2 with partial maps
Custom CLDR skeletonsVia component optionsDirect skeleton atoms or strings
Relative time ("3 days ago")Intl.RelativeTimeFormatLocalize.DateTime.Relative.to_string/2
Calendar metadata (month names, day names, eras)Not availableLocalize.Calendar.months/2, days/2, eras/2, quarters/2, day_periods/2
First day of week / weekend days per territoryNot availableLocalize.Calendar.first_day_for_territory/1, weekend/1
Calendar display namesIntl.DisplayNames (type: "calendar")Localize.Calendar.display_name/3
Date-time field display namesIntl.DisplayNames (type: "dateTimeField")Localize.Calendar.display_name/3
strftime-compatible optionsNot availableLocalize.Calendar.strftime_options!/1
Multiple calendar systemsVia calendar option17+ calendar types (Gregorian, Buddhist, Chinese, Hebrew, Islamic, Japanese, Persian, etc.)

Duration Formatting

CapabilityJS IntlLocalize
Duration formatting (unit names)Intl.DurationFormatLocalize.Duration.to_string/2
Duration formatting (numeric, "37:48:12")Not availableLocalize.Duration.to_time_string/2
Duration calculation between datesNot availableLocalize.Duration.new/2
Duration from secondsNot availableLocalize.Duration.new_from_seconds/1
Format to partsformatToParts()Not available

List Formatting

CapabilityJS IntlLocalize
Conjunction lists ("a, b, and c")Intl.ListFormat (type: "conjunction")Localize.List.to_string/2 (format: :standard)
Disjunction lists ("a, b, or c")Intl.ListFormat (type: "disjunction")Localize.List.to_string/2 (format: :or)
Unit lists ("a, b, c")Intl.ListFormat (type: "unit")Localize.List.to_string/2 (format: :unit)
Format to partsformatToParts()Not available
Intersperse (for safe HTML)Not availableLocalize.List.intersperse/2

Display Names

CapabilityJS IntlLocalize
Region/territory namesIntl.DisplayNames (type: "region")Localize.Territory.display_name/2
Language namesIntl.DisplayNames (type: "language")Localize.Language.display_name/2
Currency namesIntl.DisplayNames (type: "currency")Localize.Currency.display_name/2
Script namesIntl.DisplayNames (type: "script")Localize.Script.display_name/2
Calendar type namesIntl.DisplayNames (type: "calendar")Localize.Calendar.display_name(:calendar, ...)
Date-time field namesIntl.DisplayNames (type: "dateTimeField")Localize.Calendar.display_name(:date_time_field, ...)
Locale display names ("English (United States)")Not availableLocalize.Locale.LocaleDisplay.display_name/2
Subdivision namesNot availableLocalize.Territory.subdivision_name/2
Territory translation (name in one locale to another)Not availableLocalize.Territory.translate_territory/3
Reverse lookup (name to territory code)Not availableLocalize.Territory.to_territory_code/2

Plural Rules

CapabilityJS IntlLocalize
Cardinal plural categoryIntl.PluralRules (type: "cardinal")Localize.Number.PluralRule.plural_type/2 (type: :cardinal)
Ordinal plural categoryIntl.PluralRules (type: "ordinal")Localize.Number.PluralRule.plural_type/2 (type: :ordinal)
Range plural categoryselectRange()Not available

Collation (String Comparison and Sorting)

CapabilityJS IntlLocalize
Locale-aware string comparisonIntl.Collator.compare()Localize.Collation.compare/3
Locale-aware sortingVia Array.sort() with CollatorLocalize.Collation.sort/2
Sort key generationNot availableLocalize.Collation.sort_key/2
Sensitivity / strength levelssensitivity optionstrength option
Numeric collationnumeric optionnumeric option
Case-first orderingcaseFirst optioncase_first option

Text Segmentation

CapabilityJS IntlLocalize
Grapheme cluster segmentationIntl.Segmenter (granularity: "grapheme")Not in Localize (Elixir built-in: String.graphemes/1)
Word segmentationIntl.Segmenter (granularity: "word")Not in Localize (available via unicode_string library)
Sentence segmentationIntl.Segmenter (granularity: "sentence")Not in Localize (available via unicode_string library)
Segment metadata (isWordLike)YesNot available
Line break segmentationNot availableNot in Localize (available via unicode_string library)

Message Formatting

CapabilityJS IntlLocalize
ICU MessageFormat 2Not availableLocalize.Message.format/3
Message canonicalizationNot availableLocalize.Message.canonical_message/2
Message similarity (Jaro distance)Not availableLocalize.Message.jaro_distance/3
Gettext integrationNot availableLocalize.Gettext.Interpolation

Units of Measurement

CapabilityJS IntlLocalize
Unit formattingIntl.NumberFormat (style: "unit")Localize.Unit.to_string/2
Unit creation and validationNot availableLocalize.Unit.new/3
Unit conversionNot availableLocalize.Unit.convert/2
Measurement system conversionNot availableLocalize.Unit.convert_measurement_system/2
Unit arithmeticNot availableLocalize.Unit.Math (add, subtract, multiply, divide, compare)
Territory-based unit preferencesNot availableLocalize.Unit.Preference
Usage-based formatting ("person-height", "road")Not availableLocalize.Unit.to_string/2 with :usage option
Unit category discoveryNot availableLocalize.Unit.known_units_by_category/0
Measurement system per territoryNot availableLocalize.Unit.measurement_system_for_territory/1

Currency Data

CapabilityJS IntlLocalize
Currency formattingIntl.NumberFormat (style: "currency")Localize.Number.to_string/2 (format: :currency)
Currency display nameIntl.DisplayNames (type: "currency")Localize.Currency.display_name/2
Currency validationNot availableLocalize.Currency.known_currency_code?/1
Custom currency creationNot availableLocalize.Currency.new/2
Currencies for a localeNot availableLocalize.Currency.currencies_for_locale/1
Currency code from territoryNot availableLocalize.Territory.to_currency_code/1

Territory Data

CapabilityJS IntlLocalize
Territory display nameIntl.DisplayNames (type: "region")Localize.Territory.display_name/2
Territory hierarchy (parent/children/contains?)Not availableLocalize.Territory.parent/1, children/1, contains?/2
Territory info (GDP, population, etc.)Not availableLocalize.Territory.info/1
Unicode flag emojiNot availableLocalize.Territory.unicode_flag/1
Country codes listNot availableLocalize.Territory.country_codes/0

Locale Management

CapabilityJS IntlLocalize
Canonical locale namesIntl.getCanonicalLocales()Localize.LanguageTag.canonicalize/1
Supported values discoveryIntl.supportedValuesOf()Various known_* functions
BCP 47 language tag parsingIntl.Locale constructorLocalize.LanguageTag.parse/1
Process-level localeNot applicable (browser locale)Localize.get_locale/0, put_locale/1, with_locale/2
Locale matching / distanceNot availableLocalize.Locale.DistanceTrie
Locale display name ("English (United States)")Not availableLocalize.Locale.LocaleDisplay.display_name/2
Likely subtagsNot availableSupported via CLDR data

Text Utilities

CapabilityJS IntlLocalize
Locale-aware quotation marksNot availableLocalize.quote/2
Locale-aware ellipsisNot availableLocalize.ellipsis/2

Capabilities Unique to JS Intl

  • formatToParts() — All JS Intl formatters can return structured arrays of {type, value} objects representing the individual parts of a formatted string. This is useful for custom rendering (for example, styling the currency symbol differently from the number). Localize does not expose format parts.

  • Intl.Segmenter segment metadata — The JS segmenter returns isWordLike for each word segment, distinguishing content words from punctuation and whitespace. The unicode_string library (used by Intl.Segmenter in this project) does not provide this metadata.

  • Intl.PluralRules.selectRange() — Determines the plural category for a range of numbers (for example, "1–3 items"). Localize does not provide range plural selection.

Capabilities Unique to Localize

  • ICU MessageFormat 2Localize.Message.format/3 parses and evaluates MessageFormat 2 strings with variable placeholders, plural rules, select expressions, and custom formatting functions. JS has no built-in message formatting (developers typically use external libraries like intl-messageformat).

  • Rule-based number formatting (RBNF)Localize.Number.Rbnf.to_string/3 formats numbers as spellout text ("one hundred twenty-three"), ordinal text ("twenty-third"), Roman numerals ("CXXIII"), and other algorithmic number systems per locale.

  • Number parsingLocalize.Number.Parser.parse/2 parses locale-formatted number strings back into numbers, handling locale-specific decimal separators and grouping characters. JS Intl has no parsing counterpart.

  • Unit conversion and arithmeticLocalize.Unit.convert/2 converts between compatible units (kilometers to miles, Celsius to Fahrenheit). Localize.Unit.Math provides add, subtract, multiply, divide, and compare operations on unit values. JS Intl can format units but cannot convert between them.

  • Territory hierarchy and metadataLocalize.Territory provides parent/child relationships between territories (for example, "US" is contained in "Northern America" which is contained in "Americas"), territory info (population, GDP, languages), and Unicode flag emoji.

  • Calendar locale dataLocalize.Calendar exposes month names, day names, era names, quarter names, and day period names in all styles (wide, abbreviated, narrow) for all supported calendars and locales. It also provides first-day-of-week and weekend configuration per territory.

  • Duration calculationLocalize.Duration.new/2 computes the calendar duration between two dates or times. JS Intl.DurationFormat can only format a duration object that you provide — it cannot calculate one.

  • Locale display namesLocalize.Locale.LocaleDisplay.display_name/2 produces human-readable locale descriptions like "English (United States)" or "français (France)". JS Intl has no equivalent.

  • Subdivision namesLocalize.Territory.subdivision_name/2 provides localized names for country subdivisions (states, provinces, regions). JS Intl does not support subdivisions.

  • Custom currenciesLocalize.Currency.new/2 allows defining private-use currency codes for applications that need currencies not in ISO 4217.

  • Gettext integrationLocalize.Gettext.Interpolation provides a Gettext interpolation backend that uses CLDR formatting for interpolated values.

  • Text utilitiesLocalize.quote/2 wraps text in locale-appropriate quotation marks (for example, « » for French, „ " for German). Localize.ellipsis/2 adds locale-appropriate ellipsis characters.

  • List intersperseLocalize.List.intersperse/2 returns a list with separator strings inserted between elements (rather than a concatenated string), which is useful for building safe HTML output where elements may contain markup.