Curated library of 38 atomic skills, 7 personas, and 1 orchestrator for Elixir and Phoenix development. Organized by category: fundamentals, phoenix, database, testing, auth, infrastructure, quality, security, integrations, tooling, frameworks, personas, and orchestration. Covers core Elixir patterns, Phoenix LiveView, Ecto, OTP, Oban, testing, security, deployment, real-time, and modern tooling (Req, Swoosh, Cachex, Broadway, Ash).
73
91%
Does it follow best practices?
Impact
—
No eval scenarios have been run
Advisory
Suggest reviewing before use
Gettext is the standard internationalization library for Elixir/Phoenix applications.
gettext/1, dgettext/2, or ngettext/3 in templates, LiveView, and controllersmix gettext.extract --merge to generate/update .pot and .po files.po files — confirm new msgid entries appear with empty msgstr valuesmsgstr values for each target localeGettext.put_locale/2dgettext("errors", "Not found") keeps error strings in a separate .po file from default content# mix.exs
defp deps do
[
{:gettext, "~> 0.26"}
]
end# lib/my_app_web/gettext.ex
defmodule MyAppWeb.Gettext do
use Gettext.Backend, otp_app: :my_app
end<h1><%= gettext("Welcome to our site") %></h1>
<p>
<%= gettext("You have %{count} new messages", count: @message_count) %>
</p>
<%# Pluralization: pass count as both the integer and a binding %>
<%= ngettext("There is %{count} item", "There are %{count} items", @item_count, count: @item_count) %>defmodule MyAppWeb.HomeLive do
use MyAppWeb, :live_view
import MyAppWeb.Gettext
@impl true
def mount(_params, session, socket) do
locale = session["locale"] || "en"
Gettext.put_locale(MyAppWeb.Gettext, locale)
{:ok, assign(socket, :greeting, gettext("Hello!"))}
end
enddefmodule MyAppWeb.PageController do
use MyAppWeb, :controller
import MyAppWeb.Gettext
def index(conn, _params) do
message = gettext("Welcome to %{app_name}", app_name: "MyApp")
render(conn, :index, message: message)
end
endpriv/gettext/
├── en/LC_MESSAGES/
│ ├── default.po # Default domain
│ └── errors.po # Errors domain
├── es/LC_MESSAGES/
│ ├── default.po
│ └── errors.po
└── default.pot # Template file# priv/gettext/es/LC_MESSAGES/default.po
msgid "Welcome to our site"
msgstr "Bienvenido a nuestro sitio"
msgid "You have %{count} new message"
msgid_plural "You have %{count} new messages"
msgstr[0] "Tienes %{count} mensaje nuevo"
msgstr[1] "Tienes %{count} mensajes nuevos"# Extract new strings to .pot files
mix gettext.extract
# Merge .pot files into .po files
mix gettext.merge priv/gettext
# Extract and merge in one step
mix gettext.extract --mergeValidate: After extraction, open the relevant .po files and confirm new msgid entries appear with empty msgstr values. Fill in translations before deploying.
# lib/my_app_web/plugs/set_locale.ex
defmodule MyAppWeb.Plugs.SetLocale do
import Plug.Conn
@supported_locales ~w(en es fr de)
def init(opts), do: opts
def call(conn, _opts) do
locale =
get_locale_from_params(conn) ||
get_locale_from_session(conn) ||
"en"
Gettext.put_locale(MyAppWeb.Gettext, locale)
conn
end
defp get_locale_from_params(conn), do: validate(conn.params["locale"])
defp get_locale_from_session(conn), do: validate(get_session(conn, "locale"))
defp validate(locale) when locale in @supported_locales, do: locale
defp validate(_), do: nil
endRegister it in the router pipeline:
pipeline :browser do
# ...
plug MyAppWeb.Plugs.SetLocale
enddefmodule MyAppWeb.PageTest do
use MyAppWeb.ConnCase
test "renders translated welcome message", %{conn: conn} do
Gettext.put_locale(MyAppWeb.Gettext, "es")
conn = get(conn, ~p"/")
assert html_response(conn, 200) =~ "Bienvenido"
end
end