i18n 0.8.6 → 0.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 9edfdb04f9f18e15e4cf08fd28360a80c0ce7a22
4
- data.tar.gz: 855de9451e9b408c46f42d9105e6a31d1f2c9018
3
+ metadata.gz: dacd9a4d17f9bead5f815c49595c00d1531ed4d7
4
+ data.tar.gz: 1e4d2ba2b94da73f8dbde1957508a849f7162172
5
5
  SHA512:
6
- metadata.gz: efb2ecd003577c7b663969ca3849631e3e9ccdb64adf97b0616d99f62da2d29028a3cb0f194479861a8d5133b30e263eca1f5061a830047822d894f7f2dd56ba
7
- data.tar.gz: 474bb30ec7bf4f78ce176a8e3410b72cf1f4edd32b5a7b45389e80c3fe6de2dcff5a48739a432c369959aa5008079a896d7bd4ba418529d64082d7ecbe90d837
6
+ metadata.gz: f59e2cfebd1627b138d763d6b035078729cc62104697189e8781003aeb6537e8682e5f4f0ea0ad68e30f36873d895fdb863d8fca3abece2c48cb229e170ccb92
7
+ data.tar.gz: cd5c4bc9940ccfe400eda8696d8d9bf7630da4c4e67f46a0a6be9f799f64a54fb8d2bdcb9c80dfdeeb3dfc9e14f10d1af715d45dc230415e3491c7b6a187d3e6
@@ -0,0 +1,9 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gemspec :path => '..'
4
+
5
+ gem 'activesupport', '~> 5.1.0'
6
+ gem 'mocha'
7
+ gem 'test_declarative'
8
+ gem 'rake'
9
+ gem 'minitest'
@@ -1,3 +1,5 @@
1
+ require 'concurrent/map'
2
+
1
3
  require 'i18n/version'
2
4
  require 'i18n/exceptions'
3
5
  require 'i18n/interpolate/ruby'
@@ -8,10 +10,16 @@ module I18n
8
10
  autoload :Gettext, 'i18n/gettext'
9
11
  autoload :Locale, 'i18n/locale'
10
12
  autoload :Tests, 'i18n/tests'
13
+ autoload :Middleware, 'i18n/middleware'
11
14
 
12
15
  RESERVED_KEYS = [:scope, :default, :separator, :resolve, :object, :fallback, :fallback_in_progress, :format, :cascade, :throw, :raise, :deep_interpolation]
