Localize.Message (Localize v0.25.0)

Copy Markdown View Source

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

Summary

Functions

Formats a message into a canonical form.

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

Format an MF2 message into a string.

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

Format an MF2 message into an iolist.

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

Returns the Jaro distance between two messages.

Returns the Jaro distance between two messages or raises.

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

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

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

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, String.t()}

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

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]