From 71f2a434247683368e470f34efc106f828d859d8 Mon Sep 17 00:00:00 2001 From: Adam Meehan Date: Wed, 3 Dec 2008 18:20:34 +1100 Subject: [PATCH] added i18n support for error messages in Rails 2.2 --- README | 22 +++++++++++-- lib/validates_timeliness.rb | 31 ++++++++++++------- lib/validates_timeliness/locale/en.yml | 11 +++++++ .../rails/matchers/validate_timeliness.rb | 2 +- lib/validates_timeliness/validator.rb | 23 +++++++++----- 5 files changed, 66 insertions(+), 23 deletions(-) create mode 100644 lib/validates_timeliness/locale/en.yml diff --git a/README b/README index 532a81f..520a658 100644 --- a/README +++ b/README @@ -1,7 +1,7 @@ = validates_timeliness * Source: http://github.com/adzap/validates_timeliness - * Tickets: http://adzap.lighthouseapp.com/projects/14111-validates_timeliness + * Bugs: http://adzap.lighthouseapp.com/projects/14111-validates_timeliness == DESCRIPTION: @@ -249,6 +249,8 @@ return nil in all other situations. Restrictions are skipped if they are nil. The error messages for each temporal restrictions can also be globally overridden by updating the default AR error messages like so +For Rails 2.0/2.1: + ActiveRecord::Errors.default_error_messages.update( :invalid_date => "is not a valid date", :invalid_time => "is not a valid time", @@ -259,8 +261,22 @@ updating the default AR error messages like so :on_or_after => "must be on or after %s" ) -Or for something a little more specific you can override the format of the values -inserted in the error messages for temporal restrictions like so +Where %s is the interpolation value for the restriction. + +Rails 2.2+ using the I18n system to define new defaults: + + en: + activerecord: + errors: + messages: + on_or_before: "must equal to or before {{restriction}}" + on_or_after: "must equal to or after {{restriction}}" + +The {{restriction}} signifies where the interpolation value for the restriction +will be inserted. + +And for something a little more specific you can override the format of the interpolation +values inserted in the error messages for temporal restrictions like so ValidatesTimeliness.error_value_formats.update( :time => '%H:%M:%S', diff --git a/lib/validates_timeliness.rb b/lib/validates_timeliness.rb index ecc2543..511aec9 100644 --- a/lib/validates_timeliness.rb +++ b/lib/validates_timeliness.rb @@ -26,7 +26,6 @@ module ValidatesTimeliness mattr_accessor :ignore_restriction_errors mattr_accessor :error_value_formats - mattr_accessor :default_error_messages @@ignore_restriction_errors = false @@ -36,16 +35,24 @@ module ValidatesTimeliness :datetime => '%Y-%m-%d %H:%M:%S' } - @@default_error_messages = { - :empty => "cannot be empty", - :blank => "cannot be blank", - :invalid_date => "is not a valid date", - :invalid_time => "is not a valid time", - :invalid_datetime => "is not a valid datetime", - :before => "must be before %s", - :on_or_before => "must be on or before %s", - :after => "must be after %s", - :on_or_after => "must be on or after %s" - } + def self.load_error_messages + path = File.expand_path(File.dirname(__FILE__) + '/validates_timeliness/locale/en.yml') + if Rails::VERSION::STRING < '2.2' + messages = YAML::load(IO.read(path)) + errors = messages['en']['activerecord']['errors']['messages'].inject({}) {|h,(k,v)| h[k.to_sym] = v.gsub(/\{\{\w*\}\}/, '%s');h } + ::ActiveRecord::Errors.default_error_messages.update(errors) + else + I18n.load_path += [ path ] + end + end + def self.default_error_messages + if Rails::VERSION::STRING < '2.2' + ::ActiveRecord::Errors.default_error_messages + else + I18n.translate('activerecord.errors.messages') + end + end end + +ValidatesTimeliness.load_error_messages diff --git a/lib/validates_timeliness/locale/en.yml b/lib/validates_timeliness/locale/en.yml new file mode 100644 index 0000000..1c5e63c --- /dev/null +++ b/lib/validates_timeliness/locale/en.yml @@ -0,0 +1,11 @@ +en: + activerecord: + errors: + messages: + invalid_date: "is not a valid date" + invalid_time: "is not a valid time" + invalid_datetime: "is not a valid datetime" + before: "must be before {{restriction}}" + on_or_before: "must be on or before {{restriction}}" + after: "must be after {{restriction}}" + on_or_after: "must be on or after {{restriction}}" diff --git a/lib/validates_timeliness/spec/rails/matchers/validate_timeliness.rb b/lib/validates_timeliness/spec/rails/matchers/validate_timeliness.rb index 07f9213..10c7bad 100644 --- a/lib/validates_timeliness/spec/rails/matchers/validate_timeliness.rb +++ b/lib/validates_timeliness/spec/rails/matchers/validate_timeliness.rb @@ -18,7 +18,7 @@ module Spec def compile_error_messages validator = ValidatesTimeliness::Validator.new(options) messages = validator.send(:error_messages) - @messages = messages.inject({}) {|h, (k, v)| h[k] = v.sub(' %s', ''); h } + @messages = messages.inject({}) {|h, (k, v)| h[k] = v.gsub(/ (\%s|\{\{\w*\}\})/, ''); h } end def matches?(record) diff --git a/lib/validates_timeliness/validator.rb b/lib/validates_timeliness/validator.rb index d0c6582..b18c866 100644 --- a/lib/validates_timeliness/validator.rb +++ b/lib/validates_timeliness/validator.rb @@ -48,7 +48,7 @@ module ValidatesTimeliness compare = compare.send(type_cast_method) unless value.send(method, compare) - add_error(record, attr_name, error_messages[option] % compare.strftime(display)) + add_error(record, attr_name, option, :restriction => compare.strftime(display)) end rescue unless ValidatesTimeliness.ignore_restriction_errors @@ -58,16 +58,25 @@ module ValidatesTimeliness end end - def add_error(record, attr_name, message) - message = error_messages[message] if message.is_a?(Symbol) - record.errors.add(attr_name, message) + def add_error(record, attr_name, message, interpolate={}) + if Rails::VERSION::STRING < '2.2' + message = error_messages[message] if message.is_a?(Symbol) + message = message % interpolate.values unless interpolate.empty? + record.errors.add(attr_name, message) + else + custom = custom_error_messages[message] + record.errors.add(attr_name, custom || message, interpolate) + end end def error_messages return @error_messages if defined?(@error_messages) - custom = {} - configuration.each {|k, v| custom[$1.to_sym] = v if k.to_s =~ /(.*)_message$/ } - @error_messages = ValidatesTimeliness.default_error_messages.merge(custom) + @error_messages = ValidatesTimeliness.default_error_messages.merge(custom_error_messages) + end + + def custom_error_messages + return @custom_error_messages if defined?(@custom_error_messages) + @custom_error_messages = configuration.inject({}) {|h, (k, v)| h[$1.to_sym] = v if k.to_s =~ /(.*)_message$/;h } end def self.restriction_value(restriction, record, type)