From 9d390afcf33f3f469bb95e6888147152f6cc7442 Mon Sep 17 00:00:00 2001 From: Clemens Kofler Date: Fri, 17 Apr 2009 13:19:08 +0200 Subject: [PATCH] Implemented lambda support for #localize. Some refactoring. --- lib/i18n/backend/simple.rb | 41 ++++++++++++++++--------------------- test/simple_backend_test.rb | 32 +++++++++++++++++++++++++++++ 2 files changed, 50 insertions(+), 23 deletions(-) diff --git a/lib/i18n/backend/simple.rb b/lib/i18n/backend/simple.rb index c09acd7d..83eba417 100644 --- a/lib/i18n/backend/simple.rb +++ b/lib/i18n/backend/simple.rb @@ -27,16 +27,10 @@ def translate(locale, key, options = {}) reserved = :scope, :default count, scope, default = options.values_at(:count, *reserved) - options.delete(:default) + default = options.delete(:default) values = options.reject { |name, value| reserved.include?(name) } - entry = lookup(locale, key, scope) - if entry.nil? - entry = default(locale, default, options) - if entry.nil? - raise(I18n::MissingTranslationData.new(locale, key, options)) - end - end + entry = lookup(locale, key, scope) || resolve(locale, key, default, options) || raise(I18n::MissingTranslationData.new(locale, key, options)) entry = pluralize(locale, entry, count) entry = interpolate(locale, entry, values) entry @@ -45,14 +39,14 @@ def translate(locale, key, options = {}) # Acts the same as +strftime+, but returns a localized version of the # formatted date string. Takes a key from the date/time formats # translations as a format argument (e.g., :short in :'date.formats'). - def localize(locale, object, format = :default) + def localize(locale, object, format = :default, options={}) raise ArgumentError, "Object must be a Date, DateTime or Time object. #{object.inspect} given." unless object.respond_to?(:strftime) - type = object.respond_to?(:sec) ? 'time' : 'date' - # TODO only translate these if format is a String? - formats = translate(locale, :"#{type}.formats") - format = formats[format.to_sym] if formats && formats[format.to_sym] - # TODO raise exception unless format found? + if Symbol === format + type = object.respond_to?(:sec) ? 'time' : 'date' + format = lookup(locale, :"#{type}.formats.#{format}") + end + format = resolve(locale, object, format, options.merge(:raise => true)) format = format.to_s.dup # TODO only translate these if the format string is actually present @@ -108,19 +102,20 @@ def lookup(locale, key, scope = []) end end - # Evaluates a default translation. + # Resolves a translation. # If the given default is a String it is used literally. If it is a Symbol # it will be translated with the given options. If it is an Array the first - # translation yielded will be returned. + # translation yielded will be returned. If it is a Proc then it is evaluated. # - # I.e., default(locale, [:foo, 'default']) will return +default+ if + # I.e., resolve(locale, [:foo, 'default']) will return +default+ if # translate(locale, :foo) does not yield a result. - def default(locale, default, options = {}) - case default - when String then default - when Symbol then translate locale, default, options - when Array then default.each do |obj| - result = default(locale, obj, options.dup) and return result + def resolve(locale, object, subject, options = {}) + case subject + when String then subject + when Symbol then translate locale, subject, options + when Proc then subject.call object, options + when Array then subject.each do |subject| + result = resolve(locale, object, subject, options.dup) and return result end and nil end rescue MissingTranslationData diff --git a/test/simple_backend_test.rb b/test/simple_backend_test.rb index 7b7b1375..49ad828b 100644 --- a/test/simple_backend_test.rb +++ b/test/simple_backend_test.rb @@ -33,6 +33,10 @@ def add_datetime_translations :default => "%d.%m.%Y", :short => "%d. %b", :long => "%d. %B %Y", + :long_ordinalized => lambda { |date, options| + tz = " (#{options[:timezone]})" if options[:timezone] + "#{date.day}ter %B %Y#{tz}" + } }, :day_names => %w(Sonntag Montag Dienstag Mittwoch Donnerstag Freitag Samstag), :abbr_day_names => %w(So Mo Di Mi Do Fr Sa), @@ -45,6 +49,10 @@ def add_datetime_translations :default => "%a, %d. %b %Y %H:%M:%S %z", :short => "%d. %b %H:%M", :long => "%d. %B %Y %H:%M", + :long_ordinalized => lambda { |date, options| + tz = " (#{options[:timezone]})" if options[:timezone] + "#{date.day}ter %B %Y, %H:%M Uhr#{tz}" + } }, :am => 'am', :pm => 'pm' @@ -343,6 +351,14 @@ def test_translate_given_an_abbr_month_name_format_it_returns_an_abbrevated_mont assert_equal 'Jan', @backend.localize('de', @date, '%b') end + def test_translate_given_a_format_specified_as_a_proc + assert_equal '1ter Januar 2008', @backend.localize('de', @date, :long_ordinalized) + end + + def test_translate_given_a_format_specified_as_a_proc_with_additional_options + assert_equal '1ter Januar 2008 (MEZ)', @backend.localize('de', @date, :long_ordinalized, :timezone => 'MEZ') + end + def test_translate_given_no_format_it_does_not_fail assert_nothing_raised{ @backend.localize 'de', @date } end @@ -403,6 +419,14 @@ def test_translate_given_a_meridian_indicator_format_it_returns_the_correct_meri assert_equal 'pm', @backend.localize('de', @evening, '%p') end + def test_translate_given_a_format_specified_as_a_proc + assert_equal '1ter Januar 2008, 06:00 Uhr', @backend.localize('de', @morning, :long_ordinalized) + end + + def test_translate_given_a_format_specified_as_a_proc_with_additional_options + assert_equal '1ter Januar 2008, 06:00 Uhr (MEZ)', @backend.localize('de', @morning, :long_ordinalized, :timezone => 'MEZ') + end + def test_translate_given_no_format_it_does_not_fail assert_nothing_raised{ @backend.localize 'de', @morning } end @@ -461,6 +485,14 @@ def test_translate_given_a_meridian_indicator_format_it_returns_the_correct_meri assert_equal 'pm', @backend.localize('de', @evening, '%p') end + def test_translate_given_a_format_specified_as_a_proc + assert_equal '1ter Januar 2008, 06:00 Uhr', @backend.localize('de', @morning, :long_ordinalized) + end + + def test_translate_given_a_format_specified_as_a_proc_with_additional_options + assert_equal '1ter Januar 2008, 06:00 Uhr (MEZ)', @backend.localize('de', @morning, :long_ordinalized, :timezone => 'MEZ') + end + def test_translate_given_no_format_it_does_not_fail assert_nothing_raised{ @backend.localize 'de', @morning } end