Gettext and Rails
I encountered some problems with gettext rails integration recently, so here they are with explanation and resolution (if I found it).
Localization of ActiveRecordHelper error messages :
I choose to change the error message as explained by the gettext tutorial :
in application.rb
ActionView::Helpers::ActiveRecordHelper::L10n.set_error_message_title(Nn_("An error is occured", "%{num} errors are occured"))
ActionView::Helpers::ActiveRecordHelper::L10n.set_error_message_explanation(Nn_("The error is:", "The errors are:"))this works great, the error message displayed by the helper is the good one… except it only appears in the base language (English in my case). And the text never appears in my .pot file. After some searches in the gettext files, I found the problem : the textdomain for the helper is ‘rails’, which is great because you got validations and errors localized by gettext team for free. But it means you can’t set your own message without modifying the rails.pot in gettext package, which is not a solution because you need to maintain your own gettext gem or apply modifications to all you servers installs, and no you can’t install gettext as a rails plugin as gettext gem compile a gettext.so|.dylib on install which depends of your system.
The solution ? I didn’t find any satisfying one, if you force the textdomain to your app’s one then you need to duplicate and update all the rails translations strings from gettext package.
Gettext#updatepo and models with observers :
One of gettext nifty feature is its ability to extract your model columns names for translation. But the implementation cause some trouble when you have declared some observers in your environment.rb.
To accomplish its tasks, gettext first load rails environment. Then each files are parsed by Gettext::ActiveRecordParser#parse where you have :
old_constants = Object.constants
begin
eval(open(file).read, TOPLEVEL_BINDING)
rescue
$stderr.puts _("Ignored '%{file}'. Solve dependencies first.") % {:file => file}
$stderr.puts $!
end
loaded_constants = Object.constants - old_constantsThis code try to catch the constants the current file add to Object.constants and then parse them either as ruby or ActiveRecord subclass. But if you declared an observer in your environment.rb, the model and its observer is already in the Object.constants and are just ignored by the gettext active record parser.
Solution ? Comment the config.observers line in your environment.rb each time you need to run gettext:updatepo task, not really sexy but it works.
Fri, 30 Mar 2007 08:49 Posted in Ruby, RubyOnRails
Tags gettext, l10n, localization, rails, ruby
7 comments »
-
By Tim 3 days later:
-
By Jonathan Tron 4 days later:
Tim : I tried so many combination I didn’t remember exactly which one worked, but I think it was something like :
module Helpers #:nodoc: module ActiveRecordHelper #:nodoc: all module L10n include GetText bindtextdomain("MyDomain") end end endin my application_helper.rb.
After some time I decided I lost too much time on this problem and choosed a different approach. I defined a new
error_message_forin my application_helper.rb :def error_messages_for(object_name, view_partial = nil) obj = instance_variable_get("@#{object_name}") count = obj.errors.size unless count == 0 if view_partial.nil? if File.exist?("#{RAILS_ROOT}/app/views/shared/_error_messages.haml") render :partial => "shared/error_messages", :locals => {:object => obj, :count => count} end else render :partial => view_partial, :locals => {:object => obj, :count => count} end else "" end endwhich looks for a given shared template, mine looks like this :
%div #errorExplanation.errorExplanation %h2 = n_(ActionView::Helpers::ActiveRecordHelper::L10n.error_message_title, count) % {:num => count, :record => object} %p = n_(ActionView::Helpers::ActiveRecordHelper::L10n.error_message_explanation, count) %ul - object.errors.full_messages.each do |message| %li= messageThis solution is more flexible and benefits from Gettext Rails localization messages.
-
By Eric Northam 7 months later:
I made a quick monkey patch plugin to fix the observer parsing bug you ran into. You can install it via:
ruby script/plugin install http://svn.northam.us/gettext_active_record_fix/trunk/gettext_active_record_fix
Let me know if you run into any issues. It only tries to parse models that are defined at the top level of the file.
-
By Jonathan Tron 7 months later:
Eric : Thanks, as far as I can tell it works beautifully !
-
By Eric Northam 7 months later:
I contacted Masao about the bug and he proposed a more elegant and simple solution to my plugin. Just update your environment.rb with something similar to
unless defined? GetText config.active_record.observers = :user_observer end -
By Jonathan Tron 7 months later:
Eric : this will completely disable observers whenever GetText is used. I’m not sure about the solution… did it meant to set a variable to know when you run the updatepo/makemo tasks ?
-
By george 9 months later:
erics methods seems to work. did some debugging and GetText seems to be only defined when the task runs.
Regarding your ActiveRecordHelper ‘solution’, how did you go about forcing the textdomain to the one you used in your app? I’m curious what change you made and where.
Thanks