{"id":538,"date":"2009-12-29T20:11:42","date_gmt":"2009-12-29T22:11:42","guid":{"rendered":"http:\/\/blog.plataformatec.com.br\/?p=538"},"modified":"2010-04-25T09:48:45","modified_gmt":"2010-04-25T12:48:45","slug":"run-i18n-run","status":"publish","type":"post","link":"https:\/\/blog.plataformatec.com.br\/2009\/12\/run-i18n-run\/","title":{"rendered":"Run, I18n, run!"},"content":{"rendered":"

A new I18n gem<\/a> just got released<\/a> and it comes with two new backends extensions: Fast<\/a> and InterpolationCompiler<\/a>.<\/p>\n

First, what is a backend?<\/h3>\n

I18n.t<\/code>, I18n.translate<\/code>, I18n.l<\/code> and I18n.localize<\/code> methods are actually just wrappers to I18n.backend<\/code>, 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.<\/p>\n

By default, I18n comes with the Simple backend<\/a>, but others are available. For example, I18n has an ActiveRecord<\/a>, 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:<\/p>\n

  I18n.backend = I18n::Backend::ActiveRecord<\/pre>\n

There are a couple other backends, like a backend which implements fallbacks<\/a>, 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<\/a>, but for this while, we are going to focus on the two new backends extensions.<\/p>\n

Fast<\/h3>\n

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 } } }<\/code>, gets flattened to { :\"a.b.c\" => \"foo\" }<\/code>, 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.<\/p>\n

In order to measure different backend implementations, I pushed some benchmark setup<\/a> 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:<\/p>\n

\"Simple<\/a><\/p>\n

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:<\/p>\n

\r\n  I18n::Backend::Simple.send :include, I18n::Backend::Fast\r\n<\/pre>\n

Nice!<\/p>\n

Interpolation compiler<\/h3>\n

The InterpolationCompiler<\/a> 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}}\"<\/code>. 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:<\/p>\n

\"Simple<\/a><\/p>\n

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:<\/p>\n

\r\n  I18n::Backend::Simple.send :include, I18n::Backend::InterpolationCompiler\r\n<\/pre>\n

Run, I18n, run!<\/h3>\n

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

\"Simple<\/a><\/p>\n

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

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

\"Store\"<\/a><\/p>\n

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.<\/p>\n

Using within Rails<\/h3>\n

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<\/a> gem and configure it in your environment.<\/p>\n

Why care?<\/h3>\n

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.<\/p>\n

Running benchmarks on your own<\/h3>\n

If you want to run benchmarks on your own, it’s quite simple. You just need to do:<\/p>\n

git clone git:\/\/github.com\/svenfuchs\/i18n.git\r\ncd i18n\r\nruby benchmark\/run.rb<\/pre>\n

Credits<\/h3>\n

The possibility to have backends and such extensions is due to Sven Fuchs<\/a>, which leads the I18n group quite well.<\/p>\n

Many of the backends were added by I18n community, and the Fast<\/a> and InterpolationCompiler<\/a> were created by thedarkone<\/a>.<\/p>\n

Guys, I owe you a beer! \ud83d\ude09<\/p>\n

Enjoy!<\/p>\n","protected":false},"excerpt":{"rendered":"

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, … \u00bb<\/a><\/p>\n","protected":false},"author":4,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"ngg_post_thumbnail":0,"footnotes":""},"categories":[1],"tags":[58,59,23,7],"aioseo_notices":[],"jetpack_sharing_enabled":true,"jetpack_featured_media_url":"","_links":{"self":[{"href":"https:\/\/blog.plataformatec.com.br\/wp-json\/wp\/v2\/posts\/538"}],"collection":[{"href":"https:\/\/blog.plataformatec.com.br\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blog.plataformatec.com.br\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blog.plataformatec.com.br\/wp-json\/wp\/v2\/users\/4"}],"replies":[{"embeddable":true,"href":"https:\/\/blog.plataformatec.com.br\/wp-json\/wp\/v2\/comments?post=538"}],"version-history":[{"count":15,"href":"https:\/\/blog.plataformatec.com.br\/wp-json\/wp\/v2\/posts\/538\/revisions"}],"predecessor-version":[{"id":948,"href":"https:\/\/blog.plataformatec.com.br\/wp-json\/wp\/v2\/posts\/538\/revisions\/948"}],"wp:attachment":[{"href":"https:\/\/blog.plataformatec.com.br\/wp-json\/wp\/v2\/media?parent=538"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blog.plataformatec.com.br\/wp-json\/wp\/v2\/categories?post=538"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blog.plataformatec.com.br\/wp-json\/wp\/v2\/tags?post=538"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}