module I18n::Backend::Fallbacks

def exists?(locale, key, options = EMPTY_HASH)

def exists?(locale, key, options = EMPTY_HASH)
  return super unless options.fetch(:fallback, true)
  I18n.fallbacks[locale].each do |fallback|
    begin
      return true if super(fallback, key)
    rescue I18n::InvalidLocale
      # we do nothing when the locale is invalid, as this is a fallback anyways.
    end
  end
  false
end

def extract_non_symbol_default!(options)

def extract_non_symbol_default!(options)
  defaults = [options[:default]].flatten
  first_non_symbol_default = defaults.detect{|default| !default.is_a?(Symbol)}
  if first_non_symbol_default
    options[:default] = defaults[0, defaults.index(first_non_symbol_default)]
  end
  return first_non_symbol_default
end

def on_fallback(_original_locale, _fallback_locale, _key, _options)

Overwrite on_fallback to add specified logic when the fallback succeeds.
def on_fallback(_original_locale, _fallback_locale, _key, _options)
  nil
end

def resolve_entry(locale, object, subject, options = EMPTY_HASH)

def resolve_entry(locale, object, subject, options = EMPTY_HASH)
  return subject if options[:resolve] == false
  result = catch(:exception) do
    options.delete(:fallback_in_progress) if options.key?(:fallback_in_progress)
    case subject
    when Symbol
      I18n.translate(subject, **options.merge(:locale => options[:fallback_original_locale], :throw => true))
    when Proc
      date_or_time = options.delete(:object) || object
      resolve_entry(options[:fallback_original_locale], object, subject.call(date_or_time, **options))
    else
      subject
    end
  end
  result unless result.is_a?(MissingTranslation)
end

def translate(locale, key, options = EMPTY_HASH)

it is evaluated last after all the fallback locales have been tried.
it's a Symbol. When the default contains a String, Proc or Hash
The default option takes precedence over fallback locales only when

locales it will then throw MissingTranslation as usual.
the given options. If it does not find any result for any of the
(depends on the fallbacks implementation) until it finds a result with
locale :"de-DE" it might try the locales :"de-DE", :de and :en
locale given by I18n.fallbacks for the given locale. E.g. for the
Overwrites the Base backend translate method so that it will try each
def translate(locale, key, options = EMPTY_HASH)
  return super unless options.fetch(:fallback, true)
  return super if options[:fallback_in_progress]
  default = extract_non_symbol_default!(options) if options[:default]
  fallback_options = options.merge(:fallback_in_progress => true, fallback_original_locale: locale)
  I18n.fallbacks[locale].each do |fallback|
    begin
      catch(:exception) do
        result = super(fallback, key, fallback_options)
        unless result.nil?
          on_fallback(locale, fallback, key, options) if locale.to_s != fallback.to_s
          return result
        end
      end
    rescue I18n::InvalidLocale
      # we do nothing when the locale is invalid, as this is a fallback anyways.
    end
  end
  return if options.key?(:default) && options[:default].nil?
  return super(locale, nil, options.merge(:default => default)) if default
  throw(:exception, I18n::MissingTranslation.new(locale, key, options))
end