# `Localize.Number.System`
[🔗](https://github.com/elixir-localize/localize/blob/v1.2.0/lib/localize/number/system.ex#L1)

Functions to manage number systems for a locale.

Number systems define different representations for numeric
values. They are one of two types:

* Numeric systems use a predefined set of digits to represent
  numbers (e.g., Western digits, Thai digits, Devanagari digits).

* Algorithmic systems use rules to format numbers and do not
  have a simple digit mapping (e.g., Roman numerals, Chinese
  numerals).

Each locale defines number system types that map to specific
number systems:

* `:default` — the default number system for the locale.

* `:native` — the number system using the script's native digits.

* `:traditional` — traditional numerals (may be algorithmic).

* `:finance` — financial numerals (e.g., anti-fraud ideographs).

# `system_name`

```elixir
@type system_name() :: atom()
```

# `system_type`

```elixir
@type system_type() :: :default | :native | :traditional | :finance
```

# `algorithmic_systems`

```elixir
@spec algorithmic_systems() :: map()
```

Returns a map of number systems that are algorithmic.

Algorithmic number systems don't have decimal digits. Numbers
are formed by algorithm using rules-based number formats.

### Returns

* A map of `%{system_name => %{type: :algorithmic, rules: String.t()}}`.

### Examples

    iex> Localize.Number.System.algorithmic_systems()[:roman]
    %{type: :algorithmic, rules: "roman-upper"}

# `default_number_system_type`

```elixir
@spec default_number_system_type() :: :default
```

Returns the default number system type.

The default number system type is `:default`.

### Returns

* The atom `:default`.

### Examples

    iex> Localize.Number.System.default_number_system_type()
    :default

# `generate_transliteration_map`

```elixir
@spec generate_transliteration_map(String.t(), String.t()) ::
  map() | {:error, Exception.t()}
```

Generates a transliteration map between two digit strings.

### Arguments

* `from` is a string of digits to map from.

* `to` is a string of digits to map to (must be same length).

### Returns

* A map of `%{grapheme => grapheme}`.

* `{:error, exception}` if the strings are not the same length.

### Examples

    iex> Localize.Number.System.generate_transliteration_map("0123456789", "9876543210")
    %{
      "0" => "9",
      "1" => "8",
      "2" => "7",
      "3" => "6",
      "4" => "5",
      "5" => "4",
      "6" => "3",
      "7" => "2",
      "8" => "1",
      "9" => "0"
    }

# `known_number_system_types`

```elixir
@spec known_number_system_types() :: [system_type(), ...]
```

Returns the list of known number system type names.

### Returns

* A list of atoms: `[:default, :native, :traditional, :finance]`.

### Examples

    iex> Localize.Number.System.known_number_system_types()
    [:default, :native, :traditional, :finance]

# `known_number_systems`

```elixir
@spec known_number_systems() :: [system_name()]
```

Returns the list of known number system names.

### Returns

* A list of atoms representing all known number system names.

### Examples

    iex> :latn in Localize.Number.System.known_number_systems()
    true

# `number_system_digits`

```elixir
@spec number_system_digits(system_name()) ::
  {:ok, String.t()} | {:error, Exception.t()}
```

Returns the digit string for a numeric number system.

### Arguments

* `system_name` is a number system name atom (e.g., `:latn`).

### Returns

* `{:ok, digits}` where `digits` is a 10-character string.

* `{:error, exception}` if the system is not numeric or unknown.

### Examples

    iex> Localize.Number.System.number_system_digits(:latn)
    {:ok, "0123456789"}

# `number_system_digits!`

```elixir
@spec number_system_digits!(system_name()) :: String.t()
```

Same as `number_system_digits/1` but raises on error.

### Arguments

* `system_name` is a number system name atom.

### Returns

* A string of the number system's digits.

### Raises

* Raises an exception if the system is not numeric or unknown.

### Examples

    iex> Localize.Number.System.number_system_digits!(:latn)
    "0123456789"

# `number_system_for`

```elixir
@spec number_system_for(
  Localize.LanguageTag.t() | atom() | String.t(),
  system_name() | system_type()
) :: {:ok, map()} | {:error, Exception.t()}
```

Returns the actual number system definition from a system name
and locale.

Resolves a system type or name to the full system definition
containing `:type` and `:digits` or `:rules`.

### Arguments

* `locale` is a locale identifier atom, string, or a
  `t:Localize.LanguageTag.t/0` struct.

* `system_name` is a number system name or type atom.

### Returns

* `{:ok, system_definition}` with the system's type and digits/rules.

* `{:error, exception}` if the system cannot be resolved.

### Examples

    iex> Localize.Number.System.number_system_for(:en, :default)
    {:ok, %{type: :numeric, digits: "0123456789"}}

    iex> Localize.Number.System.number_system_for(:th, :thai)
    {:ok, %{type: :numeric, digits: "๐๑๒๓๔๕๖๗๘๙"}}

# `number_system_from_locale`

```elixir
@spec number_system_from_locale(Localize.LanguageTag.t() | atom() | String.t()) ::
  {:ok, system_name()} | {:error, Exception.t()}
```

Returns the default number system from a language tag or locale.

If the language tag has a `-u-nu-` extension, that number system
is returned. Otherwise, the default number system for the locale
is returned.

### Arguments

* `locale` is a locale identifier atom, string, or a
  `t:Localize.LanguageTag.t/0` struct.

### Returns

* A number system name atom.

* `{:error, exception}` if the locale data cannot be loaded.

### Examples

    iex> Localize.Number.System.number_system_from_locale("en-US")
    {:ok, :latn}

# `number_system_names_for`

```elixir
@spec number_system_names_for(Localize.LanguageTag.t() | atom() | String.t()) ::
  {:ok, [system_name()]} | {:error, Exception.t()}
```

Returns the unique number system names available for a locale.

### Arguments

* `locale` is a locale identifier atom, string, or a
  `t:Localize.LanguageTag.t/0` struct.

### Returns

* `{:ok, names}` where `names` is a list of unique
  number system name atoms.

* `{:error, exception}` if the locale data cannot be loaded.

### Examples

    iex> Localize.Number.System.number_system_names_for(:en)
    {:ok, [:latn]}

# `number_system_names_for!`

```elixir
@spec number_system_names_for!(Localize.LanguageTag.t() | atom() | String.t()) :: [
  system_name()
]
```

Same as `number_system_names_for/1` but raises on error.

### Arguments

* `locale` is a locale identifier atom, string, or a
  `t:Localize.LanguageTag.t/0` struct.

### Returns

* A list of unique number system name atoms.

### Raises

* Raises an exception if the locale data cannot be loaded.

### Examples

    iex> Localize.Number.System.number_system_names_for!(:th)
    [:latn, :thai]

# `number_systems`

```elixir
@spec number_systems() :: map()
```

Returns a map of all CLDR number systems and their definitions.

Each system map contains `:type` (`:numeric` or `:algorithmic`)
and either `:digits` (for numeric systems) or `:rules` (for
algorithmic systems).

### Returns

* A map of `%{system_name => system_definition}`.

### Examples

    iex> Localize.Number.System.number_systems()[:latn]
    %{type: :numeric, digits: "0123456789"}

# `number_systems_for`

```elixir
@spec number_systems_for(Localize.LanguageTag.t() | atom() | String.t()) ::
  {:ok, map()} | {:error, Exception.t()}
```

Returns the number system types mapped to number system names
for a locale.

### Arguments

* `locale` is a locale identifier atom, string, or a
  `t:Localize.LanguageTag.t/0` struct.

### Returns

* `{:ok, systems_map}` where `systems_map` is a map like
  `%{default: :latn, native: :latn}`.

* `{:error, exception}` if the locale data cannot be loaded.

### Examples

    iex> Localize.Number.System.number_systems_for(:en)
    {:ok, %{default: :latn, native: :latn}}

# `number_systems_for!`

```elixir
@spec number_systems_for!(Localize.LanguageTag.t() | atom() | String.t()) :: map()
```

Same as `number_systems_for/1` but raises on error.

### Arguments

* `locale` is a locale identifier atom, string, or a
  `t:Localize.LanguageTag.t/0` struct.

### Returns

* A map of number system types to names.

### Raises

* Raises an exception if the locale data cannot be loaded.

### Examples

    iex> Localize.Number.System.number_systems_for!(:en)
    %{default: :latn, native: :latn}

# `numeric_systems`

```elixir
@spec numeric_systems() :: map()
```

Returns a map of number systems that have their own digit
character representations.

### Returns

* A map of `%{system_name => %{type: :numeric, digits: String.t()}}`.

### Examples

    iex> Localize.Number.System.numeric_systems()[:thai]
    %{type: :numeric, digits: "๐๑๒๓๔๕๖๗๘๙"}

# `system_name_from`

```elixir
@spec system_name_from(
  system_name() | system_type(),
  Localize.LanguageTag.t() | atom() | String.t()
) :: {:ok, system_name()} | {:error, Exception.t()}
```

Resolves a number system name from a system type or direct name
for a locale.

Number systems can be referenced by type (`:default`, `:native`,
etc.) or directly by name (`:latn`, `:arab`, etc.). This function
resolves the reference to the actual system name.

Following TR35 and ICU, any numbering system in the CLDR inventory
is accepted by name even when the locale does not list it — the
`-u-nu-` locale keyword and the `:number_system` formatting option
may request, for example, `:thai` digits in an `:en` locale. Only
genuinely unknown system names return an error.

### Arguments

* `system_name` is a number system name atom or type atom.

* `locale` is a locale identifier atom, string, or a
  `t:Localize.LanguageTag.t/0` struct.

### Returns

* `{:ok, system_name}` where `system_name` is an atom.

* `{:error, exception}` if the system name cannot be resolved.

### Examples

    iex> Localize.Number.System.system_name_from(:default, :en)
    {:ok, :latn}

    iex> Localize.Number.System.system_name_from(:thai, :th)
    {:ok, :thai}

    iex> Localize.Number.System.system_name_from(:thai, :en)
    {:ok, :thai}

# `system_name_from!`

```elixir
@spec system_name_from!(
  system_name() | system_type(),
  Localize.LanguageTag.t() | atom() | String.t()
) :: system_name()
```

Same as `system_name_from/2` but raises on error.

### Arguments

* `system_name` is a number system name atom or type atom.

* `locale` is a locale identifier atom, string, or a
  `t:Localize.LanguageTag.t/0` struct.

### Returns

* A number system name atom.

### Raises

* Raises an exception if the system name cannot be resolved.

### Examples

    iex> Localize.Number.System.system_name_from!(:native, :ar)
    :arab

# `to_system`

```elixir
@spec to_system(number() | Decimal.t(), system_name()) ::
  {:ok, String.t()} | {:error, Exception.t()}
```

Converts a number into the representation of a non-Latin
number system.

For numeric systems, transliterates the digits. For algorithmic
systems, formats the number using the system's RBNF rules.

### Arguments

* `number` is an integer, float, or Decimal.

* `system_name` is a number system name atom.

### Returns

* `{:ok, string}` with the number in the requested number system.

* `{:error, exception}` if the system is unknown.

### Examples

    iex> Localize.Number.System.to_system(123, :thai)
    {:ok, "๑๒๓"}

    iex> Localize.Number.System.to_system(1234, :roman)
    {:ok, "MCCXXXIV"}

# `to_system!`

```elixir
@spec to_system!(number() | Decimal.t(), system_name()) :: String.t()
```

Same as `to_system/2` but raises on error.

### Arguments

* `number` is an integer, float, or Decimal.

* `system_name` is a number system name atom.

### Returns

* A string with the number in the requested number system.

### Raises

* Raises an exception if the system is unknown.

### Examples

    iex> Localize.Number.System.to_system!(123, :deva)
    "१२३"

---

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