Skip to content

Commit

Permalink
Add handle_exception method for more flexible custom exception handling.
Browse files Browse the repository at this point in the history
Add translate! and t! (calling translate with :raise => true)
  • Loading branch information
abriening authored and Sven Fuchs committed Jul 12, 2009
1 parent b2ae8de commit da3d851
Show file tree
Hide file tree
Showing 2 changed files with 58 additions and 5 deletions.
42 changes: 37 additions & 5 deletions lib/i18n.rb
Expand Up @@ -176,13 +176,13 @@ def reload!
# *LAMBDAS*
#
# Both translations and defaults can be given as Ruby lambdas. Lambdas will be
# called and passed the key and options.
# called and passed the key and options.
#
# E.g. assuming the key <tt>:salutation</tt> resolves to:
# lambda { |key, options| options[:gender] == 'm' ? "Mr. {{options[:name]}}" : "Mrs. {{options[:name]}}" }
#
# Then <tt>I18n.t(:salutation, :gender => 'w', :name => 'Smith') will result in "Mrs. Smith".
#
#
# It is recommended to use/implement lambdas in an "idempotent" way. E.g. when
# a cache layer is put in front of I18n.translate it will generate a cache key
# from the argument values passed to #translate. Therefor your lambdas should
Expand All @@ -193,12 +193,17 @@ def translate(*args)
key = args.shift
locale = options.delete(:locale) || I18n.locale
backend.translate(locale, key, options)
rescue I18n::ArgumentError => e
raise e if options[:raise]
send(@@exception_handler, e, locale, key, options)
rescue I18n::ArgumentError => exception
raise exception if options[:raise]
handle_exception(exception, locale, key, options)
end
alias :t :translate

def translate!(key, options = {})
translate(key, options.merge( :raise => true ))
end
alias :t! :translate!

# Localizes certain objects, such as dates and numbers to local formatting.
def localize(object, options = {})
locale = options[:locale] || I18n.locale
Expand All @@ -208,6 +213,7 @@ def localize(object, options = {})
alias :l :localize

protected

# Handles exceptions raised in the backend. All exceptions except for
# MissingTranslationData exceptions are re-raised. When a MissingTranslationData
# was caught and the option :raise is not set the handler returns an error
Expand All @@ -217,6 +223,32 @@ def default_exception_handler(exception, locale, key, options)
raise exception
end

# Any exceptions thrown in translate will be sent to the @@exception_handler
# which can be a Symbol, a Proc or any other Object.
#
# If exception_handler is a Symbol then it will simply be sent to I18n as
# a method call. A Proc will simply be called. In any other case the
# method #call will be called on the exception_handler object.
#
# Examples:
#
# I18n.exception_handler = :default_exception_handler # this is the default
# I18n.default_exception_handler(exception, locale, key, options) # will be called like this
#
# I18n.exception_handler = lambda { |*args| ... } # a lambda
# I18n.exception_handler.call(exception, locale, key, options) # will be called like this
#
# I18n.exception_handler = I18nExceptionHandler.new # an object
# I18n.exception_handler.call(exception, locale, key, options) # will be called like this
def handle_exception(exception, locale, key, options)
case @@exception_handler
when Symbol
send(@@exception_handler, exception, locale, key, options)
else
@@exception_handler.call(exception, locale, key, options)
end
end

# Merges the given locale, key and scope into a single array of keys.
# Splits keys that contain dots into multiple keys. Makes sure all
# keys are Symbols.
Expand Down
21 changes: 21 additions & 0 deletions test/i18n_test.rb
Expand Up @@ -137,4 +137,25 @@ def test_localize_nil_raises_argument_error
def test_localize_object_raises_argument_error
assert_raises(I18n::ArgumentError) { I18n.l Object.new }
end

def test_proc_exception_handler
I18n.exception_handler = Proc.new { |exception, locale, key, options|
"No exception here! [Proc handler]"
}
assert_equal "No exception here! [Proc handler]", I18n.translate(:test_proc_handler)
ensure
I18n.exception_handler = :default_exception_handler
end

def test_class_exception_handler
I18n.exception_handler = Class.new do
def call(exception, locale, key, options)
"No exception here! [Class handler]"
end
end.new
assert_equal "No exception here! [Class handler]", I18n.translate(:test_class_handler)
ensure
I18n.exception_handler = :default_exception_handler
end

end

0 comments on commit da3d851

Please sign in to comment.