Navigation Menu

Skip to content

Commit

Permalink
standarize on raising exceptions for wrong arguments
Browse files Browse the repository at this point in the history
in favor of silently returning nil, interpolating non-existing values etc.
  • Loading branch information
Sven Fuchs committed Jun 24, 2008
1 parent 61b91d9 commit 2571a1b
Show file tree
Hide file tree
Showing 4 changed files with 48 additions and 35 deletions.
7 changes: 7 additions & 0 deletions lib/i18n.rb
Expand Up @@ -9,6 +9,13 @@
require 'i18n/backend/simple'

module I18n
class ArgumentError < StandardError; end
class InvalidLocale < ArgumentError; end
class MissingTranslationData < ArgumentError; end
class InvalidPluralizationData < ArgumentError; end
class MissingInterpolationArgument < ArgumentError; end
class ReservedInterpolationKey < ArgumentError; end

@@backend = Backend::Simple
@@default_locale = 'en-US'

Expand Down
20 changes: 12 additions & 8 deletions lib/i18n/backend/simple.rb
Expand Up @@ -2,8 +2,6 @@

module I18n
module Backend
class ReservedInterpolationKey < ArgumentError; end

module Simple
@@translations = {}

Expand All @@ -24,15 +22,15 @@ def store_translations(locale, data)
end

def translate(key, locale, options = {})
raise ArgumentError, 'locale is nil in I18n::Backend::Simple#translate' if locale.nil?
raise InvalidLocale, 'locale is nil in I18n::Backend::Simple#translate' if locale.nil?
return key.map{|key| translate key, locale, options } if key.is_a? Array

reserved = :scope, :default
count, scope, default = options.values_at(:count, *reserved)
options.delete(:default)
values = options.reject{|name, value| reserved.include? name }

entry = lookup(locale, key, scope) || default(locale, default, options)
entry = lookup(locale, key, scope) || default(locale, default, options) || raise(I18n::MissingTranslationData, "translation data missing for #{normalize_keys(locale, key, scope).inspect}")
entry = pluralize entry, count
entry = interpolate entry, values
entry
Expand All @@ -42,6 +40,8 @@ def translate(key, locale, options = {})
# 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(object, locale = nil, format = :default)
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'
formats = :"#{type}.formats".t locale
format = formats[format.to_sym] if formats && formats[format.to_sym]
Expand Down Expand Up @@ -84,14 +84,17 @@ def default(locale, default, options = {})
result = default(locale, obj, options.dup) and return result
end
end
rescue MissingTranslationData
nil
end

# Picks a translation from an array according to English pluralization
# rules. It will pick the first translation if count is not equal to 1
# and the second translation if it is equal to 1. Other backends can
# implement more flexible or complex pluralization rules.
def pluralize(entry, count)
return entry unless entry.is_a?(Array) and count and entry.size == 2
return entry unless entry.is_a?(Array) and count
raise InvalidPluralizationData, "translation data #{entry} can not be used with :count => #{count}" unless entry.size == 2
entry[count == 1 ? 0 : 1]
end

Expand All @@ -104,7 +107,7 @@ def pluralize(entry, count)
# the <tt>{{...}}</tt> key in a string (once for the string and once for the
# interpolation).
def interpolate(string, values = {})
return string if !string.is_a?(String) or values.empty?
return string if !string.is_a?(String)

