Internationalization of Fractal (3rd and last part)

“Tl;dr version”: I’ve finished implementing the i18n of Fractal and I’ve submitted a first French translation of it. With some help from Daniel (my mentor) to complete the integration with the build system, so thank him for that! Here are my merge requests: https://gitlab.gnome.org/World/fractal/merge_requests/105 and https://gitlab.gnome.org/World/fractal/merge_requests/107.

I am going to detail a little bit what was done in order to achieve this.

Integrate gettext-rs to the project

I first added gettext-rs as one of the dependencies of Fractal (in this commit), as I have explained it in the previous articles. Then, I put the initialization of gettext-rs by asking it to look for the locale files in ./fractal-gtk/po (in this commit).

Wrap all the translatable strings in the Rust source files

Then I took quite some time to examine every strings in the source files of the crate fractal-gtk to wrap all messages that would end up in the GUI with gettext (it turned out that I didn’t really need to use ngettext). Wrapping some strings in the format! macro was less obvious to deal with though. For instance:

secondary = format!("You've been invited to join to <b>{}</b> room by <b>{}</b>",
                    room_name, sender_name);

Couldn’t be straightforwardly rewritten like this:

secondary = format!(gettext("You've been invited to join to <b>{}</b> room by <b>{}</b>"),
                    room_name, sender_name);

Because the first argument of format! needs to be a string literal, so I had to use this work around instead:

let sentence_template = gettext("You've been invited to join to <b>{room_name}</b> room by <b>{sender_name}</b>");
secondary = sentence_template.replace("{room_name}", room_name.as_str())
                             .replace("{sender_name}", sender_name.as_str());

I explicitly did what format! would have done here without having the constraint of using a string literal. Because in some languages, the place of {room_name} and {sender_name} can be reversed. See this commit for more details.

Adding the support of gettext within the build system

Next, we needed a way to automatically generate PO and POT files and move MO files to the right place for gettext-rs to read. So I was going to have the meson build system helping me for that. I first added a POTFILES.in file which lists all the files with translatable strings in them and a LINGUAS file which list the languages for which we want to have PO files. And I’ve added a meson.build file and updated to one in the project root to be able to generate the mentioned file: you can run `ninja -C _build fractal-pot` to generate a POT file and `ninja -C _build fractal-update-po` to generate/update PO files. See these commit for more details on: the POTFILE.in, the LINGUAS file and the meson.build files.

Once the ability to generate the locale files implemented, Daniel helped my with this commit that removes the hard-coded path to bind the text domain for gettext. And he added a Spanish translation (see this commit). I also submitted a French translation, see this commit and this one.

After my MR merged, my first task for GSoC is completed!! šŸ™‚

Leave a comment