i18n 1.7.1 → 1.8.4
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +19 -22
- data/lib/i18n.rb +3 -3
- data/lib/i18n/backend/base.rb +3 -2
- data/lib/i18n/backend/chain.rb +3 -4
- data/lib/i18n/backend/fallbacks.rb +14 -3
- data/lib/i18n/backend/flatten.rb +8 -5
- data/lib/i18n/backend/pluralization.rb +1 -1
- data/lib/i18n/core_ext/hash.rb +17 -5
- data/lib/i18n/interpolate/ruby.rb +1 -1
- data/lib/i18n/locale/fallbacks.rb +7 -5
- data/lib/i18n/locale/tag/parents.rb +8 -6
- data/lib/i18n/locale/tag/simple.rb +1 -1
- data/lib/i18n/tests/localization/procs.rb +6 -5
- data/lib/i18n/tests/procs.rb +5 -0
- data/lib/i18n/version.rb +1 -1
- metadata +9 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 37cc527d32916bffa8e32840086ef15b9f30c8eb08cb8f65bb6a4faf5d00a66e
|
4
|
+
data.tar.gz: f3f6a1a5724fe61ee5e9111bc167708d248fe7e3d700c10c0485fbd4bdf7b17e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 638f732a18f9b9a26a4085320b24a56e3205944cdd1db8d6e751ca106ec848e88224e212fc83ce6324c61d34c471b66d67e3319620f16ae7d4b9ce43d053124e
|
7
|
+
data.tar.gz: ba6baab0a49d1e18b7fff46c0bf8c1f8d23bb74d68cca6ae33b7ddf6484de02ae9de24d7d2ee9cb3e77d2acd67e5b69df7e1e7ae19fc7bb265dd47707354f763
|
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
|
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](
|
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
|
-
*
|
55
|
-
*
|
56
|
-
*
|
57
|
-
*
|
58
|
-
*
|
59
|
-
*
|
60
|
-
*
|
61
|
-
*
|
62
|
-
*
|
63
|
-
*
|
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/
|
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
|
-
|
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
|
|
data/lib/i18n.rb
CHANGED
@@ -223,11 +223,11 @@ module I18n
|
|
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
|
@@ -389,7 +389,7 @@ module I18n
|
|
389
389
|
@@normalized_key_cache[separator][key] ||=
|
390
390
|
case key
|
391
391
|
when Array
|
392
|
-
key.
|
392
|
+
key.flat_map { |k| normalize_key(k, separator) }
|
393
393
|
else
|
394
394
|
keys = key.to_s.split(separator)
|
395
395
|
keys.delete('')
|
data/lib/i18n/backend/base.rb
CHANGED
@@ -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)
|
data/lib/i18n/backend/chain.rb
CHANGED
@@ -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
|
|
@@ -20,7 +20,7 @@ module I18n
|
|
20
20
|
|
21
21
|
# Sets the current fallbacks implementation. Use this to set a different fallbacks implementation.
|
22
22
|
def fallbacks=(fallbacks)
|
23
|
-
@@fallbacks = fallbacks
|
23
|
+
@@fallbacks = fallbacks.is_a?(I18n::Locale::Fallbacks) ? fallbacks : I18n::Locale::Fallbacks.new(fallbacks)
|
24
24
|
end
|
25
25
|
end
|
26
26
|
|
@@ -46,7 +46,10 @@ module I18n
|
|
46
46
|
begin
|
47
47
|
catch(:exception) do
|
48
48
|
result = super(fallback, key, fallback_options)
|
49
|
-
|
49
|
+
unless result.nil?
|
50
|
+
on_fallback(locale, fallback, key, options) if locale != fallback
|
51
|
+
return result
|
52
|
+
end
|
50
53
|
end
|
51
54
|
rescue I18n::InvalidLocale
|
52
55
|
# we do nothing when the locale is invalid, as this is a fallback anyways.
|
@@ -68,7 +71,8 @@ module I18n
|
|
68
71
|
return first_non_symbol_default
|
69
72
|
end
|
70
73
|
|
71
|
-
def exists?(locale, key)
|
74
|
+
def exists?(locale, key, options = EMPTY_HASH)
|
75
|
+
return super unless options.fetch(:fallback, true)
|
72
76
|
I18n.fallbacks[locale].each do |fallback|
|
73
77
|
begin
|
74
78
|
return true if super(fallback, key)
|
@@ -79,6 +83,13 @@ module I18n
|
|
79
83
|
|
80
84
|
false
|
81
85
|
end
|
86
|
+
|
87
|
+
private
|
88
|
+
|
89
|
+
# Overwrite on_fallback to add specified logic when the fallback succeeds.
|
90
|
+
def on_fallback(_original_locale, _fallback_locale, _key, _optoins)
|
91
|
+
nil
|
92
|
+
end
|
82
93
|
end
|
83
94
|
end
|
84
95
|
end
|
data/lib/i18n/backend/flatten.rb
CHANGED
@@ -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]
|
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
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
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
|
32
|
+
return entry unless entry.is_a?(Hash) && count
|
33
33
|
|
34
34
|
pluralizer = pluralizer(locale)
|
35
35
|
if pluralizer.respond_to?(:call)
|
data/lib/i18n/core_ext/hash.rb
CHANGED
@@ -18,12 +18,24 @@ module I18n
|
|
18
18
|
end
|
19
19
|
end
|
20
20
|
|
21
|
-
#
|
22
|
-
|
23
|
-
|
24
|
-
|
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
|
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", :
|
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.
|
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).
|
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
|
91
|
+
end
|
92
92
|
result.push(*defaults) if include_defaults
|
93
|
-
result.uniq
|
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 ||=
|
7
|
-
|
8
|
-
|
9
|
-
|
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]
|
15
|
+
@self_and_parents ||= [self].concat parents
|
14
16
|
end
|
15
17
|
|
16
18
|
def parents
|
17
|
-
@parents ||=
|
19
|
+
@parents ||= parent ? [parent].concat(parent.parents) : []
|
18
20
|
end
|
19
21
|
end
|
20
22
|
end
|
@@ -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, {}
|
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
|
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/) ?
|
data/lib/i18n/tests/procs.rb
CHANGED
@@ -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')
|
data/lib/i18n/version.rb
CHANGED
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.
|
4
|
+
version: 1.8.4
|
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-
|
16
|
+
date: 2020-07-20 00:00:00.000000000 Z
|
17
17
|
dependencies:
|
18
18
|
- !ruby/object:Gem::Dependency
|
19
19
|
name: concurrent-ruby
|
@@ -95,11 +95,15 @@ post_install_message: |2+
|
|
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
|
|
@@ -118,7 +122,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
118
122
|
version: 1.3.5
|
119
123
|
requirements: []
|
120
124
|
rubygems_version: 3.1.2
|
121
|
-
signing_key:
|
125
|
+
signing_key:
|
122
126
|
specification_version: 4
|
123
127
|
summary: New wave Internationalization support for Ruby
|
124
128
|
test_files: []
|
129
|
+
...
|