Skip to content

elixir-localize/Intl

Repository files navigation

Intl

An Elixir interface to internationalization functions modelled on the JavaScript Intl API.

If you are familiar with the JS Intl API, you already know how to use this library. The module names, function purposes, and option names mirror their JS counterparts — adapted to idiomatic Elixir conventions (snake_case, keyword options, {:ok, result} / {:error, reason} tuples).

Relationship to Localize

Intl is a thin shim over the Localize library which provides the full CLDR-based locale data and formatting engine. Each Intl module translates JS Intl option names and conventions into the corresponding Localize calls:

  • Intl.NumberFormat delegates to Localize.Number and Localize.Unit.

  • Intl.DateTimeFormat delegates to Localize.DateTime, Localize.Date, Localize.Time, and Localize.Interval.

  • Intl.ListFormat delegates to Localize.List.

  • Intl.DisplayNames delegates to Localize.Territory, Localize.Language, Localize.Currency, and Localize.Script.

  • Intl.RelativeTimeFormat delegates to Localize.DateTime.Relative.

  • Intl.PluralRules delegates to Localize.Number.PluralRule.

  • Intl.Collator delegates to Localize.Collation.

  • Intl.DurationFormat delegates to Localize.Duration.

  • Intl.Segmenter uses String.graphemes/1 for grapheme segmentation and the optional unicode_string library for word and sentence segmentation.

If you need lower-level control or access to features beyond the Intl API surface (such as unit conversion, message formatting, or calendar metadata), use Localize directly.

Compatibility and Differences

The full compatibility matrix is in the Compatibility guide. Key points:

  • Functional, not object-oriented. JS creates formatter instances with new Intl.NumberFormat(locale, options). Elixir passes options directly: Intl.NumberFormat.format(number, options).

  • snake_case options. JS minimumFractionDigits becomes :minimum_fraction_digits.

  • Tagged return tuples. All functions return {:ok, result} or {:error, reason}. Bang variants (format!/2) raise on error.

  • Collator returns atoms. Intl.Collator.compare/3 returns :lt, :eq, or :gt instead of -1, 0, or 1.

  • formatToParts is not supported in any module. The underlying Localize library does not expose structured format parts.

  • resolvedOptions and supportedLocalesOf are not wrapped. Use Localize.available_locale_id?/1 to check locale support directly.

  • Segmenter output is simplified. Returns a flat list of strings rather than the JS iterable of rich segment objects.

Examples

Number Formatting

iex> Intl.NumberFormat.format(1_234_567.89, locale: :en)
{:ok, "1,234,567.89"}

iex> Intl.NumberFormat.format(1_234_567.89, locale: :de)
{:ok, "1.234.567,89"}

iex> Intl.NumberFormat.format(0.56, locale: :en, style: :percent)
{:ok, "56%"}

iex> Intl.NumberFormat.format(1234.5, locale: :en, style: :currency, currency: :USD)
{:ok, "$1,234.50"}

Date and Time Formatting

iex> Intl.DateTimeFormat.format(~D[2025-03-15], locale: :en, date_style: :full)
{:ok, "Saturday, March 15, 2025"}

iex> Intl.DateTimeFormat.format(~D[2025-03-15], locale: :en, date_style: :short)
{:ok, "3/15/25"}

List Formatting

iex> Intl.ListFormat.format(["Monday", "Tuesday", "Wednesday"], locale: :en)
{:ok, "Monday, Tuesday, and Wednesday"}

iex> Intl.ListFormat.format(["tea", "coffee", "juice"], locale: :en, type: :disjunction)
{:ok, "tea, coffee, or juice"}

iex> Intl.ListFormat.format(["lundi", "mardi", "mercredi"], locale: :fr)
{:ok, "lundi, mardi et mercredi"}

Display Names

iex> Intl.DisplayNames.of("US", type: :region, locale: :en)
{:ok, "United States"}

iex> Intl.DisplayNames.of("DE", type: :region, locale: :fr)
{:ok, "Allemagne"}

iex> Intl.DisplayNames.of("fr", type: :language, locale: :en)
{:ok, "French"}

iex> Intl.DisplayNames.of(:Latn, type: :script, locale: :en)
{:ok, "Latin"}

iex> Intl.DisplayNames.of("JPY", type: :currency, locale: :en)
{:ok, "Japanese Yen"}

iex> Intl.DisplayNames.of(:gregorian, type: :calendar, locale: :en)
{:ok, "Gregorian Calendar"}

Relative Time

iex> Intl.RelativeTimeFormat.format(-1, :day, locale: :en)
{:ok, "yesterday"}

iex> Intl.RelativeTimeFormat.format(3, :hour, locale: :en)
{:ok, "in 3 hours"}

iex> Intl.RelativeTimeFormat.format(-3, :day, locale: :fr)
{:ok, "il y a 3 jours"}

Plural Rules

iex> Intl.PluralRules.select(1, locale: "en")
{:ok, :one}

iex> Intl.PluralRules.select(5, locale: "en")
{:ok, :other}

iex> Intl.PluralRules.select(2, locale: "ar")
{:ok, :two}

Collation

iex> Intl.Collator.compare("ä", "z", locale: :de, sensitivity: :base)
:lt

iex> Intl.Collator.sort(["banana", "apple", "cherry"], locale: :en)
["apple", "banana", "cherry"]

Duration Formatting

iex> Intl.DurationFormat.format(%{hours: 2, minutes: 30}, locale: :en)
{:ok, "2 hours and 30 minutes"}

Text Segmentation

iex> Intl.Segmenter.segment("héllo", granularity: :grapheme)
{:ok, ["h", "é", "l", "l", "o"]}

iex> Intl.Segmenter.segment("Hello world", granularity: :word, trim: true)
{:ok, ["Hello", "world"]}

iex> Intl.Segmenter.segment("Hello. How are you?", granularity: :sentence)
{:ok, ["Hello. ", "How are you?"]}

Locale Utilities

iex> Intl.get_canonical_locales(["en-us", "fr-fr"])
{:ok, ["en-US", "fr-FR"]}

iex> {:ok, calendars} = Intl.supported_values_of(:calendar)
iex> :gregorian in calendars
true

Installation

Add intl to your list of dependencies in mix.exs:

def deps do
  [
    {:intl, "~> 0.1.0"}
  ]
end

Word and sentence segmentation require the optional unicode_string dependency:

{:unicode_string, "~> 1.8"}

Locale Data

Intl delegates to Localize for locale data. The :en locale is always available. To use other locales, either pre-download their data at build time:

mix localize.download_locales de fr ja

Or enable runtime downloading in config/runtime.exs:

config :localize, :allow_runtime_locale_download, true

Locale data is loaded lazily into :persistent_term on first access. See the Localize documentation for full configuration details.

About

An Intl-compatible wrapper around Localize

Resources

License

Stars

1 star

Watchers

0 watching

Forks

Packages

 
 
 

Contributors

Languages