Skip to content

Commit

Permalink
Merge pull request #393 from stereobooster/anonymous-objects
Browse files Browse the repository at this point in the history
Fix anonymous objects
  • Loading branch information
radar committed Mar 9, 2018
2 parents 77067d6 + ab11062 commit 274ed8a
Show file tree
Hide file tree
Showing 25 changed files with 94 additions and 50 deletions.
6 changes: 4 additions & 2 deletions lib/i18n.rb
@@ -1,3 +1,5 @@
# frozen_string_literal: true

require 'concurrent/map'

require 'i18n/version'
Expand All @@ -14,7 +16,7 @@ module I18n

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

EMPTY_HASH = {}.freeze

def self.new_double_nested_cache # :nodoc:
Concurrent::Map.new { |h,k| h[k] = Concurrent::Map.new }
Expand Down Expand Up @@ -175,7 +177,7 @@ def translate(*args)

# Wrapper for <tt>translate</tt> that adds <tt>:raise => true</tt>. With
# this option, if no translation is found, it will raise <tt>I18n::MissingTranslationData</tt>
def translate!(key, options={})
def translate!(key, options = EMPTY_HASH)
translate(key, options.merge(:raise => true))
end
alias :t! :translate!
Expand Down
2 changes: 2 additions & 0 deletions lib/i18n/backend.rb
@@ -1,3 +1,5 @@
# frozen_string_literal: true

module I18n
module Backend
autoload :Base, 'i18n/backend/base'
Expand Down
18 changes: 10 additions & 8 deletions lib/i18n/backend/base.rb
@@ -1,3 +1,5 @@
# frozen_string_literal: true

require 'yaml'
require 'i18n/core_ext/hash'
require 'i18n/core_ext/kernel/suppress_warnings'
Expand All @@ -17,11 +19,11 @@ def load_translations(*filenames)

# This method receives a locale, a data hash and options for storing translations.
# Should be implemented
def store_translations(locale, data, options = {})
def store_translations(locale, data, options = EMPTY_HASH)
raise NotImplementedError
end

def translate(locale, key, options = {})
def translate(locale, key, options = EMPTY_HASH)
raise I18n::ArgumentError if (key.is_a?(String) || key.is_a?(Symbol)) && key.empty?
raise InvalidLocale.new(locale) unless locale
return nil if key.nil? && !options.key?(:default)
Expand Down Expand Up @@ -68,7 +70,7 @@ def exists?(locale, key)
# Acts the same as +strftime+, but uses a localized version of the
# format string. Takes a key from the date/time formats translations as
# a format argument (<em>e.g.</em>, <tt>:short</tt> in <tt>:'date.formats'</tt>).
def localize(locale, object, format = :default, options = {})
def localize(locale, object, format = :default, options = EMPTY_HASH)
if object.nil? && options.include?(:default)
return options[:default]
end
Expand Down Expand Up @@ -97,7 +99,7 @@ def reload!
protected

# The method which actually looks up for the translation in the store.
def lookup(locale, key, scope = [], options = {})
def lookup(locale, key, scope = [], options = EMPTY_HASH)
raise NotImplementedError
end

Expand All @@ -109,7 +111,7 @@ def subtrees?
# If given subject is an Array, it walks the array and returns the
# first translation that can be resolved. Otherwise it tries to resolve
# the translation directly.
def default(locale, object, subject, options = {})
def default(locale, object, subject, options = EMPTY_HASH)
options = options.dup.reject { |key, value| key == :default }
case subject
when Array
Expand All @@ -126,7 +128,7 @@ def default(locale, object, subject, options = {})
# If the given subject is a Symbol, it will be translated with the
# given options. If it is a Proc then it will be evaluated. All other
# subjects will be returned directly.
def resolve(locale, object, subject, options = {})
def resolve(locale, object, subject, options = EMPTY_HASH)
return subject if options[:resolve] == false
result = catch(:exception) do
case subject
Expand Down Expand Up @@ -168,7 +170,7 @@ def pluralize(locale, entry, count)
# each element of the array is recursively interpolated (until it finds a string)
# method interpolates ["yes, %{user}", ["maybe no, %{user}, "no, %{user}"]], :user => "bartuz"
# # => "["yes, bartuz",["maybe no, bartuz", "no, bartuz"]]"
def interpolate(locale, subject, values = {})
def interpolate(locale, subject, values = EMPTY_HASH)
return subject if values.empty?

