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