Gettext Sigils
An Elixir library that provides a ~t sigil for using Gettext translations with less boilerplate and improved readability:
# before
gettext("Hello, %{name}", name: user.name)
# after
~t"Hello, #{user.name}"Installation
Using igniter
The package provides an igniter install task for easy installation and setup:
mix igniter.install gettext_sigils
The installer also rewrites existing use Gettext calls in the project to use GettextSigils.
Manually
The package can be installed by adding gettext_sigils to your list of dependencies in mix.exs:
def deps do
[
{:gettext_sigils, "~> 0.5.0"}
]
endBasic Usage
To use the ~t sigil in your module, just use GettextSigils instead of the default Gettext module (for example in MyAppWeb.html_helpers/0 when using Phoenix):
# replace this
use Gettext, backend: MyApp.Gettext
# with this
use GettextSigils, backend: MyApp.Gettext
You can then use the ~t sigil instead of the gettext macro:
~t"Hello, World!"
# same as
gettext("Hello, World!")Note: The default Gettext macros (gettext, pgettext, dgettext, ...) remain available in modules that use GettextSigils, so you can mix and match as needed.
Features
Interpolation
Interpolated expressions become Gettext bindings with automatically derived keys:
~t"The #{fruit.name} is #{color}"
# => gettext("The %{fruit_name} is %{color}", fruit_name: fruit.name, color: color)
See the Interpolation guide for the full key derivation rules, handling of ambiguous keys, and explicit key = expr syntax.
Domain & Context
Set a default Gettext domain and context per module under the :sigils key. Every ~t sigil in the module then uses these by default:
use GettextSigils,
backend: MyApp.Gettext,
sigils: [
domain: "frontend",
context: "dashboard"
]
~t"Welcome" # => dpgettext(MyApp.Gettext, "frontend", "dashboard", "Welcome")Modifiers
Single-letter suffixes on the ~t sigil tweak how a translation is produced. Define them under the :modifiers key: each entry maps a letter to a keyword list of :domain and/or :context overrides that apply when the sigil carries that letter.
defmodule MyAppWeb.DashboardLive do
use GettextSigils,
backend: MyApp.Gettext,
sigils: [
domain: "frontend",
context: inspect(__MODULE__),
modifiers: [
e: [domain: "errors"],
g: [domain: :default, context: nil]
]
]
~t"Welcome" # domain: "frontend", context: "MyAppWeb.DashboardLive"
~t"Not found"e # domain: "errors", context: "MyAppWeb.DashboardLive"
~t"Yes"g # backend default domain, no context
~t"Not found"eg # backend default domain, no context (g runs after e)
endModifier entries can also point at a module for message rewriting, postprocessing, or custom pluralization. See the Modifiers guide for the full picture.
Pluralization
The built-in N modifier turns a ~t sigil into a plural Gettext call, selecting the singular or plural form at runtime based on the count binding:
~t"#{count} error(s)"N
Pluralization requires a count binding key. Use an explicit binding key to bind it to any value:
~t"#{count = length(errors)} error(s)"NSee the Pluralization guide for the full rules and how to write a custom pluralization modifier.
Usage Rules
GettextSigils ships with usage rules and skills for LLM coding agents (Claude Code, Cursor, Codex, etc.) via the usage_rules library. See the LLM guide for setup instructions.
Sponsoring
Shoutout to my employer 🦓 zebbra for allowing me to make this public. Need Elixir expertise made in 🇨🇠Switzerland? Feel free to reach out.