case subject
Expand All @@ -184,7 +186,7 @@ def interpolate(locale, subject, values = {})
# deep_interpolate { people: { ann: "Ann is %{ann}", john: "John is %{john}" } },
# ann: 'good', john: 'big'
# #=> { people: { ann: "Ann is good", john: "John is big" } }
def deep_interpolate(locale, data, values = {})
def deep_interpolate(locale, data, values = EMPTY_HASH)
return data if values.empty?

case data
Expand Down
10 changes: 6 additions & 4 deletions lib/i18n/backend/cache.rb
@@ -1,3 +1,5 @@
# frozen_string_literal: true

# This module allows you to easily cache all responses from the backend - thus
# speeding up the I18n aspects of your application quite a bit.
#
Expand All @@ -14,9 +16,9 @@
# ActiveSupport::Cache (only the methods #fetch and #write are being used).
#
# The cache_key implementation by default assumes you pass values that return
# a valid key from #hash (see
# http://www.ruby-doc.org/core/classes/Object.html#M000337). However, you can
# configure your own digest method via which responds to #hexdigest (see
# a valid key from #hash (see
# http://www.ruby-doc.org/core/classes/Object.html#M000337). However, you can
# configure your own digest method via which responds to #hexdigest (see
# http://ruby-doc.org/stdlib/libdoc/digest/rdoc/index.html):
#
# I18n.cache_key_digest = Digest::MD5.new
Expand Down Expand Up @@ -75,7 +77,7 @@ def perform_caching?
module Backend
# TODO Should the cache be cleared if new translations are stored?
module Cache
def translate(locale, key, options = {})
def translate(locale, key, options = EMPTY_HASH)
I18n.perform_caching? ? fetch(cache_key(locale, key, options)) { super } : super
end

Expand Down
4 changes: 3 additions & 1 deletion lib/i18n/backend/cascade.rb
@@ -1,3 +1,5 @@
# frozen_string_literal: true

# The Cascade module adds the ability to do cascading lookups to backends that
# are compatible to the Simple backend.
#
Expand Down Expand Up @@ -31,7 +33,7 @@
module I18n
module Backend
module Cascade
def lookup(locale, key, scope = [], options = {})
def lookup(locale, key, scope = [], options = EMPTY_HASH)
return super unless cascade = options[:cascade]

cascade = { :step => 1 } unless cascade.is_a?(Hash)
Expand Down
8 changes: 5 additions & 3 deletions lib/i18n/backend/chain.rb
@@ -1,3 +1,5 @@
# frozen_string_literal: true

module I18n
module Backend
# Backend that chains multiple other backends and checks each of them when
Expand Down Expand Up @@ -28,15 +30,15 @@ def reload!
backends.each { |backend| backend.reload! }
end

def store_translations(locale, data, options = {})
def store_translations(locale, data, options = EMPTY_HASH)
backends.first.store_translations(locale, data, options)
end

def available_locales
backends.map { |backend| backend.available_locales }.flatten.uniq
end

def translate(locale, key, default_options = {})
def translate(locale, key, default_options = EMPTY_HASH)
namespace = nil
options = default_options.except(:default)

Expand All @@ -62,7 +64,7 @@ def exists?(locale, key)
end
end

def localize(locale, object, format = :default, options = {})
def localize(locale, object, format = :default, options = EMPTY_HASH)
backends.each do |backend|
catch(:exception) do
result = backend.localize(locale, object, format, options) and return result
Expand Down
24 changes: 11 additions & 13 deletions lib/i18n/backend/fallbacks.rb
@@ -1,3 +1,5 @@
# frozen_string_literal: true

