Lunar Logic Polska

My improvements on latest i18n gem

Krzysztof Knapik by Krzysztof Knapik 13 January 2010

Originally published at knapo.net.

In recent weeks I spent a lot of time on i18n stuff in project I currently working on, so I was really happy, after I read José Valim’s article about new i18n gem, which has been very improved and introduces new features (Thanks José for great article and benchmarks).

Unfortunately, after few days of using it I noticed a few issues (which I reported on http://github.com/svenfuchs/i18n/issues. They were related to I18n::Backend::Fallbacks, which handled only translation method, and does not localize, pluralize and :default option, also I18n:Backend::Fast threw an exception when there were no translations for locale or one of locale fallbacks. Because I need all these 3 backends, they blocked using new i18n :(

Rather than wait until they will be fixed, I forked i18n http://github.com/knapo/i18n and fixed them by myself. So, I installed it as a plugin (using braid to easily upgrade its in future):

$ braid add -p git@github.com:knapo/i18n.git

And there’s a trick (which i18n’s README hopefully says about) – to use i18n as a plugin I had to add to my initializers/i18n.rb reload_i18n! method which replaces bundled i18n gem with plugin:

def reload_i18n!
  $:.grep(/i18n/).each { |path| $:.delete(path) }
  I18n::Backend.send :remove_const, "Simple" 
  $: << Rails.root.join('vendor/plugins/i18n/lib').to_s
end

reload_i18n!

and created my own backend (I preffer that than including all modules to I18::Backend::Simple)

module I18n
  module Backend
    class Knapo < Simple
      include I18n::Backend::Pluralization
      include I18n::Backend::Fallbacks
      include I18n::Backend::Fast
      include I18n::Backend::InterpolationCompiler
    end
  end
I18n.backend = I18n::Backend::Knapo.new

The only disadvantage of having i18n as a plugin is resetting I18n.load_path, so all default translations loaded by Rails are being removed, I mean:

actionpack-2.3.5/lib/action_view/locale/en.yml
activesupport-2.3.5/lib/active_support/locale/en.yml
activerecord-2.3.5/lib/active_record/locale/en.yml

But actually it might be a feature for some devs (e.g. me:) ), I copied them into my locales dir to active_support, active_record and action_view subdirs, and have all translations file in one place, and it’s better to have default (en) Rails ones there to easily compare other locale files with them, and/or edit them.

I also added extra extensions for I18n:

  • I18n::LoadPath which makes I18n.load_path more handy:
    I18n.load_path = I18n::LoadPath.new(I18n.load_path)
    I18n.load_path << Rails.root.join('locales/pl.yml') # loads single translation file
    I18n.load_path << Rails.root.join('locales') # loads all translation data files in specific directory
    I18n.load_path << Rails.root.join('locales/*.{yml,rb}') # loads all translation data files  by given pattern
  • I18n.wih_locale which executes block in given locale set
    I18n.with_locale("pl-PL") do
      # This code are being executed with pl-PL locale
    end
  • Making MissingTranslation message thrown by I18n.localize method complete, as previously when translation was missing it returned partial message e.g. for I18n.l Time.now, :format => :missing I was getting: translation missing: en, long_ordinal, what was misleading and now I’ve got: translation missing: en, time, formats, long_ordinal

The only thing I really don’t like in new i18n is forcing I18n.locale to Symbol – why? it should absolutely be a String

Anyway, thanks to Rails i18n team for great improvements on i18n, and looking forward for fixed issues in next gem version (and Rails3, of course).

blog comments powered by Disqus