erli18n_elli (erli18n v0.6.0)

Copy Markdown View Source

Optional Elli middleware that negotiates the request locale and sets it before the handler runs — the Elli counterpart to erli18n_cowboy.

elli is an optional dependency (declared via optional_applications, like telemetry): erli18n does not require it and the published package still builds on kernel + stdlib alone. This module only runs when an Elli application installs it via elli_middleware, so Elli is present whenever the code runs. elli_request is therefore an externally-provided runtime module, not a build dependency (the same situation as the rebar3 host API in rebar3_erli18n_host): its calls are confined to a small seam (see the "elli_request seam" section below) and the default build's xref/dialyzer/eqwalizer are kept clean by suppressions scoped to exactly those external edges (-ignore_xref + the root {xref_ignores,...}, a function-scoped -dialyzer({no_unknown,...}), and a % elp:ignore W0017 per call site). Every other call stays fully checked.

Install it

Add elli to your deps (erli18n does not pull it in), then list erli18n_elli in the elli_middleware mods ahead of your real handler. Per-middleware options are the second element of the {Mod, Args} pair:

application:ensure_all_started(erli18n),
{ok, _} = erli18n_server:ensure_loaded(my_domain, <<"pt_BR">>, "priv/.../my_domain.po"),

Config = [
    {mods, [
        {erli18n_elli, #{cookie_name => <<"locale">>, query_param => <<"lang">>}},
        {my_callback, []}
    ]}
],
elli:start_link([{callback, elli_middleware}, {callback_args, Config}, {port, 8080}]).

It runs as an elli_middleware pre-processor: preprocess/2 sets the locale on the request process before your handler. The module deliberately exports only preprocess/2, not handle/2: elli_middleware skips the handle phase for any mod that does not export handle/2 (its ?IF_NOT_EXPORTED guard), so this middleware never intercepts a real handler. A handle/2 -> ignore clause would be unreachable dead code.

Options (the Args map, all optional)

KeyDefaultMeaning
sources[query, cookie, header]precedence order, highest first
query_param<<"locale">>query-string parameter carrying a locale
cookie_name<<"locale">>cookie carrying a locale
availableerli18n:loaded_locales/0the authoritative supported-locale set
defaulterli18n:default_locale/0fallback when nothing matches
set_logger_metadatatruealso set logger process metadata #{locale => L}

Default precedence is query > cookie > Accept-Language header > default, and available/default are resolved per request. Negotiation, canonicalization, and cookie parsing are delegated to erli18n_http / erli18n_negotiate. The path source is Cowboy-only (Elli exposes the path as raw segments); listing it here is a harmless no-op.

Per-process locale, the cross-process hazard, and Phoenix interop

Identical to the Cowboy adapter: Elli runs the middleware and handler in one request process, so the locale set here is visible to the handler, but it is not inherited across a spawn (worker pools, gen_servers, Task-style spawns). See erli18n_cowboy for the full discussion of the hazard, the mitigations (capture-and-re-set, pass explicitly, propagate logger metadata), and the Phoenix / mixed-Elixir interop note — all of which apply unchanged here.

References

Summary

Types

Per-middleware options (the Args map). An alias of the framework-agnostic erli18n_http_apply:options(): the Elli adapter adds no adapter-specific keys (the path source is Cowboy-only — see the module docs). Every key is optional.

Stands in for the elli request record (a tuple). A module-local alias so the default kernel + stdlib build needs no elli dependency.

Functions

elli_middleware pre-processor: negotiates the locale from the request, sets it on the request process (and, by default, in logger metadata), and returns the request unchanged so the chain continues.

Types

options()

-type options() :: erli18n_http_apply:options().

Per-middleware options (the Args map). An alias of the framework-agnostic erli18n_http_apply:options(): the Elli adapter adds no adapter-specific keys (the path source is Cowboy-only — see the module docs). Every key is optional.

req()

-type req() :: tuple().

Stands in for the elli request record (a tuple). A module-local alias so the default kernel + stdlib build needs no elli dependency.

Functions

preprocess/2

-spec preprocess(req(), term()) -> req().

elli_middleware pre-processor: negotiates the locale from the request, sets it on the request process (and, by default, in logger metadata), and returns the request unchanged so the chain continues.

Req is the Elli request record; Args is the per-middleware options map (see the module docs). The -behaviour(elli_handler) attribute is omitted on purpose so the module compiles warning-free (under warnings_as_errors) when Elli is absent; the contract is exercised by the test suite against the real framework.