Provides Gettext macros with configurable backend support.
This module allows using Gettext macros while supporting a configurable
backend through the :gettext_backend option or application config.
Configuration
Option 1: Pass backend directly (recommended for gettext extraction)
defmodule MyModule do
use MishkaGervaz.Messages, backend: MishkaCmsCore.Gettext
def my_function do
dgettext("mishka_gervaz", "Load More")
end
endOption 2: Use application config (for runtime switching)
config :mishka_gervaz, :gettext_backend, MyAppWeb.GettextThen:
defmodule MyModule do
use MishkaGervaz.Messages
def my_function do
dgettext("mishka_gervaz", "Load More")
end
endTranslation Domain
All MishkaGervaz translations use the mishka_gervaz domain, except the messages a form field
type refuses a value with, which use the errors domain. Translation files should be placed at:
priv/gettext/LOCALE/LC_MESSAGES/mishka_gervaz.po
priv/gettext/LOCALE/LC_MESSAGES/errors.poStrings from the DSL
Every string a resource's mishka_gervaz DSL holds is translated when it is drawn, through
translate_text/1: labels, placeholders, prompts, {label, value} option labels, confirm
messages, empty and error states, notices, headers and footers. A function value is called as
it is and is not translated again. Mark a string with dgettext_noop("mishka_gervaz", "...") so
mix gettext.extract finds it.
Work in another process
A new process has no Gettext locale of its own. Run work whose result holds words through
start_async/4, assign_async/4 or in_caller_locale/1 so it is translated in the locale of
the process that started it.
The same three carry the value of each process dictionary key registered with
carry_process_keys/1, so work that reads what its caller put in the process dictionary — the
tenant a page renders for, say — reads it in the other process too. None is registered by
default.
Summary
Functions
Injects Gettext macros into the using module.
Phoenix.LiveView.assign_async/4, with fun run in the caller's Gettext locales and with its
values for the keys carry_process_keys/1 registered (in_caller_locale/1).
The process dictionary keys carry_process_keys/1 registered, in the order they were first
registered.
Registers process dictionary keys whose values in_caller_locale/1, start_async/4 and
assign_async/4 carry into the work they start, beside the Gettext locales.
Gets the configured Gettext backend at runtime.
Wraps fun, of arity 0 or 1, to run in the Gettext locales of the process that calls this, with
the values it holds for the keys carry_process_keys/1 registered.
Phoenix.LiveView.start_async/4, with fun run in the caller's Gettext locales and with its
values for the keys carry_process_keys/1 registered (in_caller_locale/1).
Translates a string a resource declared in its mishka_gervaz DSL, in the locale of the process
that draws it.
Functions
Injects Gettext macros into the using module.
Options
:backend- The Gettext backend module to use. If not provided, falls back to the:gettext_backendconfig orMishkaGervaz.Gettext.
Usage
# With explicit backend (recommended for extraction)
use MishkaGervaz.Messages, backend: MyApp.Gettext
# With config-based backend
use MishkaGervaz.Messages
@spec assign_async( Phoenix.LiveView.Socket.t(), atom() | [atom()], (-> {:ok, map()} | {:error, term()}), keyword() ) :: Phoenix.LiveView.Socket.t()
Phoenix.LiveView.assign_async/4, with fun run in the caller's Gettext locales and with its
values for the keys carry_process_keys/1 registered (in_caller_locale/1).
@spec carried_process_keys() :: [term()]
The process dictionary keys carry_process_keys/1 registered, in the order they were first
registered.
@spec carry_process_keys([term()]) :: :ok
Registers process dictionary keys whose values in_caller_locale/1, start_async/4 and
assign_async/4 carry into the work they start, beside the Gettext locales.
Call it when the application starts, with the keys its own functions read with Process.get/1.
Registering a key again changes nothing. A key the calling process holds no value for is not
carried, so the other process reads it as unset too.
Examples
MishkaGervaz.Messages.carry_process_keys([{MyApp.Tenant, :current}])
Process.put({MyApp.Tenant, :current}, "acme")
Task.async(MishkaGervaz.Messages.in_caller_locale(fn -> Process.get({MyApp.Tenant, :current}) end))
|> Task.await()
#=> "acme"
Gets the configured Gettext backend at runtime.
Returns the user-configured backend or MishkaGervaz.Gettext as default.
@spec in_caller_locale((-> result) | (arg -> result)) :: (-> result) | (arg -> result) when result: term(), arg: term()
Wraps fun, of arity 0 or 1, to run in the Gettext locales of the process that calls this, with
the values it holds for the keys carry_process_keys/1 registered.
Give the wrapped function to the work another process runs, such as Task.async/1 or
Task.async_stream/3: a new process starts with no locale of its own, so words it translates are
otherwise in the default locale. The locale set with Gettext.put_locale/1 and each one set with
Gettext.put_locale/2 are carried. Both are read when fun is wrapped.
Examples
Gettext.put_locale(MyApp.Gettext, "fa")
Task.async(MishkaGervaz.Messages.in_caller_locale(fn -> Gettext.get_locale(MyApp.Gettext) end))
|> Task.await()
#=> "fa"
@spec start_async(Phoenix.LiveView.Socket.t(), term(), (-> term()), keyword()) :: Phoenix.LiveView.Socket.t()
Phoenix.LiveView.start_async/4, with fun run in the caller's Gettext locales and with its
values for the keys carry_process_keys/1 registered (in_caller_locale/1).
Use it in place of Phoenix.LiveView.start_async/4 wherever the result holds words a person
reads.
Translates a string a resource declared in its mishka_gervaz DSL, in the locale of the process
that draws it.
A binary is looked up in the mishka_gervaz domain of gettext_backend/0: the translation when
the current locale has one, the string itself otherwise. nil and every other value are
returned unchanged, so a function or a number a DSL option held passes through. A string holding
%{...} is returned as it is.
A resource marks a string only its DSL holds with dgettext_noop("mishka_gervaz", "..."), which
returns the English string; MishkaGervaz translates it each time it is drawn.
label dgettext_noop("mishka_gervaz", "Heading")Examples
iex> MishkaGervaz.Messages.translate_text("No translation for this")
"No translation for this"
iex> MishkaGervaz.Messages.translate_text(nil)
nil