The Artima Developer Community
Sponsored Link

Ruby Buzz Forum
Revisiting date localization for Ruby 1.8.6

0 replies on 1 page.

Welcome Guest
  Sign In

Go back to the topic listing  Back to Topic List Click to reply to this topic  Reply to this Topic Click to search messages in this forum  Search Forum Click for a threaded view of the topic  Threaded View   
Previous Topic   Next Topic
Flat View: This topic has 0 replies on 1 page
Patrick Lenz

Posts: 168
Nickname: scoop
Registered: Apr, 2005

Patrick Lenz is the lead developer at freshmeat.net and a contributor to the typo weblog engine
Revisiting date localization for Ruby 1.8.6 Posted: Oct 23, 2007 9:40 AM
Reply to this message Reply

This post originated from an RSS feed registered with Ruby Buzz by Patrick Lenz.
Original Post: Revisiting date localization for Ruby 1.8.6
Feed Title: poocs.net
Feed URL: http://feeds.feedburner.com/poocsnet
Feed Description: Personal weblog about free and open source software, personal development projects and random geek buzz.
Latest Ruby Buzz Posts
Latest Ruby Buzz Posts by Patrick Lenz
Latest Posts From poocs.net

Advertisement

Welcome to my yearly post about a revised version of a simple way to localize Ruby’s Time#strftime method (after my original post in ‘05 and the update in ‘06).

What’s changed?

In my original methodology, the arrays in the Date class containing the actual day and month names in clear text had to be replaced by strings wrapped in the infamous _() call of GetText in order to spit out their localized versions when requested from the modified Time#strftime call.

When Ruby 1.8.6 came along, it had its Date array constants frozen. While I agree it’s generally not a good idea to modify the contents of a constant (it’s a constant after all, mind you), the implementation I came up with 2 years ago worked fine up to and including today.

Since, also, most of the sites I’m working on require multiple languages (as opposed to, say, a single language set at application boot time), the contents of those Date arrays truly need to be modified at runtime and having those arrays frozen meant jumping through all sorts of hoops to address a supposedly simple issue.

What now?

Well, I had to come up with a way to actually execute the gettext functionality in the context of an object that has the current GetText locale bound to it. The most obvious object with that kind of property is ApplicationController.

But this still leaves us with the issue that we cannot modify the frozen Date constants and that everything we put into these constants is evaluated right away instead of at a point where we have the desired locale set.

What I came up with was a proxy object derived from the Array class that would basically just wrap the cleartext contents that are already in each of the Date arrays but not before they’re actually accessed/output.


    # lib/date_localization.rb
    class GetTextDateProxy < Array

      cattr_accessor :gettext_proxy

      def [](key)
        _(at(key))
      end

      def _(string)
        return string unless gettext_proxy
        gettext_proxy.instance_eval { gettext(string) }
      end

    end

As you can see, the proxy object is pretty simple after all. It just overwrites the default of Array#[] to look up the requested key and then wrap the output in _().

Since I couldn’t actually be bothered to include the whole of Ruby-GetText into my poor little proxy object, I then made room for it to hold a pointer to an instance of ApplicationController in a class attribute called gettext_proxy. The local underscore method of my proxy class then wraps around the actual gettext implementation available to the gettext proxy (read: ApplicationController), returning the string unchanged if there is no gettext proxy and if there is, run the string through the proxy’s gettext method.

Dealing with a state of not having a gettext proxy available is actually necessary in cases where there are calls to these arrays before ApplicationController gets to hook itself up to GetTextDateProxy.

But how does this actually hook into the Date class now? Let’s take a look:


    # lib/date_localization.rb
    class Date

      silence_warnings do
        %w(
          MONTHNAMES DAYNAMES ABBR_MONTHNAMES ABBR_DAYNAMES
        ).each do |array|
          class_eval %( #{array} = GetTextDateProxy.new(#{array}) )
        end
      end

    end

While this still looks a little tedious, it’s far less tedious than repeating the arrays’ contents simply wrapped in _() all over the place, like we had to do in previous incarnations of this methodology.

Basically, now every array is hooked up with their very own instance of GetTextDateProxy which then takes care of running the strings through gettext in the appropriate moments.

Wiring it all up

For the last part, we need to get ApplicationController to hook itself into GetTextDateProxy after having received the appropriate locale for the request it’s dealing with.

The best fit for this is the after_init_gettext hook provided by Ruby-GetText. Adding this code to ApplicationController will take care of the last required step.


    # app/controllers/application.rb
    after_init_gettext { GetTextDateProxy.gettext_proxy = self }    

Here you go, working (albeit hackish) localization for Ruby’s Time#strftime working up to and including the most recent version of Ruby, which is 1.8.6 as of this writing.

Enjoy.

Read: Revisiting date localization for Ruby 1.8.6

Topic: Libraries. This is where Ruby is head and shoulders above Python. Previous Topic   Next Topic Topic: More on the Wrong Question

Sponsored Links



Google
  Web Artima.com   

Copyright © 1996-2019 Artima, Inc. All Rights Reserved. - Privacy Policy - Terms of Use