# `Localize.Nif`
[🔗](https://github.com/elixir-localize/localize/blob/v1.2.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, 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.

# `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.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`

```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*
