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
540
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
The Umbrella and the Range
whatyouhide
0
17
gen_statem - OTP's Unsung Hero
whatyouhide
2
270
The World is a Network (and We Are Just Nodes)
whatyouhide
1
230
BEAM: The Perfect Fit for Networks
whatyouhide
1
210
Update from the Elixir team - 2022
whatyouhide
0
420
Testing Asynchronous OTP
whatyouhide
1
530
Elixir Sightseeing Tour
whatyouhide
0
440
Mint - Disrupting HTTP clients
whatyouhide
0
260
BEAM Architecture Handbook
whatyouhide
7
2.9k
Other Decks in Programming
See All in Programming
釣り地図SNSにおける有料機能の実装
nokonoko1203
0
190
Devvox Belgium - Agentic AI Patterns
kdubois
1
130
Catch Up: Go Style Guide Update
andpad
0
240
XP, Testing and ninja testing ZOZ5
m_seki
3
780
PHPに関数型の魂を宿す〜PHP 8.5 で実現する堅牢なコードとは〜 #phpcon_hiroshima / phpcon-hiroshima-2025
shogogg
1
310
バッチ処理を「状態の記録」から「事実の記録」へ
panda728
PRO
0
180
スキーマ駆動で、Zod OpenAPI Honoによる、API開発するために、Hono Takibiというライブラリを作っている
nakita628
0
270
What's new in Spring Modulith?
olivergierke
1
160
ALL CODE BASE ARE BELONG TO STUDY
uzulla
26
6.5k
Domain-centric? Why Hexagonal, Onion, and Clean Architecture Are Answers to the Wrong Question
olivergierke
3
930
One Enishi After Another
snoozer05
PRO
0
130
Six and a half ridiculous things to do with Quarkus
hollycummins
0
200
Featured
See All Featured
The World Runs on Bad Software
bkeepers
PRO
72
11k
We Have a Design System, Now What?
morganepeng
53
7.8k
Building Flexible Design Systems
yeseniaperezcruz
329
39k
Faster Mobile Websites
deanohume
310
31k
Visualizing Your Data: Incorporating Mongo into Loggly Infrastructure
mongodb
48
9.7k
How STYLIGHT went responsive
nonsquared
100
5.8k
Building Applications with DynamoDB
mza
96
6.7k
How To Stay Up To Date on Web Technology
chriscoyier
791
250k
ReactJS: Keep Simple. Everything can be a component!
pedronauck
667
120k
What’s in a name? Adding method to the madness
productmarketing
PRO
24
3.7k
Gamification - CAS2011
davidbonilla
81
5.5k
Side Projects
sachag
455
43k
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