Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
Gettext for Elixir - getting serious at compile...
Search
Sponsored
·
SiteGround - Reliable hosting with speed, security, and support you can count on.
→
Andrea Leopardi
October 03, 2015
Programming
560
2
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
Gettext for Elixir - getting serious at compile time
Andrea Leopardi
October 03, 2015
More Decks by Andrea Leopardi
See All by Andrea Leopardi
Agentic Elixir
whatyouhide
0
500
The Umbrella and the Range
whatyouhide
0
67
gen_statem - OTP's Unsung Hero
whatyouhide
2
350
The World is a Network (and We Are Just Nodes)
whatyouhide
1
260
BEAM: The Perfect Fit for Networks
whatyouhide
1
270
Update from the Elixir team - 2022
whatyouhide
0
460
Testing Asynchronous OTP
whatyouhide
1
580
Elixir Sightseeing Tour
whatyouhide
0
490
Mint - Disrupting HTTP clients
whatyouhide
0
310
Other Decks in Programming
See All in Programming
気づいたらRubyで100作品 ー クリエイティブコーディングが生活の一部になるまで / 100 Ruby Sketches Later: How Creative Coding Became Part of My Life
chobishiba
3
610
1B+ /day規模のログを管理する技術
broadleaf
0
120
LaravelLive Japan の裏方のすべて — 第188回 PHP勉強会@東京 (2026-06-24)
suguruooki
2
130
どこまでゆるくて許されるのか
tk3fftk
0
260
技術記事、 専門家としてのプログラマ、 言語化
mizchi
13
6.6k
例外の正しい扱い方 そのエラー try-catchして大丈夫?
jinwatanabe
0
290
Dataformのリポジトリを立ち上げるときにまずやること / dataform-day0-2026
snhryt
0
190
AIキャラアプリkaiwaの低遅延音声通話基盤をどう作ったか - AWS Gravitonで支える低遅延・低コストAI Agent基盤
mogamit
0
120
The NotImplementedError Problem in Ruby
koic
1
970
Mujeres en SEO Summit 2026 - Greatest Disaster Hits en Web Performance
guaca
0
210
TAKTでAI駆動開発の品質を設計する
j5ik2o
7
1.6k
Datadog × OpenTelemetry 入門と実践のあいだ
kn_to_maxpno
1
180
Featured
See All Featured
Conquering PDFs: document understanding beyond plain text
inesmontani
PRO
4
2.8k
Practical Orchestrator
shlominoach
191
11k
The World Runs on Bad Software
bkeepers
PRO
72
12k
Understanding Cognitive Biases in Performance Measurement
bluesmoon
32
2.9k
The Curse of the Amulet
leimatthew05
2
13k
Building the Perfect Custom Keyboard
takai
2
800
How to Think Like a Performance Engineer
csswizardry
28
2.7k
Discover your Explorer Soul
emna__ayadi
2
1.1k
No one is an island. Learnings from fostering a developers community.
thoeni
21
3.8k
Leveraging LLMs for student feedback in introductory data science courses - posit::conf(2025)
minecr
1
300
AI Search: Where Are We & What Can We Do About It?
aleyda
0
7.6k
Java REST API Framework Comparison - PWX 2021
mraible
34
9.4k
Transcript
gettext for elixir getting serious at compile time
None
processes otp supervision trees
vs compile time runtime
gettext is deadly simple at runtime
free } agent supervisor let it crash
andrea @whatyouhide leopardi
None
gettext
i18n b4g l10n internationalization localization boring
<%= translate "greetings.informal" %> # en_US.yml greetings: informal: "hello" context
# en_TX.yml greetings: informal: "howdy" translation
# in en_TX/LC_MESSAGES/default.po #: lib/greetings.ex:24 msgid "hello" msgstr "howdy" <%=
gettext "hello" %>
# in en_TX/LC_MESSAGES/default.po #: lib/greetings.ex:24 msgid "hello" msgstr "howdy" <%=
gettext "hello" %>
# in en_TX/LC_MESSAGES/default.po #: lib/greetings.ex:24 msgid "hello" msgstr "howdy" <%=
gettext "hello" %>
# in en_TX/LC_MESSAGES/default.po #: lib/greetings.ex:24 msgid "hello" msgstr "howdy" <%=
gettext "hello" %>
# in en_TX/LC_MESSAGES/default.po #: lib/greetings.ex:24 msgid "hello" msgstr "howdy" <%=
gettext "hello" %>
developers see plain strings
translators see plain strings
PO files
translator-friendly syntax # Enough with the greetings examples! #: lib/greeter.ex:24
msgid "hello" msgstr "hola"
tools
gettext elixir-lang /
read translations from po files extract translations from source interpolate
translations pluralization
read translations from PO files
defmodule Gettext do @translations Gettext.Compiler.po_files() for {msgid, msgstr} <- @translations
do def gettext_fn(unquote(msgid)) do unquote(msgstr) end end end
defmodule Gettext do @translations Gettext.Compiler.po_files() for {msgid, msgstr} <- @translations
do def gettext_fn(unquote(msgid)) do unquote(msgstr) end end end
defmodule Gettext do @translations Gettext.Compiler.po_files() for {msgid, msgstr} <- @translations
do def gettext_fn(unquote(msgid)) do unquote(msgstr) end end end
defmodule Gettext do @translations Gettext.Compiler.po_files() for {msgid, msgstr} <- @translations
do def gettext_fn(unquote(msgid)) do unquote(msgstr) end end end
defmodule Gettext do @translations Gettext.Compiler.po_files() for {msgid, msgstr} <- @translations
do def gettext_fn(unquote(msgid)) do unquote(msgstr) end end end
defmodule Unicode do @pairs Unicode.read("data.txt") for {lower, upper} <- @pairs
do def lower(unquote(upper)) do unquote(lower) end end end
very fast at runtime
move logic away from runtime
compiler friend is your the
extract translations from source
how they do it
printf(_("Hello"))
printf(_("Hello"))
how we do it
MACROS :D
functions that do stuff at compile time
mix gettext.extract calls mix compile --force
defmacro gettext(msgid) do extract(__CALLER__, msgid) quote do ... end end
defmacro gettext(msgid) do extract(__CALLER__, msgid) quote do ... end end
defmacro gettext(msgid) do extract(__CALLER__, msgid) quote do ... end end
has to be a string
defmacro gettext(msgid) do extract(__CALLER__, msgid) quote do ... end end
pushes to an agent
defmacro gettext(msgid) do extract(__CALLER__, msgid) quote do ... end end
has context
actual implementation
zero runtime cost
compiler friend is your the
interpolate translations
gettext "Hello %{name}!", %{name: "Frodo"} case %{name: "Frodo"} do %{name:
name} -> {:ok, "Hello " <> name} _ -> {:error, :bad_interp} end
gettext "Hello %{name}!", %{name: "Frodo"} case %{name: "Frodo"} do %{name:
name} -> {:ok, "Hello " <> name} _ -> {:error, :bad_interp} end
easy pluralization support
import MyApp.Gettext ngettext "One attendant", "%{count} attendants", 254 msgid "One
attendant" msgid_plural "%{count} attendants" msgstr[0] "Uno spettatore" msgstr[1] "%{count} spettatori"
# Arabic def plural("ar", 0), do: 0 def plural("ar", 1),
do: 1 def plural("ar", 2), do: 2 def plural("ar", n) when rem(n, 100) >= 3 and ... def plural("ar", n) when rem(n, 100) >= 11, ... def plural("ar", _n), do: 5
workflow
define a gettext module defmodule MyApp.Gettext do use Gettext, otp_app:
:my_app end
write source code import MyApp.Gettext gettext "Hello, world"
extract translations mix gettext.extract
extract translations POT files #: lib/greetings.ex:24 msgid "Hello, world!" msgstr
""
merge POT with locales mix gettext.merge priv/gettext --locale en_TX
merge POT with locales #: lib/old_greetings.ex:23 msgid "Hello, world!" msgstr
"Ciao, mondo!"
merge POT with locales #: lib/greetings.ex:24 msgid "Hello, world!" msgstr
"Ciao, mondo!"
merge POT with locales #: lib/greetings.ex:24 #, fuzzy msgid "Hello,
world!" msgstr "Ciao, mondo"
Again
so.
github.com/elixir-lang/gettext
@WHATYOUHIDE