Search documentation of Localize

# Localize.Message (Localize v0.39.0)

Copy Markdown View Source

Implements ICU MessageFormat 2 with functions to parse and interpolate messages.

## Summary

### Types

backend()
bindings()
message()
options()
safe_node()

### Functions

canonical_message(message, options \\ [])

Formats a message into a canonical form.

canonical_message!(message, options \\ [])

Formats a message into a canonical form or raises if the message cannot be parsed.

format(message, bindings \\ %{}, options \\ [])

Format an MF2 message into a string.

format!(message, bindings \\ %{}, options \\ [])

Formats a message and returns the result or raises on error.

format_to_iolist(message, bindings \\ %{}, options \\ [])

Format an MF2 message into an iolist.

format_to_safe_list(message, bindings \\ %{}, options \\ [])

Formats a message into a list of text and markup nodes preserving markup structure.

format_to_safe_list!(message, bindings \\ %{}, options \\ [])

Same as `format_to_safe_list/3` but raises on error.

jaro_distance(message1, message2, options \\ [])

Returns the Jaro distance between two messages.

jaro_distance!(message1, message2, options \\ [])

Returns the Jaro distance between two messages or raises.

to_ansi(message, options \\ [])

Parses an MF2 message and returns it formatted with ANSI colour codes for terminal display.

to_html(message, options \\ [])

Parses an MF2 message and returns it formatted as HTML with per-token `<span>` wrappers for syntax highlighting.

to_tokens(message, options \\ [])

Parses an MF2 message and returns a classified token stream for syntax highlighting.

## Types

# backend()

    @type backend() :: :nif | :elixir

# bindings()

    @type bindings() :: list() | map()

# message()

    @type message() :: binary()

# options()

    @type options() :: Keyword.t()

# safe_node()

    @type safe_node() ::
      {:text, String.t()}
      | {:markup, String.t(), %{required(String.t()) => term()}, [safe_node()]}

## Functions

# canonical_message(message, options \\ [])

    @spec canonical_message(String.t(), Keyword.t()) ::
      {:ok, String.t()} | {:error, Localize.ParseError.t()}

Formats a message into a canonical form.

This allows for messages to be compared directly, or using `jaro_distance/3`.

### Arguments

- `message` is an MF2 message in binary form.

- `options` is a keyword list of options. The default is `[]`.

### Options

- `:trim` determines if the message is trimmed of whitespace before formatting. The default is `true`.

### Returns

- `{:ok, canonical_message}` as a string.

- `{:error, reason}` on parse error.

### Examples

    iex> Localize.Message.canonical_message("{{Hello {$name}!}}")
    {:ok, "{{Hello {$name}!}}"}

# canonical_message!(message, options \\ [])

    @spec canonical_message!(String.t(), Keyword.t()) :: String.t() | no_return()

Formats a message into a canonical form or raises if the message cannot be parsed.

### Arguments

- `message` is an MF2 message in binary form.

- `options` is a keyword list of options. See `canonical_message/2`.

### Returns

- The canonical message as a string.

### Examples

    iex> Localize.Message.canonical_message!("{{Hello {$name}!}}")
    "{{Hello {$name}!}}"

# format(message, bindings \\ %{}, options \\ [])

    @spec format(String.t(), bindings(), options()) ::
      {:ok, String.t()} | {:error, Exception.t()}

Format an MF2 message into a string.

The ICU MessageFormat 2 uses message patterns with variable-element placeholders enclosed in {curly braces}. The argument syntax can include formatting details via annotation functions.

### Arguments

- `message` is an MF2 message string.

- `bindings` is a map or keyword list of arguments that are used to replace placeholders in the message.

- `options` is a keyword list of options.

### Options

- `:locale` is any valid locale name or a `t:Localize.LanguageTag` struct.

- `:trim` determines if the message is trimmed of whitespace before formatting. The default is `false`.

- `:backend` determines which formatting engine to use. Accepts `:nif` or `:elixir`. When set to `:nif`, the ICU NIF is used if available, otherwise falls back to the pure-Elixir interpreter. The default is `:elixir`.