13
16
  RESERVED_KEYS_PATTERN = /%\{(#{RESERVED_KEYS.join("|")})\}/
14
17
 
18
+
19
+ def self.new_double_nested_cache # :nodoc:
20
+ Concurrent::Map.new { |h,k| h[k] = Concurrent::Map.new }
21
+ end
22
+
15
23
  module Base
16
24
  # Gets I18n configuration object.
17
25
  def config
@@ -321,8 +329,10 @@ module I18n
321
329
  end
322
330
  end
323
331
 
332
+ @@normalized_key_cache = I18n.new_double_nested_cache
333
+
324
334
  def normalize_key(key, separator)
325
- normalized_key_cache[separator][key] ||=
335
+ @@normalized_key_cache[separator][key] ||=
326
336
  case key
327
337
  when Array
328
338
  key.map { |k| normalize_key(k, separator) }.flatten
@@ -333,10 +343,6 @@ module I18n
333
343
  keys
334
344
  end
335
345
  end
336
-
337
- def normalized_key_cache
338
- @normalized_key_cache ||= Hash.new { |h,k| h[k] = {} }
339
- end
340
346
  end
341
347
 
342
348
  extend Base
@@ -37,7 +37,8 @@ module I18n
37
37
  def translate(locale, key, options = {})
38
38
  return super unless options.fetch(:fallback, true)
39
39
  return super if options[:fallback_in_progress]
40
- default = extract_non_symbol_default!(options) if options[:default]
40
+ original_default = options[:default]
41
+ extract_non_symbol_default!(options)
41
42
 
42
43
  begin
43
44
  options[:fallback_in_progress] = true
@@ -45,7 +46,7 @@ module I18n
45
46
  begin
46
47
  catch(:exception) do
47
48
  result = super(fallback, key, options)
48
- return result if (result.nil? && options.key?(:default) && options[:default].nil?) || !result.nil?
49
+ return result unless result.nil?
49
50
  end
50
51
  rescue I18n::InvalidLocale
51
52
  # we do nothing when the locale is invalid, as this is a fallback anyways.
@@ -55,7 +56,7 @@ module I18n
55
56
  options.delete(:fallback_in_progress)
56
57
  end
57
58
 
58
- return super(locale, nil, options.merge(:default => default)) if default
59
+ return super(locale, nil, options.merge(:default => original_default)) if options.key?(:default)
59
60
  throw(:exception, I18n::MissingTranslation.new(locale, key, options))
60
61
  end
61
62
 
@@ -43,7 +43,7 @@ module I18n
43
43
 
44
44
  # Store flattened links.
45
45
  def links
46
- @links ||= Hash.new { |h,k| h[k] = {} }
46
+ @links ||= I18n.new_double_nested_cache
47
47
  end
48
48
 
49
49
  # Flatten keys for nested Hashes by chaining up keys:
@@ -99,7 +99,7 @@ module I18n
99
99
  end
100
100
 
101
101
  def find_link(locale, key) #:nodoc:
102
- links[locale].each do |from, to|
102
+ links[locale].each_pair do |from, to|
103
103
  return [from, to] if key[0, from.length] == from
104
104
  end && nil
105
105
  end
@@ -110,4 +110,4 @@ module I18n
110
110
 
111
111
  end
112
112
  end
113
- end
113
+ end
@@ -34,7 +34,7 @@ module I18n
34
34
  end
35
35
 
36
36
  def memoized_lookup
37
- @memoized_lookup ||= Hash.new { |h, k| h[k] = {} }
37
+ @memoized_lookup ||= I18n.new_double_nested_cache
38
38
  end
39
39
 
40
40
  def reset_memoizations!(locale=nil)
@@ -0,0 +1,15 @@
1
+ module I18n
2
+ class Middleware
3
+
4
+ def initialize(app)
5
+ @app = app
6
+ end
7
+
8
+ def call(env)
9
+ @app.call(env)
10
+ ensure
11
+ Thread.current[:i18n_config] = I18n::Config.new
12
+ end
13
+
14
+ end
15
+ end
@@ -1,3 +1,3 @@
1
1
  module I18n
2
- VERSION = "0.8.6"
2
+ VERSION = "0.9.0"
3
3
  end
@@ -8,7 +8,7 @@ class I18nBackendFallbacksTranslateTest < I18n::TestCase
8
8
  def setup
9
9
  super
10
10
  I18n.backend = Backend.new
11
- store_translations(:en, :foo => 'Foo in :en', :bar => 'Bar in :en', :buz => 'Buz in :en')
11
+ store_translations(:en, :foo => 'Foo in :en', :bar => 'Bar in :en', :buz => 'Buz in :en', :interpolate => 'Interpolate %{value}')
12
12
  store_translations(:de, :bar => 'Bar in :de', :baz => 'Baz in :de')
13
13
  store_translations(:'de-DE', :baz => 'Baz in :de-DE')
14
14
  store_translations(:'pt-BR', :baz => 'Baz in :pt-BR')
@@ -20,6 +20,10 @@ class I18nBackendFallbacksTranslateTest < I18n::TestCase
20
20
  assert_equal 'Baz in :de-DE', I18n.t(:baz, :locale => :'de-DE')
21
21
  end
22
22
 
23
+ test "returns interpolated value if no key provided" do
24
+ assert_equal 'Interpolate %{value}', I18n.t(:interpolate)
25
+ end
26
+
23
27
  test "returns the :en translation for a missing :de translation" do
24
28
  assert_equal 'Foo in :en', I18n.t(:foo, :locale => :de)
25
29
  end
@@ -55,6 +59,11 @@ class I18nBackendFallbacksTranslateTest < I18n::TestCase
55
59
  assert_equal({}, I18n.t(:missing_bar, :locale => :'de-DE', :default => {}))
56
60
  end
57
61
 
62
+ test "returns the :de translation for a missing :'de-DE' when :default is nil" do
63
+ assert_equal 'Bar in :de', I18n.t(:bar, :locale => :'de-DE', :default => nil)
64
+ assert_nil I18n.t(:missing_bar, :locale => :'de-DE', :default => nil)
65
+ end
66
+
58
67
  test "returns the :'de-DE' default :baz translation for a missing :'de-DE' when defaults contains Symbol" do
59
68
  assert_equal 'Baz in :de-DE', I18n.t(:missing_foo, :locale => :'de-DE', :default => [:baz, "Default Bar"])
60
69
  end
@@ -44,4 +44,36 @@ class I18nBackendMemoizeTest < I18nBackendSimpleTest
44
44
  assert I18n.available_locales.include?(:copa)
45
45
  assert_equal 1, I18n.backend.spy_calls
46
46
  end
47
+
48
+ module TestLookup
49
+ def lookup(locale, key, scope = [], options = {})
50
+ keys = I18n.normalize_keys(locale, key, scope, options[:separator])
51
+ keys.inspect
52
+ end
53
+ end
54
+
55
+ def test_lookup_concurrent_consistency
56
+ backend_impl = Class.new(I18n::Backend::Simple) do
57
+ include TestLookup
58
+ include I18n::Backend::Memoize
59
+ end
60
+ backend = backend_impl.new
61
+
62
+ memoized_lookup = backend.send(:memoized_lookup)
63
+
64
+ assert_equal "[:foo, :scoped, :sample]", backend.translate('foo', scope = [:scoped, :sample])
65
+
66
+ results = []
67
+ 30.times.inject([]) do |memo, i|
68
+ memo << Thread.new do
69
+ backend.translate('bar', scope); backend.translate(:baz, scope)
70
+ end
71
+ end.each(&:join)
72
+
73
+ memoized_lookup = backend.send(:memoized_lookup)
74
+ puts memoized_lookup.inspect if $VERBOSE
75
+ assert_equal 3, memoized_lookup.size, "NON-THREAD-SAFE lookup memoization backend: #{memoized_lookup.class}"
76
+ # if a plain Hash is used might eventually end up in a weird (inconsistent) state
77
+ end
78
+
47
79
  end
@@ -0,0 +1,24 @@
1
+ require 'test_helper'
2
+
3
+ class I18nMiddlewareTest < I18n::TestCase
4
+ def setup
5
+ super
6
+ I18n.default_locale = :fr
7
+ @app = DummyRackApp.new
8
+ @middleware = I18n::Middleware.new(@app)
9
+ end
10
+
11
+ test "middleware initializes new config object after request" do
12
+ old_i18n_config_object_id = Thread.current[:i18n_config].object_id
13
+ @middleware.call({})
14
+
15
+ updated_i18n_config_object_id = Thread.current[:i18n_config].object_id
16
+ assert_not_equal updated_i18n_config_object_id, old_i18n_config_object_id
17
+ end
18
+
19
+ test "succesfully resets i18n locale to default locale by defining new config" do
20
+ @middleware.call({})
21
+
22
+ assert_equal :fr, I18n.locale
23
+ end
24
+ end
@@ -53,3 +53,9 @@ class I18n::TestCase < TEST_CASE
53
53
  File.dirname(__FILE__) + '/test_data/locales'
54
54
  end
55
55
  end
56
+
57
+ class DummyRackApp
58
+ def call(env)
59
+ I18n.locale = :es
60
+ end
61
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: i18n
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.8.6
4
+ version: 0.9.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Sven Fuchs
@@ -12,8 +12,22 @@ authors:
12
12
  autorequire:
13
13
  bindir: bin
14
14
  cert_chain: []
15
- date: 2017-07-10 00:00:00.000000000 Z
16
- dependencies: []
15
+ date: 2017-10-15 00:00:00.000000000 Z
16
+ dependencies:
17
+ - !ruby/object:Gem::Dependency
18
+ name: concurrent-ruby
19
+ requirement: !ruby/object:Gem::Requirement
20
+ requirements:
21
+ - - "~>"
22
+ - !ruby/object:Gem::Version
23
+ version: '1.0'
24
+ type: :runtime
25
+ prerelease: false
26
+ version_requirements: !ruby/object:Gem::Requirement
27
+ requirements:
28
+ - - "~>"
29
+ - !ruby/object:Gem::Version
30
+ version: '1.0'
17
31
  description: New wave Internationalization support for Ruby.
18
32
  email: rails-i18n@googlegroups.com
19
33
  executables: []
@@ -27,6 +41,7 @@ files:
27
41
  - gemfiles/Gemfile.rails-4.1.x
28
42
  - gemfiles/Gemfile.rails-4.2.x
29
43
  - gemfiles/Gemfile.rails-5.0.x
44
+ - gemfiles/Gemfile.rails-5.1.x
30
45
  - gemfiles/Gemfile.rails-master
31
46
  - lib/i18n.rb
32
47
  - lib/i18n/backend.rb
@@ -59,6 +74,7 @@ files:
59
74
  - lib/i18n/locale/tag/parents.rb
60
75
  - lib/i18n/locale/tag/rfc4646.rb
61
76
  - lib/i18n/locale/tag/simple.rb
77
+ - lib/i18n/middleware.rb
62
78
  - lib/i18n/tests.rb
63
79
  - lib/i18n/tests/basics.rb
64
80
  - lib/i18n/tests/defaults.rb
@@ -101,6 +117,7 @@ files:
101
117
  - test/i18n/gettext_plural_keys_test.rb
102
118
  - test/i18n/interpolate_test.rb
103
119
  - test/i18n/load_path_test.rb
120
+ - test/i18n/middleware_test.rb
104
121
  - test/i18n_test.rb
105
122
  - test/locale/fallbacks_test.rb
106
123
  - test/locale/tag/rfc4646_test.rb
@@ -133,7 +150,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
133
150
  version: 1.3.5
134
151
  requirements: []
135
152
  rubyforge_project: "[none]"
136
- rubygems_version: 2.6.10
153
+ rubygems_version: 2.6.11
137
154
  signing_key:
138
155
  specification_version: 4
139
156
  summary: New wave Internationalization support for Ruby