i18n 0.9.1 → 0.9.3
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 +5 -5
- data/gemfiles/Gemfile.rails-3.2.x +1 -0
- data/gemfiles/Gemfile.rails-4.0.x +1 -0
- data/gemfiles/Gemfile.rails-4.1.x +1 -0
- data/gemfiles/Gemfile.rails-4.2.x +1 -0
- data/gemfiles/Gemfile.rails-5.0.x +1 -0
- data/gemfiles/Gemfile.rails-5.1.x +1 -0
- data/gemfiles/Gemfile.rails-master +1 -0
- data/lib/i18n.rb +9 -2
- data/lib/i18n/backend/base.rb +27 -12
- data/lib/i18n/backend/key_value.rb +66 -5
- data/lib/i18n/backend/simple.rb +5 -0
- data/lib/i18n/config.rb +5 -0
- data/lib/i18n/tests/defaults.rb +4 -0
- data/lib/i18n/tests/interpolation.rb +5 -0
- data/lib/i18n/version.rb +1 -1
- data/test/backend/key_value_test.rb +6 -0
- data/test/backend/simple_test.rb +8 -0
- data/test/i18n_test.rb +21 -5
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 57b2ff3a6c23f6e74b39b1be0a56311a2b49025f71d9e16ac4fde2d93e6448bf
|
4
|
+
data.tar.gz: 7d21368bbe369fc644e10785db19f47f7d5eef492dfdebaa090152470ffe3c00
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 8bd2956e1905c8b3d0dfb65696f6f4b96e91583a649bdf0e81772dad80c72240ee1b96996983b8e44ee312fae58aee63732166268b34669ead66c3f87d716dee
|
7
|
+
data.tar.gz: e74c46af688ac02e8fb776b39dc873ae9951901b9567e08d1fd21b68d0d5677cbc9ceeba2d8b2f2c1500b3f886084e31eafc80083adaa4572017f3ccb67a0028
|
data/lib/i18n.rb
CHANGED
@@ -140,10 +140,14 @@ module I18n
|
|
140
140
|
# called and passed the key and options.
|
141
141
|
#
|
142
142
|
# E.g. assuming the key <tt>:salutation</tt> resolves to:
|
143
|
-
# lambda { |key, options| options[:gender] == 'm' ? "Mr.
|
143
|
+
# lambda { |key, options| options[:gender] == 'm' ? "Mr. #{options[:name]}" : "Mrs. #{options[:name]}" }
|
144
144
|
#
|
145
145
|
# Then <tt>I18n.t(:salutation, :gender => 'w', :name => 'Smith') will result in "Mrs. Smith".
|
146
146
|
#
|
147
|
+
# Note that the string returned by lambda will go through string interpolation too,
|
148
|
+
# so the following lambda would give the same result:
|
149
|
+
# lambda { |key, options| options[:gender] == 'm' ? "Mr. %{name}" : "Mrs. %{name}" }
|
150
|
+
#
|
147
151
|
# It is recommended to use/implement lambdas in an "idempotent" way. E.g. when
|
148
152
|
# a cache layer is put in front of I18n.translate it will generate a cache key
|
149
153
|
# from the argument values passed to #translate. Therefor your lambdas should
|
@@ -157,7 +161,6 @@ module I18n
|
|
157
161
|
handling = options.delete(:throw) && :throw || options.delete(:raise) && :raise # TODO deprecate :raise
|
158
162
|
|
159
163
|
enforce_available_locales!(locale)
|
160
|
-
raise I18n::ArgumentError if key.is_a?(String) && key.empty?
|
161
164
|
|
162
165
|
result = catch(:exception) do
|
163
166
|
if key.is_a?(Array)
|
@@ -293,6 +296,10 @@ module I18n
|
|
293
296
|
end
|
294
297
|
end
|
295
298
|
|
299
|
+
def available_locales_initialized?
|
300
|
+
config.available_locales_initialized?
|
301
|
+
end
|
302
|
+
|
296
303
|
private
|
297
304
|
|
298
305
|
# Any exceptions thrown in translate will be sent to the @@exception_handler
|
data/lib/i18n/backend/base.rb
CHANGED
@@ -22,7 +22,10 @@ module I18n
|
|
22
22
|
end
|
23
23
|
|
24
24
|
def translate(locale, key, options = {})
|
25
|
+
raise I18n::ArgumentError if (key.is_a?(String) || key.is_a?(Symbol)) && key.empty?
|
25
26
|
raise InvalidLocale.new(locale) unless locale
|
27
|
+
return nil if key.nil? && !options.key?(:default)
|
28
|
+
|
26
29
|
entry = lookup(locale, key, options[:scope], options) unless key.nil?
|
27
30
|
|
28
31
|
if entry.nil? && options.key?(:default)
|
@@ -31,17 +34,17 @@ module I18n
|
|
31
34
|
entry = resolve(locale, key, entry, options)
|
32
35
|
end
|
33
36
|
|
37
|
+
entry = entry.dup if entry.is_a?(String)
|
38
|
+
|
39
|
+
count = options[:count]
|
40
|
+
entry = pluralize(locale, entry, count) if count
|
41
|
+
|
34
42
|
if entry.nil?
|
35
43
|
if (options.key?(:default) && !options[:default].nil?) || !options.key?(:default)
|
36
44
|
throw(:exception, I18n::MissingTranslation.new(locale, key, options))
|
37
45
|
end
|
38
46
|
end
|
39
47
|
|
40
|
-
entry = entry.dup if entry.is_a?(String)
|
41
|
-
|
42
|
-
count = options[:count]
|
43
|
-
entry = pluralize(locale, entry, count) if count
|
44
|
-
|
45
48
|
deep_interpolation = options[:deep_interpolation]
|
46
49
|
values = options.except(*RESERVED_KEYS)
|
47
50
|
if values
|
@@ -103,7 +106,8 @@ module I18n
|
|
103
106
|
case subject
|
104
107
|
when Array
|
105
108
|
subject.each do |item|
|
106
|
-
result = resolve(locale, object, item, options)
|
109
|
+
result = resolve(locale, object, item, options)
|
110
|
+
return result unless result.nil?
|
107
111
|
end and nil
|
108
112
|
else
|
109
113
|
resolve(locale, object, subject, options)
|
@@ -147,15 +151,26 @@ module I18n
|
|
147
151
|
entry[key]
|
148
152
|
end
|
149
153
|
|
150
|
-
# Interpolates values into a given
|
154
|
+
# Interpolates values into a given subject.
|
151
155
|
#
|
152
|
-
#
|
156
|
+
# if the given subject is a string then:
|
157
|
+
# method interpolates "file %{file} opened by %%{user}", :file => 'test.txt', :user => 'Mr. X'
|
153
158
|
# # => "file test.txt opened by %{user}"
|
154
|
-
|
155
|
-
|
156
|
-
|
159
|
+
#
|
160
|
+
# if the given subject is an array then:
|
161
|
+
# each element of the array is recursively interpolated (until it finds a string)
|
162
|
+
# method interpolates ["yes, %{user}", ["maybe no, %{user}, "no, %{user}"]], :user => "bartuz"
|
163
|
+
# # => "["yes, bartuz",["maybe no, bartuz", "no, bartuz"]]"
|
164
|
+
|
165
|
+
|
166
|
+
def interpolate(locale, subject, values = {})
|
167
|
+
return subject if values.empty?
|
168
|
+
|
169
|
+
case subject
|
170
|
+
when ::String then I18n.interpolate(subject, values)
|
171
|
+
when ::Array then subject.map { |element| interpolate(locale, element, values) }
|
157
172
|
else
|
158
|
-
|
173
|
+
subject
|
159
174
|
end
|
160
175
|
end
|
161
176
|
|
@@ -1,7 +1,24 @@
|
|
1
1
|
require 'i18n/backend/base'
|
2
|
-
require 'active_support/json'
|
3
2
|
|
4
3
|
module I18n
|
4
|
+
|
5
|
+
begin
|
6
|
+
require 'oj'
|
7
|
+
class JSON
|
8
|
+
class << self
|
9
|
+
def encode(value)
|
10
|
+
Oj::Rails.encode(value)
|
11
|
+
end
|
12
|
+
def decode(value)
|
13
|
+
Oj.load(value)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
rescue LoadError
|
18
|
+
require 'active_support/json'
|
19
|
+
JSON = ActiveSupport::JSON
|
20
|
+
end
|
21
|
+
|
5
22
|
module Backend
|
6
23
|
# This is a basic backend for key value stores. It receives on
|
7
24
|
# initialization the store, which should respond to three methods:
|
@@ -65,14 +82,14 @@ module I18n
|
|
65
82
|
case value
|
66
83
|
when Hash
|
67
84
|
if @subtrees && (old_value = @store[key])
|
68
|
-
old_value =
|
85
|
+
old_value = JSON.decode(old_value)
|
69
86
|
value = old_value.deep_symbolize_keys.deep_merge!(value) if old_value.is_a?(Hash)
|
70
87
|
end
|
71
88
|
when Proc
|
72
89
|
raise "Key-value stores cannot handle procs"
|
73
90
|
end
|
74
91
|
|
75
|
-
@store[key] =
|
92
|
+
@store[key] = JSON.encode(value) unless value.is_a?(Symbol)
|
76
93
|
end
|
77
94
|
end
|
78
95
|
|
@@ -89,8 +106,52 @@ module I18n
|
|
89
106
|
def lookup(locale, key, scope = [], options = {})
|
90
107
|
key = normalize_flat_keys(locale, key, scope, options[:separator])
|
91
108
|
value = @store["#{locale}.#{key}"]
|
92
|
-
value =
|
93
|
-
|
109
|
+
value = JSON.decode(value) if value
|
110
|
+
|
111
|
+
if value.is_a?(Hash)
|
112
|
+
value.deep_symbolize_keys
|
113
|
+
elsif !value.nil?
|
114
|
+
value
|
115
|
+
elsif !@subtrees
|
116
|
+
SubtreeProxy.new("#{locale}.#{key}", @store)
|
117
|
+
end
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
class SubtreeProxy
|
122
|
+
def initialize(master_key, store)
|
123
|
+
@master_key = master_key
|
124
|
+
@store = store
|
125
|
+
@subtree = nil
|
126
|
+
end
|
127
|
+
|
128
|
+
def has_key?(key)
|
129
|
+
@subtree && @subtree.has_key?(key) || self[key]
|
130
|
+
end
|
131
|
+
|
132
|
+
def [](key)
|
133
|
+
unless @subtree && value = @subtree[key]
|
134
|
+
value = @store["#{@master_key}.#{key}"]
|
135
|
+
(@subtree ||= {})[key] = JSON.decode(value) if value
|
136
|
+
end
|
137
|
+
value
|
138
|
+
end
|
139
|
+
|
140
|
+
def is_a?(klass)
|
141
|
+
Hash == klass || super
|
142
|
+
end
|
143
|
+
alias :kind_of? :is_a?
|
144
|
+
|
145
|
+
def instance_of?(klass)
|
146
|
+
Hash == klass || super
|
147
|
+
end
|
148
|
+
|
149
|
+
def nil?
|
150
|
+
@subtree.nil?
|
151
|
+
end
|
152
|
+
|
153
|
+
def inspect
|
154
|
+
@subtree.inspect
|
94
155
|
end
|
95
156
|
end
|
96
157
|
|
data/lib/i18n/backend/simple.rb
CHANGED
@@ -29,6 +29,11 @@ module I18n
|
|
29
29
|
# translations will be overwritten by new ones only at the deepest
|
30
30
|
# level of the hash.
|
31
31
|
def store_translations(locale, data, options = {})
|
32
|
+
if I18n.available_locales_initialized? &&
|
33
|
+
!I18n.available_locales.include?(locale.to_sym) &&
|
34
|
+
!I18n.available_locales.include?(locale.to_s)
|
35
|
+
return data
|
36
|
+
end
|
32
37
|
locale = locale.to_sym
|
33
38
|
translations[locale] ||= {}
|
34
39
|
data = data.deep_symbolize_keys
|
data/lib/i18n/config.rb
CHANGED
@@ -57,6 +57,11 @@ module I18n
|
|
57
57
|
@@available_locales = nil if @@available_locales.empty?
|
58
58
|
@@available_locales_set = nil
|
59
59
|
end
|
60
|
+
|
61
|
+
# Returns true if the available_locales have been initialized
|
62
|
+
def available_locales_initialized?
|
63
|
+
( !!defined?(@@available_locales) && !!@@available_locales )
|
64
|
+
end
|
60
65
|
|
61
66
|
# Clears the available locales set so it can be recomputed again after I18n
|
62
67
|
# gets reloaded.
|
data/lib/i18n/tests/defaults.rb
CHANGED
@@ -24,6 +24,10 @@ module I18n
|
|
24
24
|
assert_equal 'bar', I18n.t(:does_not_exist, :default => [:does_not_exist_2, :'foo.bar'])
|
25
25
|
end
|
26
26
|
|
27
|
+
test "defaults: given an array as a default with false it returns false" do
|
28
|
+
assert_equal false, I18n.t(:does_not_exist, :default => [false])
|
29
|
+
end
|
30
|
+
|
27
31
|
test "defaults: given false it returns false" do
|
28
32
|
assert_equal false, I18n.t(:does_not_exist, :default => false)
|
29
33
|
end
|
@@ -54,6 +54,11 @@ module I18n
|
|
54
54
|
assert_equal 'Hi Yehuda!', interpolate(:interpolate, :name => 'Yehuda')
|
55
55
|
end
|
56
56
|
|
57
|
+
test "interpolation: given an array interpolates each element" do
|
58
|
+
I18n.backend.store_translations(:en, :array_interpolate => ['Hi', 'Mr. %{name}', 'or sir %{name}'])
|
59
|
+
assert_equal ['Hi', 'Mr. Bartuz', 'or sir Bartuz'], interpolate(:array_interpolate, :name => 'Bartuz')
|
60
|
+
end
|
61
|
+
|
57
62
|
test "interpolation: given the translation is in utf-8 it still works" do
|
58
63
|
assert_equal 'Häi David!', interpolate(:default => 'Häi %{name}!', :name => 'David')
|
59
64
|
end
|
data/lib/i18n/version.rb
CHANGED
@@ -40,4 +40,10 @@ class I18nBackendKeyValueTest < I18n::TestCase
|
|
40
40
|
I18n.t("foo", :raise => true)
|
41
41
|
end
|
42
42
|
end
|
43
|
+
|
44
|
+
test "translate handles subtrees for pluralization" do
|
45
|
+
setup_backend!(false)
|
46
|
+
store_translations(:en, :bar => { :one => "One" })
|
47
|
+
assert_equal("One", I18n.t("bar", :count => 1))
|
48
|
+
end
|
43
49
|
end if I18n::TestCase.key_value?
|
data/test/backend/simple_test.rb
CHANGED
@@ -70,6 +70,14 @@ class I18nBackendSimpleTest < I18n::TestCase
|
|
70
70
|
assert_equal Hash[:'en', {:foo => {:bar => 'bar', :baz => 'baz'}}], translations
|
71
71
|
end
|
72
72
|
|
73
|
+
test "simple store_translations: do not store translations for locales not explicitly marked as available" do
|
74
|
+
I18n.available_locales = [:en, :es]
|
75
|
+
store_translations(:fr, :foo => {:bar => 'barfr', :baz => 'bazfr'})
|
76
|
+
store_translations(:es, :foo => {:bar => 'bares', :baz => 'bazes'})
|
77
|
+
assert_nil translations[:fr]
|
78
|
+
assert_equal Hash[:foo, {:bar => 'bares', :baz => 'bazes'}], translations[:es]
|
79
|
+
end
|
80
|
+
|
73
81
|
# reloading translations
|
74
82
|
|
75
83
|
test "simple reload_translations: unloads translations" do
|
data/test/i18n_test.rb
CHANGED
@@ -216,6 +216,22 @@ class I18nTest < I18n::TestCase
|
|
216
216
|
assert_raise(I18n::ArgumentError) { I18n.t("") }
|
217
217
|
end
|
218
218
|
|
219
|
+
test "translate given an empty symbol as a key raises an I18n::ArgumentError" do
|
220
|
+
assert_raise(I18n::ArgumentError) { I18n.t(:"") }
|
221
|
+
end
|
222
|
+
|
223
|
+
test "translate given an array with empty string as a key raises an I18n::ArgumentError" do
|
224
|
+
assert_raise(I18n::ArgumentError) { I18n.t(["", :foo]) }
|
225
|
+
end
|
226
|
+
|
227
|
+
test "translate given an empty array as a key returns empty array" do
|
228
|
+
assert_equal [], I18n.t([])
|
229
|
+
end
|
230
|
+
|
231
|
+
test "translate given nil returns nil" do
|
232
|
+
assert_nil I18n.t(nil)
|
233
|
+
end
|
234
|
+
|
219
235
|
test "translate given an unavailable locale rases an I18n::InvalidLocale" do
|
220
236
|
begin
|
221
237
|
I18n.config.enforce_available_locales = true
|
@@ -405,7 +421,7 @@ class I18nTest < I18n::TestCase
|
|
405
421
|
I18n.config.enforce_available_locales = false
|
406
422
|
end
|
407
423
|
end
|
408
|
-
|
424
|
+
|
409
425
|
test 'I18n.reload! reloads the set of locales that are enforced' do
|
410
426
|
begin
|
411
427
|
# Clear the backend that affects the available locales and somehow can remain
|
@@ -413,9 +429,9 @@ class I18nTest < I18n::TestCase
|
|
413
429
|
# For instance, it contains enough translations to cause a false positive with
|
414
430
|
# this test when ran with --seed=50992
|
415
431
|
I18n.backend = I18n::Backend::Simple.new
|
416
|
-
|
432
|
+
|
417
433
|
assert !I18n.available_locales.include?(:de), "Available locales should not include :de at this point"
|
418
|
-
|
434
|
+
|
419
435
|
I18n.enforce_available_locales = true
|
420
436
|
|
421
437
|
assert_raise(I18n::InvalidLocale) { I18n.default_locale = :de }
|
@@ -431,11 +447,11 @@ class I18nTest < I18n::TestCase
|
|
431
447
|
store_translations(:en, :foo => 'Foo in :en')
|
432
448
|
store_translations(:de, :foo => 'Foo in :de')
|
433
449
|
store_translations(:pl, :foo => 'Foo in :pl')
|
434
|
-
|
450
|
+
|
435
451
|
assert I18n.available_locales.include?(:de), ":de should now be allowed"
|
436
452
|
assert I18n.available_locales.include?(:en), ":en should now be allowed"
|
437
453
|
assert I18n.available_locales.include?(:pl), ":pl should now be allowed"
|
438
|
-
|
454
|
+
|
439
455
|
assert_nothing_raised { I18n.default_locale = I18n.locale = :en }
|
440
456
|
assert_nothing_raised { I18n.default_locale = I18n.locale = :de }
|
441
457
|
assert_nothing_raised { I18n.default_locale = I18n.locale = :pl }
|
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.9.
|
4
|
+
version: 0.9.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Sven Fuchs
|
@@ -13,7 +13,7 @@ authors:
|
|
13
13
|
autorequire:
|
14
14
|
bindir: bin
|
15
15
|
cert_chain: []
|
16
|
-
date:
|
16
|
+
date: 2018-01-22 00:00:00.000000000 Z
|
17
17
|
dependencies:
|
18
18
|
- !ruby/object:Gem::Dependency
|
19
19
|
name: concurrent-ruby
|
@@ -151,7 +151,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
151
151
|
version: 1.3.5
|
152
152
|
requirements: []
|
153
153
|
rubyforge_project: "[none]"
|
154
|
-
rubygems_version: 2.
|
154
|
+
rubygems_version: 2.7.4
|
155
155
|
signing_key:
|
156
156
|
specification_version: 4
|
157
157
|
summary: New wave Internationalization support for Ruby
|