Internationalization (i18n) is one of those potentially necessary but not exactly thrilling tasks, so it is best when it is as simple as possible (related: I gave a recent talk at the Boston Ruby group on Rails i18n.) To that end I’ve made Translator, a Rails plugin to simplify the i18n process. It is an extraction from what we’ve learned as we’ve been working to internationalize our Rails application.
So what does it do?
Automatic Scoping, or Keep Your Keys DRY
The first thing it does is make the process of finding keys in localized bundles easier. The I18n module introduced in Rails 2.2 is a great help but it hasn’t (yet) been incorporated in a very Rails-y way. Translator defines a convention for keys that follows a similar layout to a Rails project’s app folder. The benefit is that the code stays DRY when fetching localized strings, saving precious typing. (Rails 2.3 recently added some partial scoping for views.) An example, starting with the en.yml that contains the strings for a fake blog app:
en: blog_posts: # controller show: # action title: "My Awesome Blog Post"
The code to fetch the title string in the view is just t(‘title’) and Translator determines the implied scoping of “blog_posts.show”. It provides the same automatic scoping for mailers, models, controllers and views.
Testing Help, or The Case of the Missing Key
When extracting boatloads of strings from view templates, mail templates, flash & validation error messages it is easy to make mistakes. The default handling for for a missing translation in a view is to add a span tag with a “missing translation” error message. A reasonable handling in production, but during development and testing it is better to find any missing translations early. Translator adds a strict_mode that will fail any tests that encounter a missing translation, and it can be enabled for manually testing as well. Better to fail fast than find out later there was a typo in a key name.
To help with forgetting to extract strings into locale bundles, Translator adds a pseudo_translate mode that will make it obvious which strings did not come from a bundle. In pseudo_translate mode every string from a bundle has a marker character prepended and appended to it. This makes it easy to quickly eyeball a page and see if anything isn’t surrounded in brackets, like “[My Blog]”. Also, this can be useful to see how a layout will look if localized to a more verbose language. German, for example, tends to use something like 30% more characters than English, so you could pad each string with 10 characters and see how the layout looks.
Graceful Locale Fallback, or No Hablo Espanol Hoy
Translator adds a simple locale fallback mechanism that will first try the set locale, say :de, and if a string isn’t found will fallback to the default_locale set in I18n (:en by default). This can bridge the gap between rolling out new site changes even if all the translations aren’t ready for every language.
We’ve been using Translator in production so it should be ready for others to use. If you do I’d be interested in feedback and suggestions. The Github page has more detailed examples, RDocs and how to get started.