Internationalization (i18n)
Copy MarkdownAurora UIX ships with built-in internationalization support through the Gettext library. All labels, error messages, and UI strings generated by the framework pass through a configurable Gettext backend, so your application can be translated into any language without touching library source code.
The default backend is Aurora.Uix.GettextBackend. See its module documentation for the full
list of compile-time options and callback details.
How it works
Every module that needs to translate a string uses Aurora.Uix.Gettext, a thin __using__ macro
that wires the configured backend into the calling module:
defmodule MyAppWeb.SomeComponent do
use Aurora.Uix.Gettext # injects gettext/1, dgettext/2, dt/1, …
endAt translation time Gettext looks up the locale and domain in the compiled .po files. When no
translation is found, the call is forwarded to the backend's handle_missing_* callbacks, which
Aurora UIX uses to:
- Optionally emit a
Logger.warningso missing strings are visible during development. - Optionally write a stub entry to the matching
.potfile so translators always have an up-to-date template. - Return the English source string as a safe fallback so the UI never shows an empty field.
Configuration
Recommended: set a Gettext domain
It is strongly recommended to set :gettext_domain so that Aurora UIX strings are stored in their
own Gettext domain, separate from your application's default domain. Without this, running
mix gettext.merge can intermix or overwrite Aurora UIX translations with your own strings.
# config/config.exs
config :aurora_uix, gettext_domain: "aurora_uix"This setting takes effect at compile time — it affects both the runtime dt/1 macro (which
emits dgettext("aurora_uix", msgid) instead of gettext(msgid)) and the compile-time form label
generation, so all Aurora UIX strings end up in priv/gettext/aurora_uix.po rather than the
default default.po.
Development settings
The following keys are read by Aurora.Uix.GettextBackend at compile time. They have no
effect if you replace the backend with a custom module — a custom backend must implement the
equivalent behaviour itself.
# config/dev.exs — recommended settings for local development
config :aurora_uix,
# Write missing-translation stubs to .pot files at runtime.
gettext_pot_path: "priv/gettext",
# Emit Logger.warning for every missing translation (off by default).
gettext_show_warnings?: true| Key | Type | Default | Description |
|---|---|---|---|
:gettext_pot_path | String.t() | nil | nil | Directory where .pot files are written. When nil or omitted, no file I/O occurs. |
:gettext_show_warnings? | boolean() | false | Emit Logger.warning for missing translations. Warnings are suppressed by default. |
For production, omit both keys so no file I/O nor any gettext message happens at runtime.
Custom backend
You can replace the default backend with your own module. Be aware that doing so loses the
POT file generation and warning emission — those are implemented inside
Aurora.Uix.GettextBackend. A custom backend must re-implement any behaviour it needs.
Configure the replacement via the application environment:
config :aurora_uix, gettext_backend: MyApp.CustomGettextBackendOr per-module via the :backend option:
use Aurora.Uix.Gettext, backend: MyApp.CustomGettextBackendSee Aurora.Uix.Gettext for the full backend resolution order.
Example — CI-only strict backend (raises on any missing translation):
defmodule MyApp.StrictGettextBackend do
use Gettext.Backend, otp_app: :my_app
@impl true
def handle_missing_translation(_locale, _domain, _msgctxt, msgid, _bindings) do
raise "Missing translation for: #{msgid}"
end
@impl true
def handle_missing_plural_translation(_locale, _domain, _msgctxt, msgid, _msgid_plural, _n, _bindings) do
raise "Missing plural translation for: #{msgid}"
end
@impl true
def handle_missing_bindings(exception, _incomplete) do
raise exception
end
endThis pattern is useful in CI to catch untranslated strings early. In development and production, prefer the default backend so the UI degrades gracefully.
Automatic .pot file generation
When gettext_pot_path is configured, Aurora.Uix.GettextBackend appends a stub entry to the
appropriate .pot file the first time a missing translation is encountered at runtime. This means
you can run your dev server, exercise the UI, and then merge the stubs into your .po files —
no manual editing required.
The generated stubs follow standard .pot format:
# Generated by Aurora Uix
msgid "First name"
msgstr ""
msgid "Items"
msgid_plural "Items"
msgstr[0] ""
msgstr[1] ""The backend deduplicates: if an msgid already appears in the file it is not appended again.
Once you have exercised the UI, merge the generated stubs into your locale's .po file with:
mix gettext.merge priv/gettext --locale es
See the Gettext merge documentation for the full set of options (locale filtering, fuzzy matching, etc.).
Translation workflow
A typical development workflow:
- Configure
gettext_domain,gettext_pot_path, andgettext_show_warnings?: trueinconfig/dev.exs. - Start the dev server and browse the pages that use Aurora UIX-generated UI.
- Run
mix gettext.merge priv/gettext --locale <locale>to pull the generated stubs into your.pofiles. - Fill in
msgstrvalues for each locale. - Recompile — translations are now active.
Locale selection
Aurora UIX does not manage the active locale — that is the responsibility of the host application.
Use the standard Gettext locale mechanism in your Plug pipeline or LiveView on_mount:
# In a Plug / router pipeline
plug :put_locale
defp put_locale(conn, _opts) do
locale = get_session(conn, :locale) || "en"
Gettext.put_locale(locale)
conn
endRelated guides
- Customizing & Extending Aurora UIX — the central customization hub
Aurora.Uix.GettextBackend— default backend with POT generation and warning controlAurora.Uix.Gettext—__using__macro that wires the backend into any module- Gettext documentation