4. Using gettext for translation
Mix.install([
:gettext
])
Resolving Hex dependencies...
Resolution completed in 0.072s
New:
expo 0.4.1
gettext 0.22.3
* Getting gettext (Hex package)
* Getting expo (Hex package)
==> expo
Compiling 2 files (.erl)
Compiling 21 files (.ex)
Generated expo app
==> gettext
Compiling 17 files (.ex)
Generated gettext app
:ok
Setup .po translation files
The gettext workflow relies heavily on the filesystem: Each supported locale must have a directory in a specific place. Inside of this directory, gettext expects to find translation files (ending in .po), named for a particular domain (usually ‘default’) that contain translation strings in a specific format.
Here we generate a sample translation file for gettext, but usually, this will be done with 3rd-party tooling, like http://poedit.net/ or https://poeditor.com.
# find the current directory, where the livebook is running
{current_dir, _} = System.cmd("pwd", [])
# create a new directory for French translation files
System.cmd("mkdir", ["-p", "priv/gettext/fr_FR/LC_MESSAGES"])
# create a new ".po" translation file
sample_po_translation_file = """
msgid "Here is one string to translate"
msgstr "Voici une chaîne à traduire"
msgid "404 error"
msgstr "erreur 404"
"""
{:ok, file} = File.open("priv/gettext/fr_FR/LC_MESSAGES/default.po", [:write, :utf8])
IO.write(file, sample_po_translation_file)
:ok
Once the translation files are in place, they are parsed and baked into your application by gettext at compile-time. Below, we define a new gettext ‘backend’ module, which triggers compilation.
# define a gettext 'backend model'
defmodule DemoApp.Gettext do
use Gettext, otp_app: :foo
end
{:module, DemoApp.Gettext, <<70, 79, 82, 49, 0, 0, 47, ...>>, :ok}
Translation functions
TODO: explain these
import DemoApp.Gettext
Gettext.put_locale("fr_FR")
# simple message
gettext("Hello world")
|> IO.inspect()
gettext("404 error")
|> IO.inspect()
gettext("Here is one string to translate")
|> IO.inspect()
# plural message
number_of_apples = 4
ngettext("The apple is ripe", "The apples are ripe", number_of_apples)
|> IO.inspect()
# domain-based message
dgettext("errors", "Here is an error message to translate")
|> IO.inspect()
:ok
"Hello world"
"erreur 404"
"Voici une chaîne à traduire"
"The apples are ripe"
"Here is an error message to translate"
:ok