Gettext (i18n)
Gettext is an i18n tool that is separate from your app's code. The main benefit over other tools is, just as GResource, being integrated with GTK. Gettext apart from basic 1 on 1 translations, is also able to handle plurals and automatically detect the system's language.
You can get the Crystal bindings for it and explore its methods at: https://github.com/GeopJr/gettext.cr.
There are three filetypes associated with it: .pot
, .po
& .mo
. The last one is binary.
Getting Started
Create a
po/
folder if you haven't alreadyCreate a
po/LINGUAS
file that includes the language codes of the available translations, one per lineCreate a
po/POTFILES
file that includes the paths of the files we should extract strings from (usually all .ui files, metainfo & desktop)Run
xgettext
to extract the translatable strings into a.pot
file, which acts as a "template" for the other translations:
$ xgettext --files-from=po/POTFILES --output=po/APP_ID.pot
- Create a
.po
file for a language usingmsginit
e.g.:
$ msginit -i po/APP_ID.pot -o po/el.po -l el_GR.utf8
Translate the strings found in the newly created
.po
fileCreate a binary
.mo
usingmsgfmt
e.g.:
$ msgfmt po/el.po -o po/locale/el/LC_MESSAGES/APP_ID.mo
Move the
po/locale/
to/usr/share/locale
(not necessary)Add the following to your
prerequisites
:
Gettext.setlocale(Gettext::LC::ALL, "")
# The macro allows you to set a custom env var during compile time for the mo location e.g. `MY_APP_LOCALE_LOCATION="./po/locale/"`
Gettext.bindtextdomain("APP_ID", {{env("MY_APP_LOCALE_LOCATION").nil? ? "/usr/share/locale" : env("MY_APP_LOCALE_LOCATION")}})
Gettext.textdomain("APP_ID")
- Test it by running it with
LANG="el"
You can also add strings that only exist in code in the .pot
(and .po
) files and then translate them on demand, for instance:
label = Gtk::Label.new("")
label.text = Gettext.gettext("Hello World")
# LANG="en" => "Hello World"
# LANG="el" => "Γειά σου Κόσμε"
Translating .desktop and metainfo files
Translating those files is just as easy, for the sake of not replacing themselves, add the .in
extension (APP_ID.dekstop.in
& APP_ID.metainfo.xml.in
).
TIP
Don't forget to update them in the POTFILES
file too.
Now all you have to do is run:
- For the metainfo file:
$ msgfmt --xml --template data/APP_ID.metainfo.xml.in -d "./po" -o data/APP_ID.metainfo.xml
- For the .desktop file
$ msgfmt --desktop --template data/APP_ID.desktop.in -d "./po" -o data/APP_ID.desktop
INFO
You need to have the language you are testing with, installed (locale -a
).
TIP
Remember to add *.mo
to your .gitignore
.
TIP
Replace APP_ID
with your app's ID.