- `:functions` is a map of `%{String.t() => module()}` that registers custom MF2 formatting functions for this call. Each module must implement the `Localize.Message.Function` behaviour. Per-call functions take precedence over application-level functions registered via `config :localize, :mf2_functions`. See `Localize.Message.Function` for details.

### Returns

- `{:ok, formatted_message}` on success.

- `{:error, exception}` where `exception` is a `Localize.BindError` for unbound variables or a `Localize.FormatError` for formatting failures.

### Examples

    iex> Localize.Message.format("{{Hello {$name}!}}", %{"name" => "World"})
    {:ok, "Hello World!"}

# format!(message, bindings \\ %{}, options \\ [])

    @spec format!(String.t(), bindings(), options()) :: String.t() | no_return()

Formats a message and returns the result or raises on error.

Same as `format/3` but returns the formatted string directly or raises an exception.

### Arguments

- `message` is an MF2 message string.

- `bindings` is a map or keyword list of arguments.

- `options` is a keyword list of options. See `format/3`.

### Returns

- The formatted string.

### Examples

    iex> Localize.Message.format!("{{Hello {$name}!}}", %{"name" => "World"})
    "Hello World!"

# format_to_iolist(message, bindings \\ %{}, options \\ [])

    @spec format_to_iolist(String.t(), bindings(), options()) ::
      {:ok, list(), list(), list()}
      | {:error, list(), list(), list()}
      | {:error, Localize.ParseError.t()}
      | {:format_error, Localize.Message.Interpreter.format_error_payload()}

Format an MF2 message into an iolist.

### Arguments

- `message` is an MF2 message string.

- `bindings` is a map or keyword list of arguments that are used to replace placeholders in the message.

- `options` is a keyword list of options.

### Options

- `:locale` is any valid locale name or a language tag struct.

- `:trim` determines if the message is trimmed of whitespace before formatting. The default is `false`.

### Returns

- `{:ok, iolist, bound, unbound}` on success.

- `{:error, iolist, bound, unbound}` when bindings are missing.

- `{:format_error, reason}` on format error.

### Examples

    iex> Localize.Message.format_to_iolist("{{Hello {$name}!}}", %{"name" => "World"})
    {:ok, ["Hello ", "World", "!"], ["name"], []}

# format_to_safe_list(message, bindings \\ %{}, options \\ [])

    @spec format_to_safe_list(String.t(), bindings(), options()) ::
      {:ok, [safe_node()]} | {:error, Exception.t()}

Formats a message into a list of text and markup nodes preserving markup structure.

Unlike `format/3`, which strips markup tags from the output, this function returns a nested tree of `{:text, String.t()}` and `{:markup, name, options, children}` tuples. This is the foundation for HTML/HEEX renderers in companion packages.

The caller is responsible for turning markup nodes into actual output (HTML elements, function components, etc.). Text nodes are returned as raw strings — escaping is the renderer's responsibility.

### Arguments

- `message` is an MF2 message in binary form.

- `bindings` is a map or keyword list of variable bindings. The default is `%{}`.

- `options` is a keyword list of options. The default is `[]`.

### Options

- `:locale` is a locale name or a `Localize.LanguageTag.t/0`. The default is `Localize.get_locale/0`.

- `:trim` determines if the message is trimmed of whitespace before formatting. The default is `false`.

- `:functions` is a map of custom MF2 function modules. See `Localize.Message.Function`.

### Returns

- `{:ok, nodes}` on success, where `nodes` is a list of `safe_node()` tuples.

- `{:error, exception}` on parse or format error, including unbalanced markup or unbound variables.

### Examples

    iex> Localize.Message.format_to_safe_list(
    ...>   "Hello {$name}, click {#link href=|/home|}here{/link}!",
    ...>   %{"name" => "Kip"}
    ...> )
    {:ok, [
      {:text, "Hello Kip, click "},
      {:markup, "link", %{"href" => "/home"}, [{:text, "here"}]},
      {:text, "!"}
    ]}

    iex> Localize.Message.format_to_safe_list("Just text")
    {:ok, [{:text, "Just text"}]}

    iex> Localize.Message.format_to_safe_list("{#br/}")
    {:ok, [{:markup, "br", %{}, []}]}

