Using ruby-gettext with Edge Rails
The more I read about the various new features coming up in Rails 2.0, the more I couldn’t resist… and finally, a few days ago, I switched over to Edge Rails with my current project.
Switching to Edge Rails was easily done, however after fireing up /script/server and doing the first request, I was presented with a 500 Internal Server Error.
DISPATCHER FAILSAFE RESPONSE (has cgi) Sun Jul 29 12:43:56 +0200 2007
Status: 500 Internal Server Error
You have a nil object when you didn’t expect it!
You might have expected an instance of ActiveRecord::Base.
The error occurred while evaluating nil.[]
/usr/lib64/ruby/1.8/cgi.rb:1165:in `[]’
/usr/lib64/ruby/gems/1.8/gems/gettext-1.10.0/lib/gettext/locale_cgi.rb:26:in `system’
/usr/lib64/ruby/gems/1.8/gems/gettext-1.10.0/lib/gettext/locale.rb:88:in `system’
/usr/lib64/ruby/gems/1.8/gems/gettext-1.10.0/lib/gettext/locale.rb:96:in `default’
After some time of debugging, it turned out to be ruby-gettext, which I use for I18N, that causes a NoMethodError on each request during init-gettext.
What happened here is, that ruby-gettext tries to figure out the current visitor’s language by looking for an URL parameter or a cookie named lang or the HTTP Accept header. Looking for the URL parameter seems to be the problem in this case. Locale::SystemCGI.system calls cgi["lang"] to look for the URL parameter, but CGI#[] raises a NoMethodError, because the @params hash does not contain a key named lang. Here are the first few lines of CGI#[] (starting at line 1163 in cgi.rb):
1 def [](key) # cgi.rb:1163 2 params = @params[key] # nil gets assigned to params 3 value = params[0] # raises NoMethodError, because params is nil 4 if @multipart 5 if value 6 return value
The solution
The problem could be fixed by patching cgi.rb of the ruby standard library or locale_cgi.rb of ruby-gettext (like somebody with a similar problem suggested in this mail). However this isn’t usually applicable on production servers. Instead, you can work around this problem by modifying CGI#[] from within your rails application temporarily, until the bug is fixed.
With Edge Rails, you don’t place your own statements in config/environment.rb anymore. Instead, you can write an initializer file and place it into config/initializers. For ruby-gettext, I created config/initializers/gettext.rb, which contains:
require 'gettext/rails'
To work around the above problem, add the following code to your gettext initializer, right after the require statement:
1 class CGI 2 module QueryExtension 3 alias index_without_fix :[] 4 def [] (key) 5 return nil unless @params[key] 6 index_without_fix(key) 7 end 8 end 9 end
This modifies CGI#[] to return nil if the requested param does not exist.
Update (2007-10-20): The above problem was fixed in Ruby 1.8.6-p26.
Finally, my application runs with Edge Rails and I can now start to explore all the new stuff (and probably do a lot of refactoring to use those features).
New-style .html.erb templates
Update (2007-07-31): Ruby-gettext is currently unable to recognize new-style .html.erb template files (since it doesn’t know that .erb files should be parsed by GetText::ErbParser). I reported this to Masao, the author of ruby-gettext (so it’ll be probably fixed in future versions). Since then, you can work around it by modifying your lib/tasks/gettext.rake like this:
1 require 'gettext/utils' 2 # Tell ruby-gettext's ErbParser to parse .erb files as well 3 # See also http://zargony.com/2007/07/29/using-ruby-gettext-with-edge-rails 4 GetText::ErbParser.init(:extnames => ['.rhtml', '.erb']) 5 desc 'Update pot/po files' 6 task :updatepo do 7 GetText.update_pofiles('messages', Dir.glob("{app,lib}/**/*.{rb,rhtml,erb,rjs}"), 'MyApp') 8 end 9 desc 'Create mo-files' 10 task :makemo do 11 GetText.create_mofiles(true, 'po', 'locale') 12 end
Update (2007-08-01): Masao pointed out, that it’s better to use the GetText::ErbParser.init method rather than overriding ErbParser. Thanks Masao.
Update (2008-02-25): .erb files are now parsed by default, so the above fix isn’t necessary anymore. Scanning .erb files was added on July 31, 2007 and is included in ruby-gettext 1.90.0 which was released on Feb 02, 2008.
Great! This made my life alot easier…I hope this gets fixed in a future release of gettext though!
I still have a few problems with GetText and edge rails. I created the two rake-taks “updatepo and makemo”, but somehow makemo doesn’t work. It should create the locale directory with all its language folders along with the compiled .pot files etc. right? When I run makemo nothing happens…no errors, nothing. Any ideas?
-—