Localize.Nif (Localize v0.46.0)

Copy Markdown View Source

Optional NIF interface to ICU4C for high-performance locale operations.

This module provides NIF bindings for ICU4C functions including MessageFormat 2.0 parsing and formatting, number formatting, plural rules, unit formatting and collation.

The stable way to use the NIF backend is the backend: :nif option on the corresponding public formatting functions (for example Localize.Number.to_string/2 and Localize.Message.format/3); the individual functions in this module are a low-level surface whose signatures may change with the underlying ICU API.

The NIF is opt-in and requires:

  1. ICU system libraries installed (ICU 75+ with MF2 support).

  2. The elixir_make dependency.

  3. Enable the NIF via either:

    • Environment variable: LOCALIZE_NIF=true mix compile
    • Application config in config.exs: config :localize, :nif, true

The config key must be set in config.exs (not runtime.exs) because it is evaluated at compile time to include the :elixir_make compiler.

If the NIF is not available, available?/0 returns false and the pure Elixir implementations are used automatically.

Summary

Functions

Returns whether the NIF backend is available.

Returns whether the collation NIF function is available.

Formats a MessageFormat 2 message string using ICU.

Validates a MessageFormat 2 message string using ICU's parser.

Formats a number using ICU4C's NumberFormatter.

Returns the plural category for a number using ICU's PluralRules.

Formats a number with a unit using ICU4C's NumberFormatter.

Functions

available?()

@spec available?() :: boolean()

Returns whether the NIF backend is available.

Returns

  • true if the NIF shared library was loaded successfully.

  • false if the NIF is not compiled or ICU libraries are missing.

Examples

iex> is_boolean(Localize.Nif.available?())
true

collation_available?()

@spec collation_available?() :: boolean()

Returns whether the collation NIF function is available.

Returns

  • true if the collation NIF function was loaded successfully.

  • false if the NIF is not compiled or ICU libraries are missing.

mf2_format(message, locale \\ "en", args \\ %{})

@spec mf2_format(String.t(), String.t(), map() | String.t()) ::
  {:ok, String.t()} | {:error, String.t()}

Formats a MessageFormat 2 message string using ICU.

Arguments are passed as a map of %{name => value} and encoded to JSON for the NIF.

Arguments

  • message is an MF2 message string.

  • locale is a locale identifier string. The default is "en".

  • args is a map of variable bindings. The default is %{}.

Returns

  • {:ok, formatted_string} on success.

  • {:error, reason} on failure.

mf2_validate(message)

@spec mf2_validate(String.t()) :: {:ok, String.t()} | {:error, String.t()}

Validates a MessageFormat 2 message string using ICU's parser.

Arguments

  • message is an MF2 message string.

Returns

  • {:ok, normalized_pattern} if the message is valid.

  • {:error, reason} if the message is invalid.

nif_collation_cmp(string_a, string_b, strength, backwards, alternate, case_first, case_level, normalization, numeric, reorder_bin)

Compare two strings using ICU collation with full option support.

This is the raw NIF function. Use Localize.Collation.compare/3 for the public interface that handles option encoding.

Arguments

  • string_a - the first string to compare.

  • string_b - the second string to compare.

  • strength - ICU strength enum value, or -1 for default.

  • backwards - ICU backwards enum value, or -1 for default.

  • alternate - ICU alternate enum value, or -1 for default.

  • case_first - ICU case_first enum value, or -1 for default.

  • case_level - ICU case_level enum value, or -1 for default.

  • normalization - ICU normalization enum value, or -1 for default.

  • numeric - ICU numeric enum value, or -1 for default.

  • reorder_bin - binary of packed big-endian int32 reorder codes.

Returns

An integer: -1 (less than), 0 (equal), or 1 (greater than).

number_format(number, locale, options \\ [])

@spec number_format(number() | Decimal.t(), String.t(), Keyword.t()) ::
  {:ok, String.t()} | {:error, String.t()}

Formats a number using ICU4C's NumberFormatter.

This provides a reference implementation for cross-validating the pure Elixir number formatting in Localize.Number.

Arguments

  • number is a number (integer, float, or Decimal).

  • locale is a locale identifier string (e.g., "en-US", "de").

  • options is a keyword list of options.

Options

  • :currency is an ISO 4217 currency code string (e.g., "USD").

  • :min_fraction_digits is the minimum fractional digits.

  • :max_fraction_digits is the maximum fractional digits.

  • :notation is one of "standard", "scientific", "compact".

  • :use_grouping is a boolean for grouping separators.

Returns

  • {:ok, formatted_string} or {:error, reason}.

plural_rule(number, locale, type \\ :cardinal)

@spec plural_rule(number() | Decimal.t(), String.t(), :cardinal | :ordinal) ::
  {:ok, atom()} | {:error, String.t()}

Returns the plural category for a number using ICU's PluralRules.

Arguments

  • number is a number (integer, float, or Decimal) to classify.

  • locale is a locale identifier string (e.g., "en", "ar").

  • type is :cardinal or :ordinal.

Returns

  • {:ok, category} where category is one of :zero, :one, :two, :few, :many, or :other.

  • {:error, reason} if ICU cannot determine the plural category.

Examples

When the NIF is available:

Localize.Nif.plural_rule(1, "en", :cardinal)
#=> {:ok, :one}

Localize.Nif.plural_rule(2, "en", :ordinal)
#=> {:ok, :two}

unit_format(number, unit, locale, options \\ [])

@spec unit_format(number() | Decimal.t(), String.t(), String.t(), Keyword.t()) ::
  {:ok, String.t()} | {:error, String.t()}

Formats a number with a unit using ICU4C's NumberFormatter.

Arguments

  • number is a number (integer, float, or Decimal).

  • unit is an ICU unit identifier string (e.g., "meter", "mile-per-hour").

  • locale is a locale identifier string.

  • options is a keyword list of options.

Options

  • :style is "long", "short", or "narrow". Default is "long".

Returns

  • {:ok, formatted_string} or {:error, reason}.