Framework.I18n (Framework v0.5.0)
View SourceInternationalization (i18n) support for Framework.
Provides locale resolution, translation helpers, and i18n infrastructure for all framework components including:
- Transaction DSL operations (pure translation helpers)
- Effects system (locale-aware email/webhook dispatch)
- Template system (locale-specific template resolution)
- AppSpec routes (optional locale-prefixed routing)
Configuration
config :framework, Framework.I18n,
default_locale: "en-US",
supported_locales: ["en-US", "es-ES", "fr-FR", "de-DE"],
gettext_backend: Framework.I18n.GettextLocale Resolution Priority
- Explicit
localein operation input - User preference from
ctx.user.locale(if available) - Session locale from
ctx.session.locale(if available) - Accept-Language header from
ctx.headers["accept-language"] - Default locale from configuration
Usage in Transaction DSL
use Framework.Transaction
operation :greet_user do
plan fn input, ctx ->
user = get(:users, input.user_id)
result = compute fn ->
%{
# Pure translation - no I/O, reads from ctx
greeting: Framework.I18n.t(ctx, "user.greeting", name: user.name),
title: Framework.I18n.t(ctx, "dashboard.title")
}
end
return result
end
endUsage in Effects
effect :email, "welcome",
to: user.email,
locale: ctx.locale # Locale flows to effectGettext Integration
Framework uses Gettext for compile-time translations. Translation files
are stored in priv/gettext/<locale>/LC_MESSAGES/:
priv/gettext/
en-US/LC_MESSAGES/
default.po
errors.po
es-ES/LC_MESSAGES/
default.po
errors.po
Summary
Functions
Get the default locale from configuration.
Check if a locale is supported.
Parse Accept-Language header and return best matching supported locale.
Resolve locale from multiple sources with priority ordering.
Get list of supported locales from configuration.
Translate a message key with optional bindings.
Translate a message key with pluralization support.
Validate and normalize a locale string.
Functions
Get the default locale from configuration.
Examples
iex> Framework.I18n.get_default_locale()
"en-US"
Check if a locale is supported.
Examples
iex> Framework.I18n.locale_supported?("en-US")
true
iex> Framework.I18n.locale_supported?("invalid")
false
Parse Accept-Language header and return best matching supported locale.
Examples
iex> Framework.I18n.parse_accept_language_header("es-ES,es;q=0.9,en;q=0.8")
"es-ES"
iex> Framework.I18n.parse_accept_language_header("fr-FR,fr;q=0.9")
"fr-FR"
iex> Framework.I18n.parse_accept_language_header("invalid")
"en-US" # falls back to default
Resolve locale from multiple sources with priority ordering.
Priority Order
- Explicit input locale
- User preference (ctx.user.locale)
- Session locale (ctx.session.locale)
- Accept-Language header
- Default locale
Examples
iex> Framework.I18n.resolve_locale(%{locale: "es-ES"}, %{})
"es-ES"
iex> Framework.I18n.resolve_locale(%{}, %{user: %{locale: "fr-FR"}})
"fr-FR"
iex> Framework.I18n.resolve_locale(%{}, %{})
"en-US" # default locale
Get list of supported locales from configuration.
Examples
iex> Framework.I18n.supported_locales()
["en-US", "es-ES", "fr-FR", "de-DE"]
Translate a message key with optional bindings.
This is a pure function that reads locale from context and delegates to the configured Gettext backend. No I/O is performed.
Examples
iex> ctx = %{locale: "en-US"}
iex> Framework.I18n.t(ctx, "user.greeting", name: "Alice")
"Hello, Alice!"
iex> ctx = %{locale: "es-ES"}
iex> Framework.I18n.t(ctx, "user.greeting", name: "Alice")
"¡Hola, Alice!"Arguments
ctx- Context map containing:localekeykey- Translation key (e.g., "user.greeting", "errors.not_found")bindings- Keyword list of variable bindings for interpolation
Translate a message key with pluralization support.
Examples
iex> ctx = %{locale: "en-US"}
iex> Framework.I18n.tn(ctx, "item.count", "item.counts", 1)
"1 item"
iex> Framework.I18n.tn(ctx, "item.count", "item.counts", 5)
"5 items"
Validate and normalize a locale string.
Returns the locale if valid, otherwise returns default locale.
Examples
iex> Framework.I18n.validate_and_normalize_locale("en-US")
"en-US"
iex> Framework.I18n.validate_and_normalize_locale("invalid")
"en-US" # falls back to default