# I18n locale fallbacks are useful when you want your application to use
# translations from other locales when translations for the current locale are
# missing. E.g. you might want to use :en translations when translations in
Expand Down Expand Up @@ -34,25 +36,21 @@ module Fallbacks
# The default option takes precedence over fallback locales only when
# it's a Symbol. When the default contains a String, Proc or Hash
# it is evaluated last after all the fallback locales have been tried.
def translate(locale, key, options = {})
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]

begin
options[:fallback_in_progress] = true
I18n.fallbacks[locale].each do |fallback|
begin
catch(:exception) do
result = super(fallback, key, options)
return result unless result.nil?
end
rescue I18n::InvalidLocale
# we do nothing when the locale is invalid, as this is a fallback anyways.
fallback_options = options.merge(:fallback_in_progress => true)
I18n.fallbacks[locale].each do |fallback|
begin
catch(:exception) do
result = super(fallback, key, fallback_options)
return result unless result.nil?
end
rescue I18n::InvalidLocale
# we do nothing when the locale is invalid, as this is a fallback anyways.
end
ensure
options.delete(:fallback_in_progress)
end

return if options.key?(:default) && options[:default].nil?
Expand Down
2 changes: 2 additions & 0 deletions lib/i18n/backend/flatten.rb
@@ -1,3 +1,5 @@
# frozen_string_literal: true

module I18n
module Backend
# This module contains several helpers to assist flattening translations.
Expand Down
2 changes: 2 additions & 0 deletions lib/i18n/backend/gettext.rb
@@ -1,3 +1,5 @@
# frozen_string_literal: true

require 'i18n/gettext'
require 'i18n/gettext/po_parser'

Expand Down
4 changes: 3 additions & 1 deletion lib/i18n/backend/interpolation_compiler.rb
@@ -1,3 +1,5 @@
# frozen_string_literal: true

# The InterpolationCompiler module contains optimizations that can tremendously
# speed up the interpolation process on the Simple backend.
#
Expand Down Expand Up @@ -104,7 +106,7 @@ def interpolate(locale, string, values)
end
end

def store_translations(locale, data, options = {})
def store_translations(locale, data, options = EMPTY_HASH)
compile_all_strings_in(data)
super
end
Expand Down
6 changes: 4 additions & 2 deletions lib/i18n/backend/key_value.rb
@@ -1,3 +1,5 @@
# frozen_string_literal: true

require 'i18n/backend/base'

module I18n
Expand Down Expand Up @@ -74,7 +76,7 @@ def initialize(store, subtrees=true)
@store, @subtrees = store, subtrees
end

def store_translations(locale, data, options = {})
def store_translations(locale, data, options = EMPTY_HASH)
escape = options.fetch(:escape, true)
flatten_translations(locale, data, escape, @subtrees).each do |key, value|
key = "#{locale}.#{key}"
Expand Down Expand Up @@ -107,7 +109,7 @@ def subtrees?
@subtrees
end

def lookup(locale, key, scope = [], options = {})
def lookup(locale, key, scope = [], options = EMPTY_HASH)
key = normalize_flat_keys(locale, key, scope, options[:separator])
value = @store["#{locale}.#{key}"]
value = JSON.decode(value) if value
Expand Down
6 changes: 4 additions & 2 deletions lib/i18n/backend/memoize.rb
@@ -1,3 +1,5 @@
# frozen_string_literal: true

# Memoize module simply memoizes the values returned by lookup using
# a flat hash and can tremendously speed up the lookup process in a backend.
#
Expand All @@ -14,7 +16,7 @@ def available_locales
@memoized_locales ||= super
end

def store_translations(locale, data, options = {})
def store_translations(locale, data, options = EMPTY_HASH)
reset_memoizations!(locale)
super
end
Expand All @@ -26,7 +28,7 @@ def reload!

protected

