From 2571a1b84df95e8952c88093ce01bd2a79b9ee71 Mon Sep 17 00:00:00 2001 From: Sven Fuchs Date: Tue, 24 Jun 2008 14:01:04 +0200 Subject: [PATCH] standarize on raising exceptions for wrong arguments in favor of silently returning nil, interpolating non-existing values etc. --- lib/i18n.rb | 7 +++++++ lib/i18n/backend/simple.rb | 20 ++++++++++++-------- test/i18n_test.rb | 23 +++++++++++------------ test/simple_backend_test.rb | 33 ++++++++++++++++++--------------- 4 files changed, 48 insertions(+), 35 deletions(-) diff --git a/lib/i18n.rb b/lib/i18n.rb index 98730511..3fa8818a 100755 --- a/lib/i18n.rb +++ b/lib/i18n.rb @@ -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' diff --git a/lib/i18n/backend/simple.rb b/lib/i18n/backend/simple.rb index a89b741b..e53b3fe2 100644 --- a/lib/i18n/backend/simple.rb +++ b/lib/i18n/backend/simple.rb @@ -2,8 +2,6 @@ module I18n module Backend - class ReservedInterpolationKey < ArgumentError; end - module Simple @@translations = {} @@ -24,7 +22,7 @@ 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 @@ -32,7 +30,7 @@ def translate(key, locale, options = {}) 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 @@ -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 (e.g., :short in :'date.formats'). 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] @@ -84,6 +84,8 @@ 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 @@ -91,7 +93,8 @@ def default(locale, default, options = {}) # 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 @@ -104,7 +107,7 @@ def pluralize(entry, count) # the {{...}} 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]} @@ -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 diff --git a/test/i18n_test.rb b/test/i18n_test.rb index dd4d8514..3d6d91d6 100644 --- a/test/i18n_test.rb +++ b/test/i18n_test.rb @@ -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 diff --git a/test/simple_backend_test.rb b/test/simple_backend_test.rb index 3e69ee2b..efd5944e 100644 --- a/test/simple_backend_test.rb +++ b/test/simple_backend_test.rb @@ -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 @@ -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 @@ -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 @@ -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