Friday, April 5, 2013

Using Rails’ New I18n Support in Real Life: Part the Third


December 15th, 2008 By: Daniel

What happens when you add a new string to your default locale file and forget about the other languages? Well, by default it’ll raise a MissingTranslationData and your users will see an ugly string the likes of “es-MX, marketing_interface, index, title“. Wouldn’t it be better to at least try and default to English? My guess is that most people would prefer to see the message in another language than some cryptic error message. And while we’re wishing, don’t you think the localize method shouldn’t die a noisy death when you happen to pass it a nil?
My solution? A custom I18n backend. I simply copy/pasted the code from the default “Simple” backend, tweaked a few lines and I was good to go!
# In some file that gets sourced on startup, like maybe in your config/initializers directory
module I18n
  module Backend
    class Moki < Simple
 
      def translate(locale, key, options = {})
        raise InvalidLocale.new(locale) if locale.nil?
        return key.map { |k| translate(locale, k, options) } if key.is_a? Array
        reserved = :scope, :default
        count, scope, default = options.values_at(:count, *reserved)
        options.delete(:default)
        values = options.reject { |name, value| reserved.include?(name) }
        entry = lookup(locale, key, scope)
        if entry.nil?
          entry = default(locale, default, options)
          entry ||= lookup(I18n.default_locale, key, scope)
          raise(I18n::MissingTranslationData.new(locale, key, options)) if entry.nil?
        end
        entry = pluralize(locale, entry, count)
        entry = interpolate(locale, entry, values)
        entry
      end
 
      def localize(locale, object, format = :default)
        return nil if object.nil?
        raise ArgumentError, "Object must be a Date, DateTime or Time object. #{object.inspect} given." unless object.respond_to?(:strftime)
        type = object.respond_to?(:sec) ? 'time' : 'date'
        formats = translate(locale, "#{type}.formats")
        format = formats[format.to_sym] if formats && formats[format.to_sym]
        format = format.to_s.dup
        format.gsub!(/%a/, translate(locale, "date.abbr_day_names")[object.wday])
        format.gsub!(/%A/, translate(locale, "date.day_names")[object.wday])
        format.gsub!(/%b/, translate(locale, "date.abbr_month_names")[object.mon])
        format.gsub!(/%B/, translate(locale, "date.month_names")[object.mon])
        format.gsub!(/%p/, translate(locale, "time.#{object.hour < 12 ? :am : :pm}")) if object.respond_to? :hour
        object.strftime(format)
      end
 
    end
  end
end
I18n.backend = I18n::Backend::Moki.new

No comments:

Post a Comment