=begin gettext/active_record.rb - GetText for ActiveRecord Copyright (C) 2006 Masao Mutoh You may redistribute it and/or modify it under the same license terms as Ruby. $Id: active_record.rb,v 1.9 2006/09/10 15:08:32 mutoh Exp $ =end require 'gettext' require 'active_record' module ActiveRecord #:nodoc: class Migration extend GetText include GetText end module ConnectionAdapters #:nodoc: # An abstract definition of a column in a table. class Column attr_accessor :table_class alias :human_name_witout_localized :human_name def human_name table_class.human_attribute_name(@name) end end end module Validations # :nodoc: def self.real_included(base) base.extend ClassMethods base.class_eval{ include GetText def gettext(str) #:nodoc: _(str) end def self.human_attribute_name(attribute_key_name) #:nodoc: s_("#{self}|#{attribute_key_name.humanize}") end def self.human_attribute_table_name_for_error(table_name) #:nodoc: _(table_name.gsub(/_/, " ")) end } end if ActiveRecord::VERSION::STRING >= "1.14.5" def self.included(base) # :nodoc: super real_included(base) end else def self.append_features(base) # :nodoc: super real_included(base) end end module ClassMethods #:nodoc: @@custom_error_messages_d = {} # Very ugly but... def validates_length_of(*attrs) #:nodoc: if attrs.last.is_a?(Hash) msg = attrs.last[:message] || attrs.last[:too_long] || attrs.last[:too_short] || attrs.last[:wrong_length] if msg @@custom_error_messages_d[msg] = /\A#{Regexp.escape(msg).sub(/%d/, '(\d+)')}\Z/ end end validates_size_of(*attrs) end def custom_error_messages_d #:nodoc: @@custom_error_messages_d end end def custom_error_messages_d #:nodoc: self.class.custom_error_messages_d end end class Base include GetText include Validations @@gettext_untranslate = Hash.new(false) @@gettext_untranslate_columns = {} # Untranslate all of the tablename/fieldnames in this model class. def self.untranslate_all @@gettext_untranslate[self] = true end # Returns true if "untranslate_all" is called. Otherwise false. def self.untranslate_all? @@gettext_untranslate[self] end # Sets the untranslate columns. # (e.g.) untranslate :foo, :bar, :baz def self.untranslate(*w) ary = @@gettext_untranslate_columns[self] || [] ary += w.collect{|v| v.to_s} @@gettext_untranslate_columns[self] = ary end # Returns true if the column is set "untranslate". # (e.g.) untranslate? :foo def self.untranslate?(columnname) ary = @@gettext_untranslate_columns[self] || [] ary.include?(columnname) end def self.untranslate_data #:nodoc: [@@gettext_untranslate[self], @@gettext_untranslate_columns[self] || []] end def self.columns unless defined? @columns @columns = nil end unless @columns @columns = connection.columns(table_name, "#{name} Columns") @columns.each {|column| column.table_class = self column.primary = column.name == primary_key } end @columns end # call-seq: # set_error_message_title(msg) # # ((*Deprecated*)) # Use ActionView::Helpers::ActiveRecordHelper::L10n.set_error_message_title # instead. # # Sets a your own title of error message dialog. # * msg: [single_msg, plural_msg]. Usually you need to call this with Nn_(). # * Returns: [single_msg, plural_msg] def self.set_error_message_title(msg, plural_msg = nil) ActionView::Helpers::ActiveRecordHelper::L10n.set_error_message_title(msg, plural_msg) end # call-seq: # set_error_message_explanation(msg) # # ((*Deprecated*)) # Use ActionView::Helpers::ActiveRecordHelper::L10n.set_error_message_explanation # instead. # # Sets a your own explanation of the error message dialog. # * msg: [single_msg, plural_msg]. Usually you need to call this with Nn_(). # * Returns: [single_msg, plural_msg] def self.set_error_message_explanation(msg, plural_msg = nil) ActionView::Helpers::ActiveRecordHelper::L10n.set_error_message_explanation(msg, plural_msg) end end # activerecord-1.14.3/lib/active_record/validations.rb class Errors #:nodoc: include GetText alias initialize_without_locale initialize #:nodoc: alias full_messages_without_localized full_messages #:nodoc: def initialize(base) # :nodoc: initialize_without_locale(base) bindtextdomain("rails") end def @@default_error_messages.[]=(id, msg) #:nodoc: @@default_error_messages.update({id => msg}) if [:message, :too_long, :too_short, :wrong_length].include?(id) @@default_error_messages_d[msg] = /\A#{Regexp.escape(msg).sub(/%d/, '(\d+)')}\Z/ end end # You need to define this here, because this values will be updated by application. default_error_messages.update( :inclusion => N_("%{fn} is not included in the list"), :exclusion => N_("%{fn} is reserved"), :invalid => N_("%{fn} is invalid"), :confirmation => N_("%{fn} doesn't match confirmation"), :accepted => N_("%{fn} must be accepted"), :empty => N_("%{fn} can't be empty"), :blank => N_("%{fn} can't be blank"), :too_long => N_("%{fn} is too long (maximum is %d characters)"), :too_short => N_("%{fn} is too short (minimum is %d characters)"), :wrong_length => N_("%{fn} is the wrong length (should be %d characters)"), :taken => N_("%{fn} has already been taken"), :not_a_number => N_("%{fn} is not a number") ) @@default_error_messages_d = { default_error_messages[:too_long] => /#{Regexp.escape(default_error_messages[:too_long]).sub(/%d/, '(\d+)')}/, default_error_messages[:too_short] => /#{Regexp.escape(default_error_messages[:too_short]).sub(/%d/, '(\d+)')}/, default_error_messages[:wrong_length] => /#{Regexp.escape(default_error_messages[:wrong_length]).sub(/%d/, '(\d+)')}/, } cattr_accessor :default_error_messages_d def localize_error_messages(append_field = true) # :nodoc: # e.g.) foo field: "%{fn} foo" => "Foo foo", "foo" => "Foo foo". errors = {} @errors.each_key do |attr| @errors[attr].each do |msg| next if msg.nil? custom_msg = nil #Ugly but... :-< @@default_error_messages_d.dup.merge(@base.custom_error_messages_d).each do |key, regexp| if regexp =~ msg custom_msg = @base.gettext(key) custom_msg = _(msg) if custom_msg == msg custom_msg = _(custom_msg) % $1.to_i break end end unless custom_msg custom_msg = @base.gettext(msg) custom_msg = _(msg) if custom_msg == msg end if attr == "base" full_message = custom_msg elsif /%\{fn\}/ =~ custom_msg full_message = custom_msg % {:fn => @base.class.human_attribute_name(attr)} elsif append_field full_message = @base.class.human_attribute_name(attr) + " " + custom_msg else full_message = custom_msg end errors[attr] ||= [] errors[attr] << full_message end end errors end # Returns error messages. # * Returns nil, if no errors are associated with the specified attribute. # * Returns the error message, if one error is associated with the specified attribute. # * Returns an array of error messages, if more than one error is associated with the specified attribute. # And for GetText, # * If the error messages include %{fn}, it returns formatted text such as "foo %{fn}" => "foo Field" # * else, the error messages are prepended the field name such as "foo" => "foo" (Same as default behavior). # Note that this behaviour is different from full_messages. def on(attribute) # e.g.) foo field: "%{fn} foo" => "Foo foo", "foo" => "foo". errors = localize_error_messages(false) if errors[attribute.to_s].nil? nil elsif errors[attribute.to_s].length == 1 errors[attribute.to_s].first else errors[attribute.to_s] end end # Returns all the full error messages in an array. # * If the error messages include %{fn}, it returns formatted text such as "foo %{fn}" => "foo Field" # * else, the error messages are prepended the field name such as "foo" => "Field foo" (Same as default behavior). # As L10n, first one is recommanded because the order of subject,verb and others are not same in languages. def full_messages full_messages = [] errors = localize_error_messages errors.each_key do |attr| errors[attr].each do |msg| next if msg.nil? full_messages << msg end end full_messages end end end