Building an Internationalization Library
Learn to use code generation to produce an internationalization library.
Almost all user-facing applications are best served by an internationalization layer where language snippets can be stored and referenced programmatically. Let’s use code generation to produce an internationalization library in very few lines of code.
This will be the most advanced exercise we’ve done so far, so we’ll start by breaking down our implementation into a rubric that we can use to attack complex metaprogramming problems:
- Step 1: Plan our macro API
- Step 2: Implement a skeleton module with metaprogramming hooks
- Step 3: Generate code from your accumulated module attributes
The Internationalization Library project:
In this lesson, you will incrementally build up an internationalization library. You will edit and test the code in the following widget:
defmodule I18n do use Translator locale "en", flash: [ hello: "Hello %{first} %{last}!", bye: "Bye, %{name}!" ], users: [ title: "Users", ] locale "fr", flash: [ hello: "Salut %{first} %{last}!", bye: "Au revoir, %{name}!" ], users: [ title: "Utilisateurs", ] end
Step 1: Plan our macro API
The first step of our Translator implementation is to plan the surface area of our macro
API. This is often called README Driven Development. It helps tease out our library goals and figure out what macros we need to make them happen.
Our goal is to produce the API given in the code widget below. Eventually, we want to call our module like this:
iex> I18n.t("en", "flash.hello", first:
# Output: "Chris", last: "McCord")
"Hello Chris Mccord!"
iex> I18n.t("fr", "flash.hello", first:
# Output: "Chris", last:
...defmodule I18n douse Translatorlocale "en",flash: [hello: "Hello %{first} %{last}!",bye: "Bye, %{name}!"],users: [title: "Users",]locale "fr",flash: [hello: "Salut %{first} %{last}!",bye: "Au revoir, %{name}!"],users: [title: "Utilisateurs",]end
We’ll support ...