def lookup(locale, key, scope = nil, options = {})
def lookup(locale, key, scope = nil, options = EMPTY_HASH)
flat_key = I18n::Backend::Flatten.normalize_flat_keys(locale,
key, scope, options[:separator]).to_sym
flat_hash = memoized_lookup[locale.to_sym]
Expand Down
6 changes: 4 additions & 2 deletions lib/i18n/backend/metadata.rb
@@ -1,3 +1,5 @@
# frozen_string_literal: true

# I18n translation metadata is useful when you want to access information
# about how a translation was looked up, pluralized or interpolated in
# your application.
Expand Down Expand Up @@ -35,7 +37,7 @@ def translation_metadata=(translation_metadata)
end
end

def translate(locale, key, options = {})
def translate(locale, key, options = EMPTY_HASH)
metadata = {
:locale => locale,
:key => key,
Expand All @@ -47,7 +49,7 @@ def translate(locale, key, options = {})
with_metadata(metadata) { super }
end

def interpolate(locale, entry, values = {})
def interpolate(locale, entry, values = EMPTY_HASH)
metadata = entry.translation_metadata.merge(:original => entry)
with_metadata(metadata) { super }
end
Expand Down
2 changes: 2 additions & 0 deletions lib/i18n/backend/pluralization.rb
@@ -1,3 +1,5 @@
# frozen_string_literal: true

# I18n Pluralization are useful when you want your application to
# customize pluralization rules.
#
Expand Down
6 changes: 4 additions & 2 deletions lib/i18n/backend/simple.rb
@@ -1,3 +1,5 @@
# frozen_string_literal: true

module I18n
module Backend
# A simple backend that reads translations from YAML files and stores them in
Expand Down Expand Up @@ -28,7 +30,7 @@ def initialized?
# This uses a deep merge for the translations hash, so existing
# translations will be overwritten by new ones only at the deepest
# level of the hash.
def store_translations(locale, data, options = {})
def store_translations(locale, data, options = EMPTY_HASH)
if I18n.enforce_available_locales &&
I18n.available_locales_initialized? &&
!I18n.available_locales.include?(locale.to_sym) &&
Expand Down Expand Up @@ -73,7 +75,7 @@ def translations
# nested translations hash. Splits keys or scopes containing dots
# into multiple keys, i.e. <tt>currency.format</tt> is regarded the same as
# <tt>%w(currency format)</tt>.
def lookup(locale, key, scope = [], options = {})
def lookup(locale, key, scope = [], options = EMPTY_HASH)
init_translations unless initialized?
keys = I18n.normalize_keys(locale, key, scope, options[:separator])

Expand Down
2 changes: 2 additions & 0 deletions lib/i18n/backend/transliterator.rb
@@ -1,4 +1,6 @@
# encoding: utf-8
# frozen_string_literal: true

module I18n
module Backend
module Transliterator
Expand Down
4 changes: 3 additions & 1 deletion lib/i18n/config.rb
@@ -1,3 +1,5 @@
# frozen_string_literal: true

require 'set'

module I18n
Expand Down Expand Up @@ -57,7 +59,7 @@ def available_locales=(locales)
@@available_locales = nil if @@available_locales.empty?
@@available_locales_set = nil
end

# Returns true if the available_locales have been initialized
def available_locales_initialized?
( !!defined?(@@available_locales) && !!@@available_locales )
Expand Down
4 changes: 3 additions & 1 deletion lib/i18n/exceptions.rb
@@ -1,3 +1,5 @@
# frozen_string_literal: true

require 'cgi'

module I18n
Expand Down Expand Up @@ -42,7 +44,7 @@ class MissingTranslation < ArgumentError
module Base
attr_reader :locale, :key, :options

def initialize(locale, key, options = {})
def initialize(locale, key, options = EMPTY_HASH)
@key, @locale, @options = key, locale, options.dup
options.each { |k, v| self.options[k] = v.inspect if v.is_a?(Proc) }
end
Expand Down
2 changes: 2 additions & 0 deletions lib/i18n/gettext.rb
@@ -1,3 +1,5 @@
# frozen_string_literal: true

module I18n
module Gettext
PLURAL_SEPARATOR = "\001"
Expand Down

0 comments on commit 274ed8a

Please sign in to comment.