Resolves which locale a message should be rendered in for a given recipient.
Outbound messages (email, and the external notification channels) render on a background or request process that has no meaningful Gettext locale of its own — the sender's locale is not the recipient's. This module is the single answer to "whose language is this message in".
Where the preference lives
A user's dialect preference is stored full ("en-GB", "pt-BR") in
custom_fields["preferred_locale"], written by
PhoenixKit.Users.Auth.update_user_locale_preference/2 from the language
switcher. Absent means the user never chose one.
Two consumers, two shapes
for_rendering/1— for template lookup. Returns the full dialect and nevernil, falling back to the site's content language and then"en". Template resolution does its own dialect→base narrowing ("en-GB" is tried before "en"), so handing it the dialect strictly beats pre-truncating.base/1— for Gettext, which keys on base codes and treatsnilas "leave the current locale alone".
Installing it
in_locale/2 runs a function with a locale installed on the process, which is
how a Gettext-backed default reaches the right language: these render on a
background worker or on behalf of another user, so the locale arrives as a
value rather than being ambient. nil means "leave the current locale alone"
— what a screen rendering for its own viewer wants.
Failure
for_rendering/1 is total. The site default is read through
PhoenixKit.Settings, which can raise on an unowned checkout or exit on a
dead pool; both are caught and answered with "en". An unreachable database
must degrade a message to English, never fail the send — this is the path
PhoenixKit.Users.LoginAlerts calls during sign-in.
Summary
Functions
The recipient's preference as a base language code, or nil.
The locale to render a template in for recipient. Never nil.
Runs fun with locale installed on the process, restoring it afterwards.
The recipient's stored dialect preference, or nil when they have none.
Functions
The recipient's preference as a base language code, or nil.
For Gettext, which keys on base codes; nil means "no preference, leave the
current locale alone".
iex> alias PhoenixKit.Utils.RecipientLocale
iex> RecipientLocale.base(%{custom_fields: %{"preferred_locale" => "pt-BR"}})
"pt"
The locale to render a template in for recipient. Never nil.
Preference → the site's content language → "en".
iex> alias PhoenixKit.Utils.RecipientLocale
iex> RecipientLocale.for_rendering(%{custom_fields: %{"preferred_locale" => "uk"}})
"uk"
Runs fun with locale installed on the process, restoring it afterwards.
A nil locale runs fun untouched, so a caller with no recipient preference
keeps whatever locale is already in force.
iex> alias PhoenixKit.Utils.RecipientLocale
iex> RecipientLocale.in_locale(nil, fn -> :ran end)
:ran
The recipient's stored dialect preference, or nil when they have none.
Accepts anything: a %User{}, a plain map, or a bare email string (used by
the magic-link registration path, where no account exists yet).
iex> alias PhoenixKit.Utils.RecipientLocale
iex> RecipientLocale.preferred(%{custom_fields: %{"preferred_locale" => "en-GB"}})
"en-GB"
iex> RecipientLocale.preferred("someone@example.com")
nil