# format_to_safe_list!(message, bindings \\ %{}, options \\ [])

    @spec format_to_safe_list!(String.t(), bindings(), options()) :: [safe_node()]

Same as `format_to_safe_list/3` but raises on error.

# jaro_distance(message1, message2, options \\ [])

    @spec jaro_distance(String.t(), String.t(), Keyword.t()) ::
      {:ok, float()} | {:error, Localize.ParseError.t()}

Returns the Jaro distance between two messages.

This allows for fuzzy matching of messages which can be helpful when a message string is changed but the semantics remain the same.

### Arguments

- `message1` is an MF2 message in binary form.

- `message2` is an MF2 message in binary form.

- `options` is a keyword list of options. The default is `[]`.

### Options

- `:trim` determines if the message is trimmed of whitespace before formatting. The default is `false`.

### Returns

- `{:ok, distance}` where `distance` is a float between 0.0 and 1.0.

- `{:error, reason}` on parse error.

### Examples

    iex> Localize.Message.jaro_distance("{{Hello}}", "{{Hello}}")
    {:ok, 1.0}

# jaro_distance!(message1, message2, options \\ [])

    @spec jaro_distance!(String.t(), String.t(), Keyword.t()) :: float() | no_return()

Returns the Jaro distance between two messages or raises.

Same as `jaro_distance/3` but returns the distance directly.

### Arguments

- `message1` is an MF2 message in binary form.

- `message2` is an MF2 message in binary form.

- `options` is a keyword list of options.

### Returns

- A float distance between 0.0 and 1.0.

### Examples

    iex> Localize.Message.jaro_distance!("{{Hello}}", "{{Hello}}")
    1.0

# to_ansi(message, options \\ [])

    @spec to_ansi(String.t(), Keyword.t()) ::
      {:ok, String.t()} | {:error, Localize.ParseError.t()}

Parses an MF2 message and returns it formatted with ANSI colour codes for terminal display.

### Arguments

- `message` is an MF2 message in binary form.

- `options` is a keyword list.

### Options

- `:trim` — whitespace trim before parse (default `true`).

- `:palette` — a map overriding the default class-to-colour mapping. See `Localize.Message.Formatter.ANSI`.

### Returns

- `{:ok, ansi_string}` on success.

- `{:error, reason}` if the message cannot be parsed.

# to_html(message, options \\ [])

    @spec to_html(String.t(), Keyword.t()) ::
      {:ok, String.t()} | {:error, Localize.ParseError.t()}

Parses an MF2 message and returns it formatted as HTML with per-token `<span>` wrappers for syntax highlighting.

### Arguments

- `message` is an MF2 message in binary form.

- `options` is a keyword list.

### Options

- `:trim` — whitespace trim before parse (default `true`).

- `:standalone` — wraps the output in a `<pre><code>` block (default `false`).

- `:wrapper_tag`, `:wrapper_class`, `:span_tag`, `:class_prefix` — see `Localize.Message.Formatter.HTML` for details.

### Returns

- `{:ok, html}` on success.

- `{:error, reason}` if the message cannot be parsed.

# to_tokens(message, options \\ [])

    @spec to_tokens(String.t(), Keyword.t()) ::
      {:ok, [Localize.Message.Highlighter.token()]}
      | {:error, Localize.ParseError.t()}

Parses an MF2 message and returns a classified token stream for syntax highlighting.

Each token is a `{class, text}` tuple where `class` is one of the atoms documented in `Localize.Message.Highlighter`. Concatenating every token's text yields the canonical MF2 message.

Use this when you want to produce your own rendered output. For HTML or ANSI output, prefer `to_html/2` or `to_ansi/2`.

### Arguments

- `message` is an MF2 message in binary form.

- `options` is a keyword list. The `:trim` option (default `true`) strips leading and trailing whitespace before parsing.

### Returns

- `{:ok, tokens}` where `tokens` is a list of `{class, text}` tuples.

- `{:error, reason}` if the message cannot be parsed.

### Examples

    iex> {:ok, tokens} = Localize.Message.to_tokens("Hello {$name}!")
    iex> Enum.map(tokens, &elem(&1, 0))
    [:text, :punctuation_bracket, :variable, :punctuation_bracket, :text]