Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Implemented lambda support for #localize. Some refactoring.
  • Loading branch information
clemens authored and Sven Fuchs committed Apr 30, 2009
1 parent 38d85ea commit 9d390af
Show file tree
Hide file tree
Showing 2 changed files with 50 additions and 23 deletions.
41 changes: 18 additions & 23 deletions lib/i18n/backend/simple.rb
Expand Up @@ -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
Expand All @@ -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 (<em>e.g.</em>, <tt>:short</tt> in <tt>:'date.formats'</tt>).
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
Expand Down Expand Up @@ -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.
#
# <em>I.e.</em>, <tt>default(locale, [:foo, 'default'])</tt> will return +default+ if
# <em>I.e.</em>, <tt>resolve(locale, [:foo, 'default'])</tt> will return +default+ if
# <tt>translate(locale, :foo)</tt> 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
Expand Down
32 changes: 32 additions & 0 deletions test/simple_backend_test.rb
Expand Up @@ -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),
Expand All @@ -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'
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down

0 comments on commit 9d390af

Please sign in to comment.