# `Localize.Nif`
[🔗](https://github.com/elixir-localize/localize/blob/v0.13.0/lib/localize/nif.ex#L1)

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.

# `available?`

```elixir
@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?`

```elixir
@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`

```elixir
@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`

```elixir
@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`

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`

```elixir
@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`

```elixir
@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`

```elixir
@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}`.

---

*Consult [api-reference.md](api-reference.md) for complete listing*
