Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

2 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

localize_lfe

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.

Installation

Elixir must be installed on your system. Localize is an Elixir package, so building it requires the Elixir compiler even though your own code is LFE. Erlang/OTP alone is not enough.

localize_lfe is not yet published to hex, so depend on it from git:

{plugins, [rebar3_lfe, rebar_mix]}.

{provider_hooks,
 [{post, [{compile, {mix, consolidate_protocols}}]}]}.

{deps,
 [{localize_lfe,
   {git, "https://github.com/elixir-localize/localize_lfe.git", {branch, "main"}}}]}.

The rebar_mix plugin is what compiles the Elixir dependency and consolidates its protocols.

Usage

(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"

Inputs are LFE-idiomatic

  • 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 for format/style may be atoms ('percent) or strings.

  • Locales are atoms (de) or strings ("en-AU").

Pluralisation with MessageFormat 2

(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"

Safety

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.

Locale data

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 ja

A call for a locale that has not been installed formats with the root locale rather than raising.

Development

rebar3 compile
rebar3 as test lfe ltest
rebar3 dialyzer

License

Apache-2.0. See LICENSE.md.

About

Localize bindings for LFE (Lisp flavoured Erlang)

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages