i18n 1.8.1 → 1.8.6

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: d32ff36d5385248b7ee10b2f56290d334d8960c4bf2ad235586cb3ced8076ba3
4
- data.tar.gz: 61ce5e019df9b588683df2f5d7450d9a59e11c1113149c621a52ade0e8008c12
3
+ metadata.gz: d9b8df30b8d8d663013890240fddf75eda1bd6c117b160ce5bfd319fc6a0e573
4
+ data.tar.gz: 1dbf4d1a8318f5000647f0d11a0ac8d779221e47668a0bc2717f39979b47c127
5
5
  SHA512:
6
- metadata.gz: 447fbf79001dabdeb67c2f40fced56fc33996c97e04aa9fafed6944f105c57d8b76f2a01a7f962501f3b9c746d0f20e14815210e9cdad5c38387f7ea75e95949
7
- data.tar.gz: 0a520450edfe558d3441e1d14bbd5a23c6e3ee2814286979722a43c8e570f4d130c3a953c558ed1ab4e9149035752b59a0d2a41475ddb84122825839bdcf3ecd
6
+ metadata.gz: b4f2bf69569a1cf19f77905a58aff61bc764229adf57b3f539a6d59e7006a5b9299de3db48360ae09b33817512096af052925569480cc387494058c635451d97
7
+ data.tar.gz: 9e8df6cd121e09dfcfdb2384542bbfa4837b7ddb5442d0d5f7ee14832e1b0b7fab0ba65192b733c490b8b25dfd1cfc0bc7e0c87ec57e1b47327caeec067337ad
data/README.md CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  [![Build Status](https://github.com/ruby-i18n/i18n/workflows/Ruby/badge.svg)](https://github.com/ruby-i18n/i18n/actions?query=workflow%3ARuby)
4
4
 
5
- Ruby Internationalization and localization solution.
5
+ Ruby internationalization and localization (i18n) solution.
6
6
 
7
7
  Currently maintained by @radar.
8
8
 
@@ -12,7 +12,7 @@ Currently maintained by @radar.
12
12
 
13
13
  You will most commonly use this library within a Rails app.
14
14
 
15
- [See the Rails Guide](http://guides.rubyonrails.org/i18n.html) for an example of its usage.
15
+ [See the Rails Guide](https://guides.rubyonrails.org/i18n.html) for an example of its usage.
16
16
 
17
17
  ### Ruby (without Rails)
18
18
 
@@ -51,16 +51,16 @@ I18n.t(:test) # => "Dies ist ein Test"
51
51
 
52
52
  ## Features
53
53
 
54
- * translation and localization
55
- * interpolation of values to translations (Ruby 1.9 compatible syntax)
56
- * pluralization (CLDR compatible)
57
- * customizable transliteration to ASCII
58
- * flexible defaults
59
- * bulk lookup
60
- * lambdas as translation data
61
- * custom key/scope separator
62
- * custom exception handlers
63
- * extensible architecture with a swappable backend
54
+ * Translation and localization
55
+ * Interpolation of values to translations
56
+ * Pluralization (CLDR compatible)
57
+ * Customizable transliteration to ASCII
58
+ * Flexible defaults
59
+ * Bulk lookup
60
+ * Lambdas as translation data
61
+ * Custom key/scope separator
62
+ * Custom exception handlers
63
+ * Extensible architecture with a swappable backend
64
64
 
65
65
  ## Pluggable Features
66
66
 
@@ -106,19 +106,16 @@ follow the usual test setup and should be easy to grok.
106
106
 
107
107
  ## More Documentation
108
108
 
109
- Additional documentation can be found here: https://github.com/svenfuchs/i18n/wiki
110
-
111
- ## Authors
112
-
113
- * [Sven Fuchs](http://www.artweb-design.de)
114
- * [Joshua Harvey](http://www.workingwithrails.com/person/759-joshua-harvey)
115
- * [Stephan Soller](http://www.arkanis-development.de)
116
- * [Saimon Moore](http://saimonmoore.net)
117
- * [Matt Aimonetti](https://matt.aimonetti.net/)
109
+ Additional documentation can be found here: https://github.com/ruby-i18n/i18n/wiki
118
110
 
119
111
  ## Contributors
120
112
 
121
- https://github.com/svenfuchs/i18n/graphs/contributors
113
+ * @radar
114
+ * @carlosantoniodasilva
115
+ * @josevalim
116
+ * @knapo
117
+ * @tigrish
118
+ * [and many more](https://github.com/ruby-i18n/i18n/graphs/contributors)
122
119
 
123
120
  ## License
124
121
 
@@ -192,7 +192,7 @@ module I18n
192
192
  # I18n.t(:salutation, { :gender => 'w', :name => 'Smith' })
193
193
  # I18n.t(:salutation, any_hash)
194
194
  #
195
- def translate(key = nil, *, throw: false, raise: false, locale: nil, **options) # TODO deprecate :raise
195
+ def translate(key = nil, throw: false, raise: false, locale: nil, **options) # TODO deprecate :raise
196
196
  locale ||= config.locale
197
197
  raise Disabled.new('t') if locale == false
198
198
  enforce_available_locales!(locale)
@@ -217,17 +217,17 @@ module I18n
217
217
 
218
218
  # Wrapper for <tt>translate</tt> that adds <tt>:raise => true</tt>. With
219
219
  # this option, if no translation is found, it will raise <tt>I18n::MissingTranslationData</tt>
220
- def translate!(key, options = EMPTY_HASH)
221
- translate(key, **options.merge(:raise => true))
220
+ def translate!(key, **options)
221
+ translate(key, **options, raise: true)
222
222
  end
223
223
  alias :t! :translate!
224
224
 
225
225
  # Returns true if a translation exists for a given key, otherwise returns false.
226
- def exists?(key, _locale = nil, locale: _locale)
226
+ def exists?(key, _locale = nil, locale: _locale, **options)
227
227
  locale ||= config.locale
228
228
  raise Disabled.new('exists?') if locale == false
229
229
  raise I18n::ArgumentError if key.is_a?(String) && key.empty?
230
- config.backend.exists?(locale, key)
230
+ config.backend.exists?(locale, key, options)
231
231
  end
232
232
 
233
233
  # Transliterates UTF-8 characters to ASCII. By default this method will
@@ -281,7 +281,7 @@ module I18n
281
281
  # I18n.transliterate("Jürgen") # => "Juergen"
282
282
  # I18n.transliterate("Jürgen", :locale => :en) # => "Jurgen"
283
283
  # I18n.transliterate("Jürgen", :locale => :de) # => "Juergen"
284
- def transliterate(key, *, throw: false, raise: false, locale: nil, replacement: nil, **options)
284
+ def transliterate(key, throw: false, raise: false, locale: nil, replacement: nil, **options)
285
285
  locale ||= config.locale
286
286
  raise Disabled.new('transliterate') if locale == false
287
287
  enforce_available_locales!(locale)
@@ -389,7 +389,7 @@ module I18n
389
389
  @@normalized_key_cache[separator][key] ||=
390
390
  case key
391
391
  when Array
392
- key.map { |k| normalize_key(k, separator) }.flatten
392
+ key.flat_map { |k| normalize_key(k, separator) }
393
393
  else
394
394
  keys = key.to_s.split(separator)
395
395
  keys.delete('')
@@ -64,7 +64,7 @@ module I18n
64
64
  entry
65
65
  end
66
66
 
67
- def exists?(locale, key)
67
+ def exists?(locale, key, options = EMPTY_HASH)
68
68
  lookup(locale, key) != nil
69
69
  end
70
70
 
@@ -146,7 +146,7 @@ module I18n
146
146
  I18n.translate(subject, **options.merge(:locale => locale, :throw => true))
147
147
  when Proc
148
148
  date_or_time = options.delete(:object) || object
149
- resolve(locale, object, subject.call(date_or_time, options))
149
+ resolve(locale, object, subject.call(date_or_time, **options))
150
150
  else
151
151
  subject
152
152
  end
@@ -163,6 +163,7 @@ module I18n
163
163
  # not standard with regards to the CLDR pluralization rules.
164
164
  # Other backends can implement more flexible or complex pluralization rules.
165
165
  def pluralize(locale, entry, count)
166
+ entry = entry.reject { |k, _v| k == :attributes } if entry.is_a?(Hash)
166
167
  return entry unless entry.is_a?(Hash) && count && entry.values.none? { |v| v.is_a?(Hash) }
167
168
 
168
169
  key = pluralization_key(entry, count)
@@ -73,9 +73,9 @@ module I18n
73
73
  throw(:exception, I18n::MissingTranslation.new(locale, key, options))
74
74
  end
75
75
 
76
- def exists?(locale, key)
76
+ def exists?(locale, key, options = EMPTY_HASH)
77
77
  backends.any? do |backend|
78
- backend.exists?(locale, key)
78
+ backend.exists?(locale, key, options)
79
79
  end
80
80
  end
81
81
 
@@ -101,8 +101,7 @@ module I18n
101
101
  init_translations unless initialized?
102
102
  translations
103
103
  end
104
-
105
- memo.deep_merge!(partial_translations)
104
+ memo.deep_merge!(partial_translations) { |_, a, b| b || a }
106
105
  end
107
106
  end
108
107
 
@@ -10,17 +10,15 @@
10
10
  #
11
11
  # I18n::Backend::Simple.include(I18n::Backend::Fallbacks)
12
12
  module I18n
13
- @@fallbacks = nil
14
-
15
13
  class << self
16
14
  # Returns the current fallbacks implementation. Defaults to +I18n::Locale::Fallbacks+.
17
15
  def fallbacks
18
- @@fallbacks ||= I18n::Locale::Fallbacks.new
16
+ Thread.current[:i18n_fallbacks] ||= I18n::Locale::Fallbacks.new
19
17
  end
20
18
 
21
19
  # Sets the current fallbacks implementation. Use this to set a different fallbacks implementation.
22
20
  def fallbacks=(fallbacks)
23
- @@fallbacks = fallbacks
21
+ Thread.current[:i18n_fallbacks] = fallbacks.is_a?(Array) ? I18n::Locale::Fallbacks.new(fallbacks) : fallbacks
24
22
  end
25
23
  end
26
24
 
@@ -46,7 +44,10 @@ module I18n
46
44
  begin
47
45
  catch(:exception) do
48
46
  result = super(fallback, key, fallback_options)
49
- return result unless result.nil?
47
+ unless result.nil?
48
+ on_fallback(locale, fallback, key, options) if locale != fallback
49
+ return result
50
+ end
50
51
  end
51
52
  rescue I18n::InvalidLocale
52
53
  # we do nothing when the locale is invalid, as this is a fallback anyways.
@@ -68,7 +69,8 @@ module I18n
68
69
  return first_non_symbol_default
69
70
  end
70
71
 
71
- def exists?(locale, key)
72
+ def exists?(locale, key, options = EMPTY_HASH)
73
+ return super unless options.fetch(:fallback, true)
72
74
  I18n.fallbacks[locale].each do |fallback|
73
75
  begin
74
76
  return true if super(fallback, key)
@@ -79,6 +81,13 @@ module I18n
79
81
 
80
82
  false
81
83
  end
84
+
85
+ private
86
+
87
+ # Overwrite on_fallback to add specified logic when the fallback succeeds.
88
+ def on_fallback(_original_locale, _fallback_locale, _key, _optoins)
89
+ nil
90
+ end
82
91
  end
83
92
  end
84
93
  end
@@ -18,14 +18,17 @@ module I18n
18
18
  # and creates way less objects than the one at I18n.normalize_keys.
19
19
  # It also handles escaping the translation keys.
20
20
  def self.normalize_flat_keys(locale, key, scope, separator)
21
- keys = [scope, key].flatten.compact
21
+ keys = [scope, key]
22
+ keys.flatten!
23
+ keys.compact!
24
+
22
25
  separator ||= I18n.default_separator
23
26
 
24
27
  if separator != FLATTEN_SEPARATOR
25
- keys.map! do |k|
26
- k.to_s.tr("#{FLATTEN_SEPARATOR}#{separator}",
27
- "#{SEPARATOR_ESCAPE_CHAR}#{FLATTEN_SEPARATOR}")
28
- end
28
+ from_str = "#{FLATTEN_SEPARATOR}#{separator}"
29
+ to_str = "#{SEPARATOR_ESCAPE_CHAR}#{FLATTEN_SEPARATOR}"
30
+
31
+ keys.map! { |k| k.to_s.tr from_str, to_str }
29
32
  end
30
33
 
31
34
  keys.join(".")
@@ -29,7 +29,7 @@ module I18n
29
29
  # either pick a special :zero translation even for languages where the
30
30
  # pluralizer does not return a :zero key.
31
31
  def pluralize(locale, entry, count)
32
- return entry unless entry.is_a?(Hash) && count && entry.values.none? { |v| v.is_a?(Hash) }
32
+ return entry unless entry.is_a?(Hash) && count
33
33
 
34
34
  pluralizer = pluralizer(locale)
35
35
  if pluralizer.respond_to?(:call)
@@ -18,12 +18,24 @@ module I18n
18
18
  end
19
19
  end
20
20
 
21
- # deep_merge_hash! by Stefan Rusterholz, see http://www.ruby-forum.com/topic/142809
22
- def deep_merge!(data)
23
- merger = lambda do |_key, v1, v2|
24
- Hash === v1 && Hash === v2 ? v1.merge(v2, &merger) : v2
21
+ # deep_merge from activesupport 5
22
+ # Copyright (c) 2005-2019 David Heinemeier Hansson
23
+ def deep_merge(other_hash, &block)
24
+ dup.deep_merge!(other_hash, &block)
25
+ end
26
+
27
+ # deep_merge! from activesupport 5
28
+ # Copyright (c) 2005-2019 David Heinemeier Hansson
29
+ def deep_merge!(other_hash, &block)
30
+ merge!(other_hash) do |key, this_val, other_val|
31
+ if this_val.is_a?(Hash) && other_val.is_a?(Hash)
32
+ this_val.deep_merge(other_val, &block)
33
+ elsif block_given?
34
+ block.call(key, this_val, other_val)
35
+ else
36
+ other_val
37
+ end
25
38
  end
26
- merge!(data, &merger)
27
39
  end
28
40
 
29
41
  def symbolize_key(key)
@@ -8,7 +8,7 @@ module I18n
8
8
  /%<(\w+)>(.*?\d*\.?\d*[bBdiouxXeEfgGcps])/ # matches placeholders like "%<foo>.d"
9
9
  ].freeze
10
10
  INTERPOLATION_PATTERN = Regexp.union(DEFAULT_INTERPOLATION_PATTERNS)
11
- deprecate_constant :INTERPOLATION_PATTERN if method_defined? :INTERPOLATION_PATTERN
11
+ deprecate_constant :INTERPOLATION_PATTERN
12
12
 
13
13
  class << self
14
14
  # Return String or raises MissingInterpolationArgument exception.
@@ -26,7 +26,7 @@
26
26
  #
27
27
  # I18n.default_locale = :"en-US"
28
28
  # I18n.fallbacks = I18n::Locale::Fallbacks.new(:"de-AT" => :"de-DE")
29
- # I18n.fallbacks[:"de-AT"] # => [:"de-AT", :"de-DE", :de, :"en-US", :en]
29
+ # I18n.fallbacks[:"de-AT"] # => [:"de-AT", :de, :"de-DE"]
30
30
  #
31
31
  # # using a custom locale as default fallback locale
32
32
  #
@@ -60,7 +60,7 @@ module I18n
60
60
  end
61
61
 
62
62
  def defaults=(defaults)
63
- @defaults = defaults.map { |default| compute(default, false) }.flatten
63
+ @defaults = defaults.flat_map { |default| compute(default, false) }
64
64
  end
65
65
  attr_reader :defaults
66
66
 
@@ -84,13 +84,15 @@ module I18n
84
84
  protected
85
85
 
86
86
  def compute(tags, include_defaults = true, exclude = [])
87
- result = Array(tags).collect do |tag|
87
+ result = Array(tags).flat_map do |tag|
88
88
  tags = I18n::Locale::Tag.tag(tag).self_and_parents.map! { |t| t.to_sym } - exclude
89
89
  tags.each { |_tag| tags += compute(@map[_tag], false, exclude + tags) if @map[_tag] }
90
90
  tags
91
- end.flatten
91
+ end
92
92
  result.push(*defaults) if include_defaults
93
- result.uniq.compact
93
+ result.uniq!
94
+ result.compact!
95
+ result
94
96
  end
95
97
  end
96
98
  end
@@ -3,18 +3,20 @@ module I18n
3
3
  module Tag
4
4
  module Parents
5
5
  def parent
6
- @parent ||= begin
7
- segs = to_a.compact
8
- segs.length > 1 ? self.class.tag(*segs[0..(segs.length-2)].join('-')) : nil
9
- end
6
+ @parent ||=
7
+ begin
8
+ segs = to_a
9
+ segs.compact!
10
+ segs.length > 1 ? self.class.tag(*segs[0..(segs.length - 2)].join('-')) : nil
11
+ end
10
12
  end
11
13
 
12
14
  def self_and_parents
13
- @self_and_parents ||= [self] + parents
15
+ @self_and_parents ||= [self].concat parents
14
16
  end
15
17
 
16
18
  def parents
17
- @parents ||= ([parent] + (parent ? parent.parents : [])).compact
19
+ @parents ||= parent ? [parent].concat(parent.parents) : []
18
20
  end
19
21
  end
20
22
  end
@@ -19,7 +19,7 @@ module I18n
19
19
  end
20
20
 
21
21
  def subtags
22
- @subtags = tag.to_s.split('-').map { |subtag| subtag.to_s }
22
+ @subtags = tag.to_s.split('-').map!(&:to_s)
23
23
  end
24
24
 
25
25
  def to_sym
@@ -52,19 +52,20 @@ module I18n
52
52
  test "localize Time: given a format that resolves to a Proc it calls the Proc with the object" do
53
53
  setup_time_proc_translations
54
54
  time = ::Time.utc(2008, 3, 1, 6, 0)
55
- assert_equal I18n::Tests::Localization::Procs.inspect_args([time, {}]), I18n.l(time, :format => :proc, :locale => :ru)
55
+ assert_equal I18n::Tests::Localization::Procs.inspect_args([time], {}), I18n.l(time, :format => :proc, :locale => :ru)
56
56
  end
57
57
 
58
58
  test "localize Time: given a format that resolves to a Proc it calls the Proc with the object and extra options" do
59
59
  setup_time_proc_translations
60
60
  time = ::Time.utc(2008, 3, 1, 6, 0)
61
61
  options = { :foo => 'foo' }
62
- assert_equal I18n::Tests::Localization::Procs.inspect_args([time, options]), I18n.l(time, **options.merge(:format => :proc, :locale => :ru))
62
+ assert_equal I18n::Tests::Localization::Procs.inspect_args([time], options), I18n.l(time, **options.merge(:format => :proc, :locale => :ru))
63
63
  end
64
64
 
65
65
  protected
66
66
 
67
- def self.inspect_args(args)
67
+ def self.inspect_args(args, kwargs)
68
+ args << kwargs
68
69
  args = args.map do |arg|
69
70
  case arg
70
71
  when ::Time, ::DateTime
@@ -85,12 +86,12 @@ module I18n
85
86
  I18n.backend.store_translations :ru, {
86
87
  :time => {
87
88
  :formats => {
88
- :proc => lambda { |*args| I18n::Tests::Localization::Procs.inspect_args(args) }
89
+ :proc => lambda { |*args, **kwargs| I18n::Tests::Localization::Procs.inspect_args(args, kwargs) }
89
90
  }
90
91
  },
91
92
  :date => {
92
93
  :formats => {
93
- :proc => lambda { |*args| I18n::Tests::Localization::Procs.inspect_args(args) }
94
+ :proc => lambda { |*args, **kwargs| I18n::Tests::Localization::Procs.inspect_args(args, kwargs) }
94
95
  },
95
96
  :'day_names' => lambda { |key, options|
96
97
  (options[:format] =~ /^%A/) ?
@@ -8,6 +8,11 @@ module I18n
8
8
  assert_equal '[:a_lambda, {:foo=>"foo"}]', I18n.t(:a_lambda, :foo => 'foo')
9
9
  end
10
10
 
11
+ test "lookup: given a translation is a proc it passes the interpolation values as keyword arguments" do
12
+ I18n.backend.store_translations(:en, :a_lambda => lambda { |key, foo:, **| I18n::Tests::Procs.filter_args(key, foo: foo) })
13
+ assert_equal '[:a_lambda, {:foo=>"foo"}]', I18n.t(:a_lambda, :foo => 'foo')
14
+ end
15
+
11
16
  test "defaults: given a default is a Proc it calls it with the key and interpolation values" do
12
17
  proc = lambda { |*args| I18n::Tests::Procs.filter_args(*args) }
13
18
  assert_equal '[nil, {:foo=>"foo"}]', I18n.t(nil, :default => proc, :foo => 'foo')
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module I18n
4
- VERSION = "1.8.1"
4
+ VERSION = "1.8.6"
5
5
  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: 1.8.1
4
+ version: 1.8.6
5
5
  platform: ruby
6
6
  authors:
7
7
  - Sven Fuchs
@@ -10,10 +10,10 @@ authors:
10
10
  - Stephan Soller
11
11
  - Saimon Moore
12
12
  - Ryan Bigg
13
- autorequire:
13
+ autorequire:
14
14
  bindir: bin
15
15
  cert_chain: []
16
- date: 2020-01-09 00:00:00.000000000 Z
16
+ date: 2021-01-01 00:00:00.000000000 Z
17
17
  dependencies:
18
18
  - !ruby/object:Gem::Dependency
19
19
  name: concurrent-ruby
@@ -86,20 +86,24 @@ homepage: https://github.com/ruby-i18n/i18n
86
86
  licenses:
87
87
  - MIT
88
88
  metadata:
89
- bug_tracker_uri: https://github.com/svenfuchs/i18n/issues
90
- changelog_uri: https://github.com/svenfuchs/i18n/releases
89
+ bug_tracker_uri: https://github.com/ruby-i18n/i18n/issues
90
+ changelog_uri: https://github.com/ruby-i18n/i18n/releases
91
91
  documentation_uri: https://guides.rubyonrails.org/i18n.html
92
- source_code_uri: https://github.com/svenfuchs/i18n
92
+ source_code_uri: https://github.com/ruby-i18n/i18n
93
93
  post_install_message: |2+
94
94
 
95
95
  HEADS UP! i18n 1.1 changed fallbacks to exclude default locale.
96
96
  But that may break your application.
97
97
 
98
+ If you are upgrading your Rails application from an older version of Rails:
99
+
98
100
  Please check your Rails app for 'config.i18n.fallbacks = true'.
99
101
  If you're using I18n (>= 1.1.0) and Rails (< 5.2.2), this should be
100
102
  'config.i18n.fallbacks = [I18n.default_locale]'.
101
103
  If not, fallbacks will be broken in your app by I18n 1.1.x.
102
104
 
105
+ If you are starting a NEW Rails application, you can ignore this notice.
106
+
103
107
  For more info see:
104
108
  https://github.com/svenfuchs/i18n/releases/tag/v1.1.0
105
109
 
@@ -117,8 +121,9 @@ required_rubygems_version: !ruby/object:Gem::Requirement
117
121
  - !ruby/object:Gem::Version
118
122
  version: 1.3.5
119
123
  requirements: []
120
- rubygems_version: 3.0.3
121
- signing_key:
124
+ rubygems_version: 3.2.3
125
+ signing_key:
122
126
  specification_version: 4
123
127
  summary: New wave Internationalization support for Ruby
124
128
  test_files: []
129
+ ...