Run, I18n, run!

A new I18n gem just got released and it comes with two new backends extensions: Fast and InterpolationCompiler.

First, what is a backend?

I18n.t, I18n.translate, I18n.l and I18n.localize methods are actually just wrappers to I18n.backend, which is actually who does all the heavy lifting. This means that you can change your backend to other stuff, as long as it respects the required API.

By default, I18n comes with the Simple backend, but others are available. For example, I18n has an ActiveRecord, which stores translations in the database. This is useful in cases someone needs to change translations through a web interface. To use it, you just need to do:

  I18n.backend = I18n::Backend::ActiveRecord

There are a couple other backends, like a backend which implements fallbacks, so if something cannot be found in a specified language, like german (:de), it can fallback to english (:en). You can check the whole list, but for this while, we are going to focus on the two new backends extensions.

Fast

Fast, means fast. And oh, boy, this one is fast. This extension flattens translations to speed up the look up. For example, the following hash { :a => { :b => { :c => :foo } } }, gets flattened to { :"a.b.c" => "foo" }, so instead of recursively looking into hashes, it looks just once. The obvious expense is that whenever you are storing translations, you need to flatten the translation hash, and it takes more time than usual.

In order to measure different backend implementations, I pushed some benchmark setup to the I18n repository. The current setup measures the storage time, the time it takes to translate a key (the depth of the key means how many nested hashes it takes), the time to translate a key falling back to the default key and the time translate a key (at depth 5) and interpolate. The results comparing the Simple backend without and with Fast extension are showed below:

Simple vs. Fast

In other words, a simple lookup using the Fast extension is 3 to 4 times faster than the Simple one. Besides, configuring your application to use it is very simple:

  I18n::Backend::Simple.send :include, I18n::Backend::Fast

Nice!

Interpolation compiler

The InterpolationCompiler is a backend extension which extracts all required interpolation keys from a string, leaving just the minimum required to runtime. Imagine the following string: "This is a custom blank message for {{model}}: {{attribute}}". This extension annotates the string so it knows that it needs to interpolate both model and attribute, and points exactly where the interpolation should happen. We can compare the Simple backend without and with the InterpolationCompiler below:

Simple vs. Interpol

The InterpolationCompiler just changes the time taken when we have interpolation keys, without affecting too much the other translations. You can add it to your app as easy as the Fast backend:

  I18n::Backend::Simple.send :include, I18n::Backend::InterpolationCompiler

Run, I18n, run!

But the best is still coming! Fast and InterpolationCompiler can actually be used together, to achieve unseen performance in I18n. The benchmark speaks for itself:

Simple vs. FastInterpol

While we speed up the performance in around four times in simple lookups, Fast and InterpolationCompiler improvements get combined whenever we need to use interpolation, becoming around six times faster!

As said previously, both extensions increase the time taken to store translations as side-effect. Such can be viewed below:

Store

The yaml hash used in for the benchmark, is relatively slow, but it shows how the time taken to store translations grows with such extensions. But remember, you are constantly storing translations only in development (before each request is processed). In production, the translations are stored at startup and that is it.

Using within Rails

You should be able to use such features today in Rails 2.3.5 and it will also be possible in Rails 3. You just need to install the I18n gem and configure it in your environment.

Why care?

All the times shown are in miliseconds. In other words, why care? If you are building a simple application, using just one language, those improvements likely won’t change anything. But in an application which relies on I18n, during a request/response lifecycle, I18n is invoked many times: error messages for models, flash messages, page titles, e-mail subjects, page content, date and time localization, pluralization rules and even in many of ActionView helpers. So in such cases, it’s worth to give such extensions a try.

Running benchmarks on your own

If you want to run benchmarks on your own, it’s quite simple. You just need to do:

git clone git://github.com/svenfuchs/i18n.git
cd i18n
ruby benchmark/run.rb

Credits

The possibility to have backends and such extensions is due to Sven Fuchs, which leads the I18n group quite well.

Many of the backends were added by I18n community, and the Fast and InterpolationCompiler were created by thedarkone.

Guys, I owe you a beer! 😉

Enjoy!

16 responses to “Run, I18n, run!”

  1. This is some seriously good news for all of us I18n users. Thanks for the info José.

  2. This is some seriously good news for all of us I18n users. Thanks for the info José.

  3. Gravis says:

    Awesome ! Thanks guys for the very good work 🙂

  4. Gravis says:

    Awesome ! Thanks guys for the very good work 🙂

  5. Daniel Lopes says:

    I think fallbacks should be built in Rails, it is a really common situation and the code is fairly easy to port from Fallback backend to SimpleBackend. I think this change will no bloat Rails.

  6. Daniel Lopes says:

    I think fallbacks should be built in Rails, it is a really common situation and the code is fairly easy to port from Fallback backend to SimpleBackend. I think this change will no bloat Rails.

  7. Sven Fuchs says:

    Daniel, Fallbacks is not actually a backend but a Module that’s supposed to be mixed into the Simple backend (or compatible backends). It’s not part of Simple by default because this functionality is not needed for many, many applications (so we can spare these apps a bit load). This stuff is part of I18n 0.3.x and can be installed/used as a gem starting from Rails 2.3.5 (iirc), it will be part of Rails 3, too.

  8. Sven Fuchs says:

    Daniel, Fallbacks is not actually a backend but a Module that’s supposed to be mixed into the Simple backend (or compatible backends). It’s not part of Simple by default because this functionality is not needed for many, many applications (so we can spare these apps a bit load). This stuff is part of I18n 0.3.x and can be installed/used as a gem starting from Rails 2.3.5 (iirc), it will be part of Rails 3, too.

  9. Daniel Lopes says:

    Great, thanks Sven.

  10. Daniel Lopes says:

    Great, thanks Sven.

  11. Thanks for the post José.

    Sorry by change the subject, but, which chart tool did you use to generate those charts?

    Thanks.

  12. Thanks for the post José.

    Sorry by change the subject, but, which chart tool did you use to generate those charts?

    Thanks.

  13. José Valim says:

    @bruno, I used Open Office for Mac.

  14. José Valim says:

    @bruno, I used Open Office for Mac.

  15. @josevalim Ok, thanks!

  16. @josevalim Ok, thanks!