Search documentation of Localize

# Localize.Nif (Localize v0.39.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. Additional functions for number, date/time, and unit formatting will be added as the library grows.

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

available?()

Returns whether the NIF backend is available.

collation_available?()

Returns whether the collation NIF function is available.

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

Formats a MessageFormat 2 message string using ICU.

mf2_validate(message)

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

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.

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

Formats a number using ICU4C's NumberFormatter.

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

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

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

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.Nif.nif_compare/3` for the higher-level 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}`.