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
Andrea Leopardi
October 03, 2015
Programming
2
530
Gettext for Elixir - getting serious at compile time
Andrea Leopardi
October 03, 2015
Tweet
Share
More Decks by Andrea Leopardi
See All by Andrea Leopardi
gen_statem - OTP's Unsung Hero
whatyouhide
2
250
The World is a Network (and We Are Just Nodes)
whatyouhide
1
220
BEAM: The Perfect Fit for Networks
whatyouhide
1
200
Update from the Elixir team - 2022
whatyouhide
0
400
Testing Asynchronous OTP
whatyouhide
1
520
Elixir Sightseeing Tour
whatyouhide
0
420
Mint - Disrupting HTTP clients
whatyouhide
0
250
BEAM Architecture Handbook
whatyouhide
7
2.8k
The Evolution of a Language
whatyouhide
0
160
Other Decks in Programming
See All in Programming
Cursor AI Agentと伴走する アプリケーションの高速リプレイス
daisuketakeda
1
120
Kotlin エンジニアへ送る:Swift 案件に参加させられる日に備えて~似てるけど色々違う Swift の仕様 / from Kotlin to Swift
lovee
1
240
イベントストーミングから始めるドメイン駆動設計
jgeem
4
870
Passkeys for Java Developers
ynojima
3
870
Select API from Kotlin Coroutine
jmatsu
1
180
Is Xcode slowly dying out in 2025?
uetyo
1
140
業務自動化をJavaとSeleniumとAWS Lambdaで実現した方法
greenflagproject
1
120
DroidKnights 2025 - 다양한 스크롤 뷰에서의 영상 재생
gaeun5744
3
300
C++20 射影変換
faithandbrave
0
500
今ならAmazon ECSのサービス間通信をどう選ぶか / Selection of ECS Interservice Communication 2025
tkikuc
11
2.7k
コードの90%をAIが書く世界で何が待っているのか / What awaits us in a world where 90% of the code is written by AI
rkaga
41
27k
Spring gRPC で始める gRPC 入門 / Introduction to gRPC with Spring gRPC
mackey0225
2
520
Featured
See All Featured
The Success of Rails: Ensuring Growth for the Next 100 Years
eileencodes
45
7.4k
The Cult of Friendly URLs
andyhume
79
6.4k
[Rails World 2023 - Day 1 Closing Keynote] - The Magic of Rails
eileencodes
35
2.3k
KATA
mclloyd
29
14k
How to Create Impact in a Changing Tech Landscape [PerfNow 2023]
tammyeverts
53
2.8k
The MySQL Ecosystem @ GitHub 2015
samlambert
251
13k
Six Lessons from altMBA
skipperchong
28
3.8k
CoffeeScript is Beautiful & I Never Want to Write Plain JavaScript Again
sstephenson
161
15k
Code Reviewing Like a Champion
maltzj
524
40k
How to Think Like a Performance Engineer
csswizardry
24
1.7k
Designing Experiences People Love
moore
142
24k
Facilitating Awesome Meetings
lara
54
6.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