Why GetText is Better than Rails I18n

We have a strong opinion about how an application in general, and more especially a Rails application, should be internationalized. A lot of people use the default Rails Internationalization API (I18n) but we don't really think this is an ideal solution for big projects.

Our reasons.

1. It's painful to "make up" keys. Need to switch between many files.

In a system like YAML, you have to invent the keys.

For example the welcome title of the main page of an app may be in t("home.title") but you can end up with very verbose things like t("on_call_schedules.contact_form.on_call_schedule_comment_placeholder").

2. Not trivial to search text in code.

When you want to change a text, you have to look for its key in the codebase, then find the text itself in the corresponding YAML file. Doesn't sound very practical to us.

With GetText, editing a text is just a matter of finding it and updating it, right in place.

3. Difficult coevolution between keys and associated text.

You've found a nice, short and descriptive key name for a given text. A few weeks later the customer asks for a significant change in the source language of that text. In such a situation you also need to change the key according to its new signification. Sometimes you won't, or you will forget. Then you will probably end up with a key name not representative of its content.

4. Difficult to know if all the keys are really used in the application.

All the translation keys are located at the same place : in YAML file(s). They are also organized as a tree. When the key is used in the code, it is formatted with a dot syntax like my.key. When you are in a YAML file, it's not easy to perform a "find in project" with your editor to see if it is still used or not. Because you have to convert the path in the tree to dot syntax before.

With the GetText paradigm, unused strings will be automatically detected at POT file generation. And with Translation.io you can safely remove all unused strings with the rake translation:sync_and_purge task.

5. YAML can contain values that are not translations.

Rails YAML files contain not only translation strings but also localization values (integers, arrays, booleans) in the same place and that's bad. For example : date formats, number separators, default currency or measure units, etc.

A translator is supposed to translate, not localize. That's not his role to choose how you want your dates or numbers to be displayed, right ? Moreover, this special keys often contain special constructions (e.g., with percent signs or spaces) that he might break.

We think localization is part of the configuration of the app and it should not reach the translator UI at all. That's why these localization keys are detected and separated on a dedicated YAML file with Translation.io.

6. GetText is a standard in the Open-Source community.

GNU GetText has been around since 1995 and is the de-facto translation solution for many projects. So why not using it in Rails applications ?

7. GetText syntax is nice.

GetText syntax looks optimal to us: short method names because used everywhere in the codebase and easy to remember. Ok t is a short name too ;-)

However, YAML has some advantages too.

1. Pre-translated YAML files for Gems.

That's true it's easier to ship the translatable strings of a Gem as a YAML file. No dependency at all because Rails ships with YAML.

2. Allows to copyright text in the source language.

With YAML, if you are using an external service like Locale, you can use keys to write a new text in the source language, not only in the target languages. It creates a lot of situations where you need to deal with conflicts, but this is not possible to do the same thing with GetText.

Also, as explained above, you have to be careful when you update the keys in order to keep them relevant.

When it's a key coming from Rails, you can override the source text it in your own YAML file too.

Conclusion

We, Translation.io, propose two ways for translating your applications, but we strongly encourage you to use GetText as your main workflow since your translation process will be way smoother.