i18n 1.14.4 → 1.14.5

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
  SHA256:
3
- metadata.gz: ef99abbb2ed698cd9dd77ab484720a5ecf68be96a7064f2f8b432a69758ada07
4
- data.tar.gz: 0a4ade5577fe636c03d6ef9ca11f7a26b80a5c58078ee87c2f9dcf9fdd6882de
3
+ metadata.gz: 8e29c720198c6fd20a8ec55a99ad4ce81c2ff09abf74a55ee6e09513ac17546c
4
+ data.tar.gz: 6ad9b851da6ba7c857dbd79b9e817493f7eaba91be46f16cec3a86cb94c32c11
5
5
  SHA512:
6
- metadata.gz: 21b666c06e7c8ebdb78088ef2ecd8da866ebd414dff3f3a8535b3e950c12bf0f38695a22acac6da7775e8e245c7a99a0d1d9a6bc409e0ea3d552520a0be26f68
7
- data.tar.gz: c5f81a0bafbf70daa4a2c4374f3906ef31cea1d8f94d5d5e9b980224d1b6bc75f95cdd3e08709f6cae410c34f4285deb375d7e5b06e19f283743221606e23434
6
+ metadata.gz: 7de3901b122039da2a99507e40dbe5e57ce8e5622c14591ebf251adf563c763f55d2f1fb1bc7d54c5f2be427a37b81839e636de7eee434a53ab80a39c4f8bf53
7
+ data.tar.gz: 1bfd4bd7c5dd8de6df524ae64d652e2f785955a1928bd3bca66e3ba8515e2d4d60c83ff576c51ca84e744625874145c0850f301b8d2fd6090c226541ad389575
@@ -188,8 +188,8 @@ module I18n
188
188
  #
189
189
  # if the given subject is an array then:
190
190
  # each element of the array is recursively interpolated (until it finds a string)
191
- # method interpolates ["yes, %{user}", ["maybe no, %{user}, "no, %{user}"]], :user => "bartuz"
192
- # # => "["yes, bartuz",["maybe no, bartuz", "no, bartuz"]]"
191
+ # method interpolates ["yes, %{user}", ["maybe no, %{user}", "no, %{user}"]], :user => "bartuz"
192
+ # # => ["yes, bartuz", ["maybe no, bartuz", "no, bartuz"]]
193
193
  def interpolate(locale, subject, values = EMPTY_HASH)
194
194
  return subject if values.empty?
195
195
 
@@ -90,11 +90,13 @@ module I18n
90
90
  protected
91
91
 
92
92
  def compute(tags, include_defaults = true, exclude = [])
93
- result = Array(tags).flat_map do |tag|
93
+ result = []
94
+ Array(tags).each do |tag|
94
95
  tags = I18n::Locale::Tag.tag(tag).self_and_parents.map! { |t| t.to_sym } - exclude
95
- tags.each { |_tag| tags += compute(@map[_tag], false, exclude + tags) if @map[_tag] }
96
- tags
96
+ result += tags
97
+ tags.each { |_tag| result += compute(@map[_tag], false, exclude + result) if @map[_tag] }
97
98
  end
99
+
98
100
  result.push(*defaults) if include_defaults
99
101
  result.uniq!
100
102
  result.compact!
@@ -118,6 +118,24 @@ module I18n
118
118
  assert_raises(I18n::ReservedInterpolationKey) { interpolate(:interpolate) }
119
119
  end
120
120
 
121
+ test "interpolation: it does not raise I18n::ReservedInterpolationKey for escaped variables" do
122
+ assert_nothing_raised do
123
+ assert_equal '%{separator}', interpolate(:foo => :bar, :default => '%%{separator}')
124
+ end
125
+
126
+ # Note: The two interpolations below do not remove the escape character (%) because
127
+ # I18n should not alter the strings when no interpolation parameters are given,
128
+ # see the comment at the top of this file.
129
+ assert_nothing_raised do
130
+ assert_equal '%%{scope}', interpolate(:default => '%%{scope}')
131
+ end
132
+
133
+ I18n.backend.store_translations(:en, :interpolate => 'Hi %%{scope}!')
134
+ assert_nothing_raised do
135
+ assert_equal 'Hi %%{scope}!', interpolate(:interpolate)
136
+ end
137
+ end
138
+
121
139
  test "interpolation: deep interpolation for default string" do