map = {'%d' => '{{count}}', '%s' => '{{value}}'} # TODO deprecate this?
string.gsub!(/#{map.keys.join('|')}/){|key| map[key]}
Expand All @@ -117,8 +120,9 @@ def interpolate(string, values = {})
end_pos = s.pos - 1

raise ReservedInterpolationKey, %s(reserved key :#{key} used in "#{string}") if %w(scope default).include?(key)

s.string[start_pos..end_pos] = values[key.to_sym].to_s if values.has_key? key.to_sym
raise MissingInterpolationArgument, %s(interpolation argument #{key} missing in "#{string}") unless values.has_key? key.to_sym

s.string[start_pos..end_pos] = values[key.to_sym].to_s
s.unscan
end
s.string
Expand Down
23 changes: 11 additions & 12 deletions test/i18n_test.rb
Expand Up @@ -95,24 +95,23 @@ def test_translate_with_options_using_scope_works
end
end

def test_translate_no_args
assert_raises(ArgumentError) { I18n.t }
def test_translate_given_no_args_raises_missing_translation_data
assert_raises(I18n::MissingTranslationData){ I18n.t }
end

def test_translate_given_a_bogus_key_raises_missing_translation_data
assert_raises(I18n::MissingTranslationData){ I18n.t :bogus }
end

def test_localize_no_args
def test_localize_given_no_args_raises_argument_error
assert_raises(ArgumentError) { I18n.l }
end

def test_translate_just_key
assert_equal :bogus_key, I18n.t(:bogus_key)
end

def test_localize_nil
assert_nil I18n.l(nil)
def test_localize_nil_raises_argument_error
assert_raises(I18n::ArgumentError) { I18n.l nil }
end

def test_localize_object
obj = Object.new
assert_equal obj, I18n.l(obj)
def test_localize_object_raises_argument_error
assert_raises(I18n::ArgumentError) { I18n.l Object.new }
end
end
33 changes: 18 additions & 15 deletions test/simple_backend_test.rb
Expand Up @@ -80,18 +80,13 @@ def test_store_translations_covert_key_symbols
assert_equal Hash[:'en-US', {:foo => {:bar => 'baz'}}],
@backend.send(:class_variable_get, :@@translations)
end

end

class I18nSimpleBackendTranslateTest < Test::Unit::TestCase
include I18nSimpleBackendTestSetup

def test_translate_given_nil_as_a_locale_raises_an_argument_error
assert_raises(ArgumentError){ @backend.translate :bar, nil }
end


def test_translate_calls_lookup_with_locale_given
@backend.expects(:lookup).with 'de-DE', :bar, [:foo]
@backend.expects(:lookup).with('de-DE', :bar, [:foo]).returns 'bar'
@backend.translate :bar, 'de-DE', :scope => [:foo]
end

Expand Down Expand Up @@ -125,6 +120,14 @@ def test_translate_calls_interpolate_including_count_as_a_value
def test_given_no_keys_it_returns_the_default
assert_equal 'default', @backend.translate(nil, 'en-US', :default => 'default')
end

def test_translate_given_nil_as_a_locale_raises_an_argument_error
assert_raises(I18n::InvalidLocale){ @backend.translate :bar, nil }
end

def test_translate_with_a_bogus_key_and_no_default_raises_missing_translation_data
assert_raises(I18n::MissingTranslationData){ @backend.translate :bogus, 'de-DE' }
end
end

class I18nSimpleBackendLookupTest < Test::Unit::TestCase
Expand Down Expand Up @@ -163,8 +166,8 @@ def test_pluralize_given_3_returns_plural_string
assert_equal 'bars', @backend.send(:pluralize, ['bar', 'bars'], 3)
end

def test_pluralize_given_2_with_invalid_pluralization_data
assert_equal ['bar'], @backend.send(:pluralize, ['bar'], 2)
def test_interpolate_given_invalid_pluralization_data_raises_invalid_pluralization_data
assert_raises(I18n::InvalidPluralizationData){ @backend.send(:pluralize, ['bar'], 2) }
end
end

Expand All @@ -183,16 +186,16 @@ def test_interpolate_given_an_non_string_as_a_string_returns_nil
assert_equal [], @backend.send(:interpolate, [], :name => 'David')
end

def test_interpolate_given_an_empty_values_hash_returns_the_unmodified_string
assert_equal 'Hi {{name}}!', @backend.send(:interpolate, 'Hi {{name}}!', {})
end

def test_interpolate_given_a_values_hash_with_nil_values_interpolates_the_string
assert_equal 'Hi !', @backend.send(:interpolate, 'Hi {{name}}!', {:name => nil})
end

def test_interpolate_given_a_string_containing_a_reserved_key_raises_an_exception
assert_raises(I18n::Backend::ReservedInterpolationKey) { @backend.send(:interpolate, '{{default}}', {:default => nil}) }
def test_interpolate_given_an_empty_values_hash_raises_missing_interpolation_argument
assert_raises(I18n::MissingInterpolationArgument) { @backend.send(:interpolate, 'Hi {{name}}!', {}) }
end

def test_interpolate_given_a_string_containing_a_reserved_key_raises_reserved_interpolation_key
assert_raises(I18n::ReservedInterpolationKey) { @backend.send(:interpolate, '{{default}}', {:default => nil}) }
end
end

Expand Down

0 comments on commit 2571a1b

Please sign in to comment.