Locale-aware formatting for LFE, backed by Localize.
The localize module wraps Localize so LFE code can format numbers, currencies, dates, times, units, lists and MessageFormat 2 messages with full CLDR locale awareness — while speaking LFE's own idioms: charlists, atoms, Erlang date/time tuples and lisp-case option keys.
Because LFE compiles to the BEAM, there is no bridge or sandbox here — every localize:* call is a direct call into Localize. This library exists purely for ergonomics: it gives lispers (localize:currency 1234.56 "EUR") instead of ('Elixir.Localize.Number':to_string 1234.56 (list #(currency #"EUR"))), and it does the charlist/binary/atom coercion Localize expects.
Add to your rebar.config. Localize is an Elixir package, so LFE projects pull it through rebar_mix:
{plugins, [rebar3_lfe, rebar_mix]}.
{provider_hooks,
[{post, [{compile, {mix, consolidate_protocols}}]}]}.
{deps,
[{localize_lfe, "0.1.0"}]}.(localize:number 1234.5) ; #"1,234.5"
(localize:currency 1234.56 "EUR" (list #(locale de))) ; #"1.234,56 €"
(localize:percent 0.56) ; #"56%"
(localize:date #(2025 7 10) (list #(format long))) ; #"July 10, 2025"
(localize:date "2025-07-10") ; #"Jul 10, 2025"
(localize:relative -3 'day) ; #"3 days ago"
(localize:unit 42 "kilometer" (list #(format short))) ; #"42 km"
(localize:list (list "apple" "banana" "cherry")) ; #"apple, banana, and cherry"
(localize:territory-name "AU") ; #"Australia"
(localize:language-name "de") ; #"German"-
Strings may be charlists (
"USD") or binaries (#"USD") — both are coerced to what Localize wants. -
Dates and times accept an Erlang tuple (
#(2025 7 10),#(14 30 0)) or an ISO 8601 string. -
Option keys are lisp-case atoms (
fractional-digits,number-system) and are translated to Localize's snake_case. Values forformat/stylemay be atoms ('percent) or strings. -
Locales are atoms (
de) or strings ("en-AU").
(set mf2 #".input {$count :integer}\n.match $count\n one {{{$count} item}}\n * {{{$count} items}}")
(localize:message mf2 (map #"count" 1)) ; #"1 item"
(localize:message mf2 (map #"count" 5)) ; #"5 items"Every function returns a binary and, on any error — an unknown locale, an unparseable date, a bogus territory code — falls back to a safe rendering of its input rather than raising. Display-name codes resolve only to already-existing atoms, so a bad code can never grow the atom table. There is no error return to branch on.
Only the en locale ships with Localize. Install the locales you serve once, at build time, from a checkout of Localize:
mix localize.download_locales de fr jaA call for a locale that has not been installed formats with the root locale rather than raising.
rebar3 compile
rebar3 as test lfe ltest
rebar3 dialyzerApache-2.0. See LICENSE.md.