122
140
  assert_equal 'Hi %{name}!', interpolate(:default => 'Hi %{name}!', :deep_interpolation => true)
123
141
  end
data/lib/i18n/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module I18n
4
- VERSION = "1.14.4"
4
+ VERSION = "1.14.5"
5
5
  end
data/lib/i18n.rb CHANGED
@@ -48,7 +48,7 @@ module I18n
48
48
  end
49
49
 
50
50
  def self.reserved_keys_pattern # :nodoc:
51
- @reserved_keys_pattern ||= /%\{(#{RESERVED_KEYS.join("|")})\}/
51
+ @reserved_keys_pattern ||= /(?<!%)%\{(#{RESERVED_KEYS.join("|")})\}/
52
52
  end
53
53
 
54
54
  module Base
@@ -231,6 +231,35 @@ module I18n
231
231
  end
232
232
  alias :t! :translate!
233
233
 
234
+ # Returns an array of interpolation keys for the given translation key
235
+ #
236
+ # *Examples*
237
+ #
238
+ # Suppose we have the following:
239
+ # I18n.t 'example.zero' == 'Zero interpolations'
240
+ # I18n.t 'example.one' == 'One interpolation %{foo}'
241
+ # I18n.t 'example.two' == 'Two interpolations %{foo} %{bar}'
242
+ # I18n.t 'example.three' == ['One %{foo}', 'Two %{bar}', 'Three %{baz}']
243
+ # I18n.t 'example.one', locale: :other == 'One interpolation %{baz}'
244
+ #
245
+ # Then we can expect the following results:
246
+ # I18n.interpolation_keys('example.zero') #=> []
247
+ # I18n.interpolation_keys('example.one') #=> ['foo']
248
+ # I18n.interpolation_keys('example.two') #=> ['foo', 'bar']
249
+ # I18n.interpolation_keys('example.three') #=> ['foo', 'bar', 'baz']
250
+ # I18n.interpolation_keys('one', scope: 'example', locale: :other) #=> ['baz']
251
+ # I18n.interpolation_keys('does-not-exist') #=> []
252
+ # I18n.interpolation_keys('example') #=> []
253
+ def interpolation_keys(key, **options)
254
+ raise I18n::ArgumentError if !key.is_a?(String) || key.empty?
255
+
256
+ return [] unless exists?(key, **options.slice(:locale, :scope))
257
+
258
+ translation = translate(key, **options.slice(:locale, :scope))
259
+ interpolation_keys_from_translation(translation)
260
+ .flatten.compact
261
+ end
262
+
234
263
  # Returns true if a translation exists for a given key, otherwise returns false.
235
264
  def exists?(key, _locale = nil, locale: _locale, **options)
236
265
  locale ||= config.locale
@@ -429,6 +458,17 @@ module I18n
429
458
  keys
430
459
  end
431
460
  end
461
+
462
+ def interpolation_keys_from_translation(translation)
463
+ case translation
464
+ when ::String
465
+ translation.scan(Regexp.union(I18n.config.interpolation_patterns))
466
+ when ::Array
467
+ translation.map { |element| interpolation_keys_from_translation(element) }
468
+ else
469
+ []
470
+ end
471
+ end
432
472
  end
433
473
 
434
474
  extend Base
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: 1.14.4
4
+ version: 1.14.5
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: 2024-03-06 00:00:00.000000000 Z
16
+ date: 2024-05-06 00:00:00.000000000 Z
17
17
  dependencies:
18
18
  - !ruby/object:Gem::Dependency
19
19
  name: concurrent-ruby