Hello community, here is the log from the commit of package rubygem-i18n for openSUSE:Factory checked in at 2017-10-23 16:53:08 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/rubygem-i18n (Old) and /work/SRC/openSUSE:Factory/.rubygem-i18n.new (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "rubygem-i18n" Mon Oct 23 16:53:08 2017 rev:15 rq:535855 version:0.9.0 Changes: -------- --- /work/SRC/openSUSE:Factory/rubygem-i18n/rubygem-i18n.changes 2017-08-16 16:11:51.533004857 +0200 +++ /work/SRC/openSUSE:Factory/.rubygem-i18n.new/rubygem-i18n.changes 2017-10-23 16:53:39.311664424 +0200 @@ -1,0 +2,7 @@ +Mon Oct 23 05:56:56 UTC 2017 - mschnit...@suse.com + +- updated to version 0.9.0 + * Made Backend::Memoize threadsafe. See #51 and #352. + * Added a middleware I18n::Middleware that should be used to ensure that i18n config is reset correctly between requests. See #381 and #382. + +------------------------------------------------------------------- Old: ---- i18n-0.8.6.gem New: ---- i18n-0.9.0.gem ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ rubygem-i18n.spec ++++++ --- /var/tmp/diff_new_pack.hkRCfC/_old 2017-10-23 16:53:39.751643834 +0200 +++ /var/tmp/diff_new_pack.hkRCfC/_new 2017-10-23 16:53:39.755643646 +0200 @@ -24,7 +24,7 @@ # Name: rubygem-i18n -Version: 0.8.6 +Version: 0.9.0 Release: 0 %define mod_name i18n %define mod_full_name %{mod_name}-%{version} @@ -33,7 +33,7 @@ BuildRequires: %{rubygem gem2rpm} BuildRequires: ruby-macros >= 5 Url: http://github.com/svenfuchs/i18n -Source: http://rubygems.org/gems/%{mod_full_name}.gem +Source: https://rubygems.org/gems/%{mod_full_name}.gem Source1: gem2rpm.yml Summary: New wave Internationalization support for Ruby License: MIT ++++++ i18n-0.8.6.gem -> i18n-0.9.0.gem ++++++ Binary files old/checksums.yaml.gz and new/checksums.yaml.gz differ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/gemfiles/Gemfile.rails-5.1.x new/gemfiles/Gemfile.rails-5.1.x --- old/gemfiles/Gemfile.rails-5.1.x 1970-01-01 01:00:00.000000000 +0100 +++ new/gemfiles/Gemfile.rails-5.1.x 2017-10-16 00:38:42.000000000 +0200 @@ -0,0 +1,9 @@ +source 'https://rubygems.org' + +gemspec :path => '..' + +gem 'activesupport', '~> 5.1.0' +gem 'mocha' +gem 'test_declarative' +gem 'rake' +gem 'minitest' diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/lib/i18n/backend/fallbacks.rb new/lib/i18n/backend/fallbacks.rb --- old/lib/i18n/backend/fallbacks.rb 2017-07-10 07:39:13.000000000 +0200 +++ new/lib/i18n/backend/fallbacks.rb 2017-10-16 00:38:42.000000000 +0200 @@ -37,7 +37,8 @@ def translate(locale, key, options = {}) return super unless options.fetch(:fallback, true) return super if options[:fallback_in_progress] - default = extract_non_symbol_default!(options) if options[:default] + original_default = options[:default] + extract_non_symbol_default!(options) begin options[:fallback_in_progress] = true @@ -45,7 +46,7 @@ begin catch(:exception) do result = super(fallback, key, options) - return result if (result.nil? && options.key?(:default) && options[:default].nil?) || !result.nil? + return result unless result.nil? end rescue I18n::InvalidLocale # we do nothing when the locale is invalid, as this is a fallback anyways. @@ -55,7 +56,7 @@ options.delete(:fallback_in_progress) end - return super(locale, nil, options.merge(:default => default)) if default + return super(locale, nil, options.merge(:default => original_default)) if options.key?(:default) throw(:exception, I18n::MissingTranslation.new(locale, key, options)) end diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/lib/i18n/backend/flatten.rb new/lib/i18n/backend/flatten.rb --- old/lib/i18n/backend/flatten.rb 2017-07-10 07:39:13.000000000 +0200 +++ new/lib/i18n/backend/flatten.rb 2017-10-16 00:38:42.000000000 +0200 @@ -43,7 +43,7 @@ # Store flattened links. def links - @links ||= Hash.new { |h,k| h[k] = {} } + @links ||= I18n.new_double_nested_cache end # Flatten keys for nested Hashes by chaining up keys: @@ -99,7 +99,7 @@ end def find_link(locale, key) #:nodoc: - links[locale].each do |from, to| + links[locale].each_pair do |from, to| return [from, to] if key[0, from.length] == from end && nil end @@ -110,4 +110,4 @@ end end -end \ No newline at end of file +end diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/lib/i18n/backend/memoize.rb new/lib/i18n/backend/memoize.rb --- old/lib/i18n/backend/memoize.rb 2017-07-10 07:39:13.000000000 +0200 +++ new/lib/i18n/backend/memoize.rb 2017-10-16 00:38:42.000000000 +0200 @@ -34,7 +34,7 @@ end def memoized_lookup - @memoized_lookup ||= Hash.new { |h, k| h[k] = {} } + @memoized_lookup ||= I18n.new_double_nested_cache end def reset_memoizations!(locale=nil) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/lib/i18n/middleware.rb new/lib/i18n/middleware.rb --- old/lib/i18n/middleware.rb 1970-01-01 01:00:00.000000000 +0100 +++ new/lib/i18n/middleware.rb 2017-10-16 00:38:42.000000000 +0200 @@ -0,0 +1,15 @@ +module I18n + class Middleware + + def initialize(app) + @app = app + end + + def call(env) + @app.call(env) + ensure + Thread.current[:i18n_config] = I18n::Config.new + end + + end +end diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/lib/i18n/version.rb new/lib/i18n/version.rb --- old/lib/i18n/version.rb 2017-07-10 07:39:13.000000000 +0200 +++ new/lib/i18n/version.rb 2017-10-16 00:38:42.000000000 +0200 @@ -1,3 +1,3 @@ module I18n - VERSION = "0.8.6" + VERSION = "0.9.0" end diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/lib/i18n.rb new/lib/i18n.rb --- old/lib/i18n.rb 2017-07-10 07:39:13.000000000 +0200 +++ new/lib/i18n.rb 2017-10-16 00:38:42.000000000 +0200 @@ -1,3 +1,5 @@ +require 'concurrent/map' + require 'i18n/version' require 'i18n/exceptions' require 'i18n/interpolate/ruby' @@ -8,10 +10,16 @@ autoload :Gettext, 'i18n/gettext' autoload :Locale, 'i18n/locale' autoload :Tests, 'i18n/tests' + autoload :Middleware, 'i18n/middleware' RESERVED_KEYS = [:scope, :default, :separator, :resolve, :object, :fallback, :fallback_in_progress, :format, :cascade, :throw, :raise, :deep_interpolation] RESERVED_KEYS_PATTERN = /%\{(#{RESERVED_KEYS.join("|")})\}/ + + def self.new_double_nested_cache # :nodoc: + Concurrent::Map.new { |h,k| h[k] = Concurrent::Map.new } + end + module Base # Gets I18n configuration object. def config @@ -321,8 +329,10 @@ end end + @@normalized_key_cache = I18n.new_double_nested_cache + def normalize_key(key, separator) - normalized_key_cache[separator][key] ||= + @@normalized_key_cache[separator][key] ||= case key when Array key.map { |k| normalize_key(k, separator) }.flatten @@ -333,10 +343,6 @@ keys end end - - def normalized_key_cache - @normalized_key_cache ||= Hash.new { |h,k| h[k] = {} } - end end extend Base diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/metadata new/metadata --- old/metadata 2017-07-10 07:39:13.000000000 +0200 +++ new/metadata 2017-10-16 00:38:42.000000000 +0200 @@ -1,7 +1,7 @@ --- !ruby/object:Gem::Specification name: i18n version: !ruby/object:Gem::Version - version: 0.8.6 + version: 0.9.0 platform: ruby authors: - Sven Fuchs @@ -12,8 +12,22 @@ autorequire: bindir: bin cert_chain: [] -date: 2017-07-10 00:00:00.000000000 Z -dependencies: [] +date: 2017-10-15 00:00:00.000000000 Z +dependencies: +- !ruby/object:Gem::Dependency + name: concurrent-ruby + requirement: !ruby/object:Gem::Requirement + requirements: + - - "~>" + - !ruby/object:Gem::Version + version: '1.0' + type: :runtime + prerelease: false + version_requirements: !ruby/object:Gem::Requirement + requirements: + - - "~>" + - !ruby/object:Gem::Version + version: '1.0' description: New wave Internationalization support for Ruby. email: rails-i...@googlegroups.com executables: [] @@ -27,6 +41,7 @@ - gemfiles/Gemfile.rails-4.1.x - gemfiles/Gemfile.rails-4.2.x - gemfiles/Gemfile.rails-5.0.x +- gemfiles/Gemfile.rails-5.1.x - gemfiles/Gemfile.rails-master - lib/i18n.rb - lib/i18n/backend.rb @@ -59,6 +74,7 @@ - lib/i18n/locale/tag/parents.rb - lib/i18n/locale/tag/rfc4646.rb - lib/i18n/locale/tag/simple.rb +- lib/i18n/middleware.rb - lib/i18n/tests.rb - lib/i18n/tests/basics.rb - lib/i18n/tests/defaults.rb @@ -101,6 +117,7 @@ - test/i18n/gettext_plural_keys_test.rb - test/i18n/interpolate_test.rb - test/i18n/load_path_test.rb +- test/i18n/middleware_test.rb - test/i18n_test.rb - test/locale/fallbacks_test.rb - test/locale/tag/rfc4646_test.rb @@ -133,7 +150,7 @@ version: 1.3.5 requirements: [] rubyforge_project: "[none]" -rubygems_version: 2.6.10 +rubygems_version: 2.6.11 signing_key: specification_version: 4 summary: New wave Internationalization support for Ruby diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/test/backend/fallbacks_test.rb new/test/backend/fallbacks_test.rb --- old/test/backend/fallbacks_test.rb 2017-07-10 07:39:13.000000000 +0200 +++ new/test/backend/fallbacks_test.rb 2017-10-16 00:38:42.000000000 +0200 @@ -8,7 +8,7 @@ def setup super I18n.backend = Backend.new - store_translations(:en, :foo => 'Foo in :en', :bar => 'Bar in :en', :buz => 'Buz in :en') + store_translations(:en, :foo => 'Foo in :en', :bar => 'Bar in :en', :buz => 'Buz in :en', :interpolate => 'Interpolate %{value}') store_translations(:de, :bar => 'Bar in :de', :baz => 'Baz in :de') store_translations(:'de-DE', :baz => 'Baz in :de-DE') store_translations(:'pt-BR', :baz => 'Baz in :pt-BR') @@ -20,6 +20,10 @@ assert_equal 'Baz in :de-DE', I18n.t(:baz, :locale => :'de-DE') end + test "returns interpolated value if no key provided" do + assert_equal 'Interpolate %{value}', I18n.t(:interpolate) + end + test "returns the :en translation for a missing :de translation" do assert_equal 'Foo in :en', I18n.t(:foo, :locale => :de) end @@ -55,6 +59,11 @@ assert_equal({}, I18n.t(:missing_bar, :locale => :'de-DE', :default => {})) end + test "returns the :de translation for a missing :'de-DE' when :default is nil" do + assert_equal 'Bar in :de', I18n.t(:bar, :locale => :'de-DE', :default => nil) + assert_nil I18n.t(:missing_bar, :locale => :'de-DE', :default => nil) + end + test "returns the :'de-DE' default :baz translation for a missing :'de-DE' when defaults contains Symbol" do assert_equal 'Baz in :de-DE', I18n.t(:missing_foo, :locale => :'de-DE', :default => [:baz, "Default Bar"]) end diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/test/backend/memoize_test.rb new/test/backend/memoize_test.rb --- old/test/backend/memoize_test.rb 2017-07-10 07:39:13.000000000 +0200 +++ new/test/backend/memoize_test.rb 2017-10-16 00:38:42.000000000 +0200 @@ -44,4 +44,36 @@ assert I18n.available_locales.include?(:copa) assert_equal 1, I18n.backend.spy_calls end + + module TestLookup + def lookup(locale, key, scope = [], options = {}) + keys = I18n.normalize_keys(locale, key, scope, options[:separator]) + keys.inspect + end + end + + def test_lookup_concurrent_consistency + backend_impl = Class.new(I18n::Backend::Simple) do + include TestLookup + include I18n::Backend::Memoize + end + backend = backend_impl.new + + memoized_lookup = backend.send(:memoized_lookup) + + assert_equal "[:foo, :scoped, :sample]", backend.translate('foo', scope = [:scoped, :sample]) + + results = [] + 30.times.inject([]) do |memo, i| + memo << Thread.new do + backend.translate('bar', scope); backend.translate(:baz, scope) + end + end.each(&:join) + + memoized_lookup = backend.send(:memoized_lookup) + puts memoized_lookup.inspect if $VERBOSE + assert_equal 3, memoized_lookup.size, "NON-THREAD-SAFE lookup memoization backend: #{memoized_lookup.class}" + # if a plain Hash is used might eventually end up in a weird (inconsistent) state + end + end diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/test/i18n/middleware_test.rb new/test/i18n/middleware_test.rb --- old/test/i18n/middleware_test.rb 1970-01-01 01:00:00.000000000 +0100 +++ new/test/i18n/middleware_test.rb 2017-10-16 00:38:42.000000000 +0200 @@ -0,0 +1,24 @@ +require 'test_helper' + +class I18nMiddlewareTest < I18n::TestCase + def setup + super + I18n.default_locale = :fr + @app = DummyRackApp.new + @middleware = I18n::Middleware.new(@app) + end + + test "middleware initializes new config object after request" do + old_i18n_config_object_id = Thread.current[:i18n_config].object_id + @middleware.call({}) + + updated_i18n_config_object_id = Thread.current[:i18n_config].object_id + assert_not_equal updated_i18n_config_object_id, old_i18n_config_object_id + end + + test "succesfully resets i18n locale to default locale by defining new config" do + @middleware.call({}) + + assert_equal :fr, I18n.locale + end +end diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/test/test_helper.rb new/test/test_helper.rb --- old/test/test_helper.rb 2017-07-10 07:39:13.000000000 +0200 +++ new/test/test_helper.rb 2017-10-16 00:38:42.000000000 +0200 @@ -53,3 +53,9 @@ File.dirname(__FILE__) + '/test_data/locales' end end + +class DummyRackApp + def call(env) + I18n.locale = :es + end +end