Skip to content

Commit

Permalink
enable I18n.t to use throw as an error handling strategy and use it i…
Browse files Browse the repository at this point in the history
…n I18n::Backend::Base.resolve for re-translating symbols
  • Loading branch information
Sven Fuchs committed Apr 23, 2011
1 parent d390694 commit 4028976
Show file tree
Hide file tree
Showing 5 changed files with 43 additions and 38 deletions.
42 changes: 23 additions & 19 deletions lib/i18n.rb
Expand Up @@ -9,7 +9,7 @@ module I18n
autoload :Locale, 'i18n/locale'
autoload :Tests, 'i18n/tests'

RESERVED_KEYS = [:scope, :default, :separator, :resolve, :object, :fallback, :format, :cascade, :raise, :rescue_format]
RESERVED_KEYS = [:scope, :default, :separator, :resolve, :object, :fallback, :format, :cascade, :throw, :raise, :rescue_format]
RESERVED_KEYS_PATTERN = /%\{(#{RESERVED_KEYS.join("|")})\}/

class << self
Expand Down Expand Up @@ -141,26 +141,22 @@ def reload!
# always return the same translations/values per unique combination of argument
# values.
def translate(*args)
options = args.last.is_a?(Hash) ? args.pop : {}
key = args.shift
backend = config.backend
locale = options.delete(:locale) || config.locale
raises = options.delete(:raise)
options = args.last.is_a?(Hash) ? args.pop : {}
key = args.shift
backend = config.backend
locale = options.delete(:locale) || config.locale
handling = options.delete(:throw) && :throw || options.delete(:raise) && :raise # TODO deprecate :raise

raise I18n::ArgumentError if key.is_a?(String) && key.empty?

result = catch(:missing_translation) do
result = catch(:exception) do
if key.is_a?(Array)
key.map { |k| backend.translate(locale, k, options) }
else
backend.translate(locale, key, options)
end
end
result.is_a?(Exception) ? raise(result) : result

rescue I18n::ArgumentError => exception
raise exception if raises
handle_exception(exception, locale, key, options)
result.is_a?(MissingTranslationData) ? handle_exception(handling, result, locale, key, options) : result
end
alias :t :translate

Expand Down Expand Up @@ -269,7 +265,8 @@ def normalize_keys(locale, key, scope, separator = nil)
private

# Any exceptions thrown in translate will be sent to the @@exception_handler
# which can be a Symbol, a Proc or any other Object.
# which can be a Symbol, a Proc or any other Object unless they're forced to
# be raised or thrown (MissingTranslationData).
#
# 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
Expand All @@ -285,12 +282,19 @@ def normalize_keys(locale, key, scope, separator = nil)
#
# 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 handler = options[:exception_handler] || config.exception_handler
when Symbol
send(handler, exception, locale, key, options)
def handle_exception(handling, exception, locale, key, options)
case handling
when :raise
raise exception
when :throw
throw :exception, exception
else
handler.call(exception, locale, key, options)
case handler = options[:exception_handler] || config.exception_handler
when Symbol
send(handler, exception, locale, key, options)
else
handler.call(exception, locale, key, options)
end
end
end

Expand All @@ -302,7 +306,7 @@ def normalize_key(key, separator)
else
keys = key.to_s.split(separator)
keys.delete('')
keys.map!{ |k| k.to_sym }
keys.map! { |k| k.to_sym }
keys
end
end
Expand Down
23 changes: 12 additions & 11 deletions lib/i18n/backend/base.rb
Expand Up @@ -34,7 +34,7 @@ def translate(locale, key, options = {})
default(locale, key, default, options) : resolve(locale, key, entry, options)
end

throw(:missing_translation, I18n::MissingTranslationData.new(locale, key, options)) if entry.nil?
throw(:exception, I18n::MissingTranslationData.new(locale, key, options)) if entry.nil?
entry = entry.dup if entry.is_a?(String)

entry = pluralize(locale, entry, count) if count
Expand Down Expand Up @@ -108,17 +108,18 @@ def default(locale, object, subject, options = {})
# subjects will be returned directly.
def resolve(locale, object, subject, options = {})
return subject if options[:resolve] == false
case subject
when Symbol
I18n.translate(subject, options.merge(:locale => locale, :raise => true))
when Proc
date_or_time = options.delete(:object) || object
resolve(locale, object, subject.call(date_or_time, options))
else
subject
result = catch(:exception) do
case subject
when Symbol
I18n.translate(subject, options.merge(:locale => locale, :throw => true))
when Proc
date_or_time = options.delete(:object) || object
resolve(locale, object, subject.call(date_or_time, options))
else
subject
end
end
rescue MissingTranslationData
nil
result unless result.is_a?(MissingTranslationData)
end

# Picks a translation from an array according to English pluralization
Expand Down
4 changes: 2 additions & 2 deletions lib/i18n/backend/cache.rb
Expand Up @@ -70,14 +70,14 @@ def translate(locale, key, options = {})

def fetch(cache_key, &block)
result = _fetch(cache_key, &block)
throw(:missing_translation, result) if result.is_a?(MissingTranslationData)
throw(:exception, result) if result.is_a?(MissingTranslationData)
result = result.dup if result.frozen? rescue result
result
end

def _fetch(cache_key, &block)
result = I18n.cache_store.read(cache_key) and return result
result = catch(:missing_translation, &block)
result = catch(:exception, &block)
I18n.cache_store.write(cache_key, result) unless result.is_a?(Proc)
result
end
Expand Down
8 changes: 4 additions & 4 deletions lib/i18n/backend/chain.rb
Expand Up @@ -41,7 +41,7 @@ def translate(locale, key, default_options = {})
options = default_options.except(:default)

backends.each do |backend|
catch(:missing_translation) do
catch(:exception) do
options = default_options if backend == backends.last
translation = backend.translate(locale, key, options)
if namespace_lookup?(translation, options)
Expand All @@ -54,16 +54,16 @@ def translate(locale, key, default_options = {})
end

return namespace if namespace
throw(:missing_translation, I18n::MissingTranslationData.new(locale, key, options))
throw(:exception, I18n::MissingTranslationData.new(locale, key, options))
end

def localize(locale, object, format = :default, options = {})
backends.each do |backend|
catch(:missing_translation) do
catch(:exception) do
result = backend.localize(locale, object, format, options) and return result
end
end
throw(:missing_translation, I18n::MissingTranslationData.new(locale, format, options))
throw(:exception, I18n::MissingTranslationData.new(locale, format, options))
end

protected
Expand Down
4 changes: 2 additions & 2 deletions lib/i18n/backend/fallbacks.rb
Expand Up @@ -41,15 +41,15 @@ def translate(locale, key, options = {})

options[:fallback] = true
I18n.fallbacks[locale].each do |fallback|
catch(:missing_translation) do
catch(:exception) do
result = super(fallback, key, options)
return result unless result.nil?
end
end
options.delete(:fallback)

return super(locale, nil, options.merge(:default => default)) if default
throw(:missing_translation, I18n::MissingTranslationData.new(locale, key, options))
throw(:exception, I18n::MissingTranslationData.new(locale, key, options))
end

def extract_string_or_lambda_default!(options)
Expand Down

0 comments on commit 4028976

Please sign in to comment.