i18n 1.8.10 → 1.14.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +2 -1
- data/lib/i18n/backend/base.rb +34 -15
- data/lib/i18n/backend/chain.rb +4 -4
- data/lib/i18n/backend/fallbacks.rb +20 -2
- data/lib/i18n/backend/gettext.rb +2 -4
- data/lib/i18n/backend/key_value.rb +4 -6
- data/lib/i18n/backend/lazy_loadable.rb +184 -0
- data/lib/i18n/backend/pluralization.rb +58 -17
- data/lib/i18n/backend/simple.rb +12 -8
- data/lib/i18n/backend/transliterator.rb +24 -24
- data/lib/i18n/backend.rb +2 -1
- data/lib/i18n/config.rb +2 -2
- data/lib/i18n/exceptions.rb +49 -3
- data/lib/i18n/interpolate/ruby.rb +17 -3
- data/lib/i18n/locale/fallbacks.rb +13 -15
- data/lib/i18n/locale/tag/simple.rb +1 -1
- data/lib/i18n/tests/basics.rb +5 -7
- data/lib/i18n/tests/defaults.rb +1 -1
- data/lib/i18n/tests/interpolation.rb +7 -7
- data/lib/i18n/tests/localization/date.rb +9 -4
- data/lib/i18n/tests/localization/date_time.rb +2 -2
- data/lib/i18n/tests/localization/procs.rb +1 -0
- data/lib/i18n/tests/localization/time.rb +2 -2
- data/lib/i18n/tests/lookup.rb +3 -3
- data/lib/i18n/tests/pluralization.rb +1 -1
- data/lib/i18n/tests/procs.rb +7 -1
- data/lib/i18n/utils.rb +55 -0
- data/lib/i18n/version.rb +1 -1
- data/lib/i18n.rb +46 -26
- metadata +6 -5
- data/lib/i18n/core_ext/hash.rb +0 -59
@@ -45,30 +45,30 @@ module I18n
|
|
45
45
|
"Ç"=>"C", "È"=>"E", "É"=>"E", "Ê"=>"E", "Ë"=>"E", "Ì"=>"I", "Í"=>"I",
|
46
46
|
"Î"=>"I", "Ï"=>"I", "Ð"=>"D", "Ñ"=>"N", "Ò"=>"O", "Ó"=>"O", "Ô"=>"O",
|
47
47
|
"Õ"=>"O", "Ö"=>"O", "×"=>"x", "Ø"=>"O", "Ù"=>"U", "Ú"=>"U", "Û"=>"U",
|
48
|
-
"Ü"=>"U", "Ý"=>"Y", "Þ"=>"Th", "ß"=>"ss", "
|
49
|
-
"
|
50
|
-
"
|
51
|
-
"
|
52
|
-
"
|
53
|
-
"
|
54
|
-
"
|
55
|
-
"
|
56
|
-
"
|
57
|
-
"
|
58
|
-
"
|
59
|
-
"
|
60
|
-
"
|
61
|
-
"
|
62
|
-
"
|
63
|
-
"ņ"=>"n", "Ň"=>"N", "ň"=>"n", "ʼn"=>"'n", "Ŋ"=>"NG",
|
64
|
-
"Ō"=>"O", "ō"=>"o", "Ŏ"=>"O", "ŏ"=>"o", "Ő"=>"O", "ő"=>"o",
|
65
|
-
"œ"=>"oe", "Ŕ"=>"R", "ŕ"=>"r", "Ŗ"=>"R", "ŗ"=>"r", "Ř"=>"R",
|
66
|
-
"Ś"=>"S", "ś"=>"s", "Ŝ"=>"S", "ŝ"=>"s", "Ş"=>"S", "ş"=>"s",
|
67
|
-
"š"=>"s", "Ţ"=>"T", "ţ"=>"t", "Ť"=>"T", "ť"=>"t", "Ŧ"=>"T",
|
68
|
-
"Ũ"=>"U", "ũ"=>"u", "Ū"=>"U", "ū"=>"u", "Ŭ"=>"U", "ŭ"=>"u",
|
69
|
-
"ů"=>"u", "Ű"=>"U", "ű"=>"u", "Ų"=>"U", "ų"=>"u", "Ŵ"=>"W",
|
70
|
-
"Ŷ"=>"Y", "ŷ"=>"y", "Ÿ"=>"Y", "Ź"=>"Z", "ź"=>"z", "Ż"=>"Z",
|
71
|
-
"Ž"=>"Z", "ž"=>"z"
|
48
|
+
"Ü"=>"U", "Ý"=>"Y", "Þ"=>"Th", "ß"=>"ss", "ẞ"=>"SS", "à"=>"a",
|
49
|
+
"á"=>"a", "â"=>"a", "ã"=>"a", "ä"=>"a", "å"=>"a", "æ"=>"ae", "ç"=>"c",
|
50
|
+
"è"=>"e", "é"=>"e", "ê"=>"e", "ë"=>"e", "ì"=>"i", "í"=>"i", "î"=>"i",
|
51
|
+
"ï"=>"i", "ð"=>"d", "ñ"=>"n", "ò"=>"o", "ó"=>"o", "ô"=>"o", "õ"=>"o",
|
52
|
+
"ö"=>"o", "ø"=>"o", "ù"=>"u", "ú"=>"u", "û"=>"u", "ü"=>"u", "ý"=>"y",
|
53
|
+
"þ"=>"th", "ÿ"=>"y", "Ā"=>"A", "ā"=>"a", "Ă"=>"A", "ă"=>"a", "Ą"=>"A",
|
54
|
+
"ą"=>"a", "Ć"=>"C", "ć"=>"c", "Ĉ"=>"C", "ĉ"=>"c", "Ċ"=>"C", "ċ"=>"c",
|
55
|
+
"Č"=>"C", "č"=>"c", "Ď"=>"D", "ď"=>"d", "Đ"=>"D", "đ"=>"d", "Ē"=>"E",
|
56
|
+
"ē"=>"e", "Ĕ"=>"E", "ĕ"=>"e", "Ė"=>"E", "ė"=>"e", "Ę"=>"E", "ę"=>"e",
|
57
|
+
"Ě"=>"E", "ě"=>"e", "Ĝ"=>"G", "ĝ"=>"g", "Ğ"=>"G", "ğ"=>"g", "Ġ"=>"G",
|
58
|
+
"ġ"=>"g", "Ģ"=>"G", "ģ"=>"g", "Ĥ"=>"H", "ĥ"=>"h", "Ħ"=>"H", "ħ"=>"h",
|
59
|
+
"Ĩ"=>"I", "ĩ"=>"i", "Ī"=>"I", "ī"=>"i", "Ĭ"=>"I", "ĭ"=>"i", "Į"=>"I",
|
60
|
+
"į"=>"i", "İ"=>"I", "ı"=>"i", "IJ"=>"IJ", "ij"=>"ij", "Ĵ"=>"J", "ĵ"=>"j",
|
61
|
+
"Ķ"=>"K", "ķ"=>"k", "ĸ"=>"k", "Ĺ"=>"L", "ĺ"=>"l", "Ļ"=>"L", "ļ"=>"l",
|
62
|
+
"Ľ"=>"L", "ľ"=>"l", "Ŀ"=>"L", "ŀ"=>"l", "Ł"=>"L", "ł"=>"l", "Ń"=>"N",
|
63
|
+
"ń"=>"n", "Ņ"=>"N", "ņ"=>"n", "Ň"=>"N", "ň"=>"n", "ʼn"=>"'n", "Ŋ"=>"NG",
|
64
|
+
"ŋ"=>"ng", "Ō"=>"O", "ō"=>"o", "Ŏ"=>"O", "ŏ"=>"o", "Ő"=>"O", "ő"=>"o",
|
65
|
+
"Œ"=>"OE", "œ"=>"oe", "Ŕ"=>"R", "ŕ"=>"r", "Ŗ"=>"R", "ŗ"=>"r", "Ř"=>"R",
|
66
|
+
"ř"=>"r", "Ś"=>"S", "ś"=>"s", "Ŝ"=>"S", "ŝ"=>"s", "Ş"=>"S", "ş"=>"s",
|
67
|
+
"Š"=>"S", "š"=>"s", "Ţ"=>"T", "ţ"=>"t", "Ť"=>"T", "ť"=>"t", "Ŧ"=>"T",
|
68
|
+
"ŧ"=>"t", "Ũ"=>"U", "ũ"=>"u", "Ū"=>"U", "ū"=>"u", "Ŭ"=>"U", "ŭ"=>"u",
|
69
|
+
"Ů"=>"U", "ů"=>"u", "Ű"=>"U", "ű"=>"u", "Ų"=>"U", "ų"=>"u", "Ŵ"=>"W",
|
70
|
+
"ŵ"=>"w", "Ŷ"=>"Y", "ŷ"=>"y", "Ÿ"=>"Y", "Ź"=>"Z", "ź"=>"z", "Ż"=>"Z",
|
71
|
+
"ż"=>"z", "Ž"=>"Z", "ž"=>"z"
|
72
72
|
}.freeze
|
73
73
|
|
74
74
|
def initialize(rule = nil)
|
data/lib/i18n/backend.rb
CHANGED
@@ -3,7 +3,6 @@
|
|
3
3
|
module I18n
|
4
4
|
module Backend
|
5
5
|
autoload :Base, 'i18n/backend/base'
|
6
|
-
autoload :InterpolationCompiler, 'i18n/backend/interpolation_compiler'
|
7
6
|
autoload :Cache, 'i18n/backend/cache'
|
8
7
|
autoload :CacheFile, 'i18n/backend/cache_file'
|
9
8
|
autoload :Cascade, 'i18n/backend/cascade'
|
@@ -11,7 +10,9 @@ module I18n
|
|
11
10
|
autoload :Fallbacks, 'i18n/backend/fallbacks'
|
12
11
|
autoload :Flatten, 'i18n/backend/flatten'
|
13
12
|
autoload :Gettext, 'i18n/backend/gettext'
|
13
|
+
autoload :InterpolationCompiler, 'i18n/backend/interpolation_compiler'
|
14
14
|
autoload :KeyValue, 'i18n/backend/key_value'
|
15
|
+
autoload :LazyLoadable, 'i18n/backend/lazy_loadable'
|
15
16
|
autoload :Memoize, 'i18n/backend/memoize'
|
16
17
|
autoload :Metadata, 'i18n/backend/metadata'
|
17
18
|
autoload :Pluralization, 'i18n/backend/pluralization'
|
data/lib/i18n/config.rb
CHANGED
@@ -38,7 +38,7 @@ module I18n
|
|
38
38
|
end
|
39
39
|
|
40
40
|
# Returns an array of locales for which translations are available.
|
41
|
-
# Unless you
|
41
|
+
# Unless you explicitly set these through I18n.available_locales=
|
42
42
|
# the call will be delegated to the backend.
|
43
43
|
def available_locales
|
44
44
|
@@available_locales ||= nil
|
@@ -106,7 +106,7 @@ module I18n
|
|
106
106
|
# if you don't care about arity.
|
107
107
|
#
|
108
108
|
# == Example:
|
109
|
-
# You can
|
109
|
+
# You can suppress raising an exception and return string instead:
|
110
110
|
#
|
111
111
|
# I18n.config.missing_interpolation_argument_handler = Proc.new do |key|
|
112
112
|
# "#{key} is missing"
|
data/lib/i18n/exceptions.rb
CHANGED
@@ -24,7 +24,7 @@ module I18n
|
|
24
24
|
been set is likely to display text from the wrong locale to some users.
|
25
25
|
|
26
26
|
If you have a legitimate reason to access i18n data outside of the user flow, you can do so by passing
|
27
|
-
the desired locale
|
27
|
+
the desired locale explicitly with the `locale` argument, e.g. `I18n.#{method}(..., locale: :en)`
|
28
28
|
MESSAGE
|
29
29
|
end
|
30
30
|
end
|
@@ -47,10 +47,12 @@ module I18n
|
|
47
47
|
|
48
48
|
class MissingTranslation < ArgumentError
|
49
49
|
module Base
|
50
|
+
PERMITTED_KEYS = [:scope, :default].freeze
|
51
|
+
|
50
52
|
attr_reader :locale, :key, :options
|
51
53
|
|
52
54
|
def initialize(locale, key, options = EMPTY_HASH)
|
53
|
-
@key, @locale, @options = key, locale, options.
|
55
|
+
@key, @locale, @options = key, locale, options.slice(*PERMITTED_KEYS)
|
54
56
|
options.each { |k, v| self.options[k] = v.inspect if v.is_a?(Proc) }
|
55
57
|
end
|
56
58
|
|
@@ -61,8 +63,18 @@ module I18n
|
|
61
63
|
end
|
62
64
|
|
63
65
|
def message
|
64
|
-
|
66
|
+
if (default = options[:default]).is_a?(Array) && default.any?
|
67
|
+
other_options = ([key, *default]).map { |k| normalized_option(k).prepend('- ') }.join("\n")
|
68
|
+
"Translation missing. Options considered were:\n#{other_options}"
|
69
|
+
else
|
70
|
+
"Translation missing: #{keys.join('.')}"
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
def normalized_option(key)
|
75
|
+
I18n.normalize_keys(locale, key, options[:scope]).join('.')
|
65
76
|
end
|
77
|
+
|
66
78
|
alias :to_s :message
|
67
79
|
|
68
80
|
def to_exception
|
@@ -108,4 +120,38 @@ module I18n
|
|
108
120
|
super "can not load translations from #{filename}, the file type #{type} is not known"
|
109
121
|
end
|
110
122
|
end
|
123
|
+
|
124
|
+
class UnsupportedMethod < ArgumentError
|
125
|
+
attr_reader :method, :backend_klass, :msg
|
126
|
+
def initialize(method, backend_klass, msg)
|
127
|
+
@method = method
|
128
|
+
@backend_klass = backend_klass
|
129
|
+
@msg = msg
|
130
|
+
super "#{backend_klass} does not support the ##{method} method. #{msg}"
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
134
|
+
class InvalidFilenames < ArgumentError
|
135
|
+
NUMBER_OF_ERRORS_SHOWN = 20
|
136
|
+
def initialize(file_errors)
|
137
|
+
super <<~MSG
|
138
|
+
Found #{file_errors.count} error(s).
|
139
|
+
The first #{[file_errors.count, NUMBER_OF_ERRORS_SHOWN].min} error(s):
|
140
|
+
#{file_errors.map(&:message).first(NUMBER_OF_ERRORS_SHOWN).join("\n")}
|
141
|
+
|
142
|
+
To use the LazyLoadable backend:
|
143
|
+
1. Filenames must start with the locale.
|
144
|
+
2. An underscore must separate the locale with any optional text that follows.
|
145
|
+
3. The file must only contain translation data for the single locale.
|
146
|
+
|
147
|
+
Example:
|
148
|
+
"/config/locales/fr.yml" which contains:
|
149
|
+
```yml
|
150
|
+
fr:
|
151
|
+
dog:
|
152
|
+
chien
|
153
|
+
```
|
154
|
+
MSG
|
155
|
+
end
|
156
|
+
end
|
111
157
|
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
# heavily based on Masao Mutoh's gettext String interpolation extension
|
2
4
|
# http://github.com/mutoh/gettext/blob/f6566738b981fe0952548c421042ad1e0cdfb31e/lib/gettext/core_ext/string.rb
|
3
5
|
|
@@ -5,22 +7,32 @@ module I18n
|
|
5
7
|
DEFAULT_INTERPOLATION_PATTERNS = [
|
6
8
|
/%%/,
|
7
9
|
/%\{([\w|]+)\}/, # matches placeholders like "%{foo} or %{foo|word}"
|
8
|
-
/%<(\w+)>(
|
10
|
+
/%<(\w+)>([^\d]*?\d*\.?\d*[bBdiouxXeEfgGcps])/ # matches placeholders like "%<foo>.d"
|
9
11
|
].freeze
|
10
12
|
INTERPOLATION_PATTERN = Regexp.union(DEFAULT_INTERPOLATION_PATTERNS)
|
11
13
|
deprecate_constant :INTERPOLATION_PATTERN
|
12
14
|
|
15
|
+
INTERPOLATION_PATTERNS_CACHE = Hash.new do |hash, patterns|
|
16
|
+
hash[patterns] = Regexp.union(patterns)
|
17
|
+
end
|
18
|
+
private_constant :INTERPOLATION_PATTERNS_CACHE
|
19
|
+
|
13
20
|
class << self
|
14
21
|
# Return String or raises MissingInterpolationArgument exception.
|
15
22
|
# Missing argument's logic is handled by I18n.config.missing_interpolation_argument_handler.
|
16
23
|
def interpolate(string, values)
|
17
|
-
raise ReservedInterpolationKey.new($1.to_sym, string) if string =~
|
24
|
+
raise ReservedInterpolationKey.new($1.to_sym, string) if string =~ I18n.reserved_keys_pattern
|
18
25
|
raise ArgumentError.new('Interpolation values must be a Hash.') unless values.kind_of?(Hash)
|
19
26
|
interpolate_hash(string, values)
|
20
27
|
end
|
21
28
|
|
22
29
|
def interpolate_hash(string, values)
|
23
|
-
|
30
|
+
pattern = INTERPOLATION_PATTERNS_CACHE[config.interpolation_patterns]
|
31
|
+
interpolated = false
|
32
|
+
|
33
|
+
interpolated_string = string.gsub(pattern) do |match|
|
34
|
+
interpolated = true
|
35
|
+
|
24
36
|
if match == '%%'
|
25
37
|
'%'
|
26
38
|
else
|
@@ -34,6 +46,8 @@ module I18n
|
|
34
46
|
$3 ? sprintf("%#{$3}", value) : value
|
35
47
|
end
|
36
48
|
end
|
49
|
+
|
50
|
+
interpolated ? interpolated_string : string
|
37
51
|
end
|
38
52
|
end
|
39
53
|
end
|
@@ -15,19 +15,12 @@
|
|
15
15
|
# * all parent locales of a given locale (e.g. :es for :"es-MX") first,
|
16
16
|
# * the current default locales and all of their parents second
|
17
17
|
#
|
18
|
-
# The default locales are set to [
|
19
|
-
# set to something else.
|
18
|
+
# The default locales are set to [] by default but can be set to something else.
|
20
19
|
#
|
21
20
|
# One can additionally add any number of additional fallback locales manually.
|
22
21
|
# These will be added before the default locales to the fallback chain. For
|
23
22
|
# example:
|
24
23
|
#
|
25
|
-
# # using the default locale as default fallback locale
|
26
|
-
#
|
27
|
-
# I18n.default_locale = :"en-US"
|
28
|
-
# I18n.fallbacks = I18n::Locale::Fallbacks.new(:"de-AT" => :"de-DE")
|
29
|
-
# I18n.fallbacks[:"de-AT"] # => [:"de-AT", :de, :"de-DE"]
|
30
|
-
#
|
31
24
|
# # using a custom locale as default fallback locale
|
32
25
|
#
|
33
26
|
# I18n.fallbacks = I18n::Locale::Fallbacks.new(:"en-GB", :"de-AT" => :de, :"de-CH" => :de)
|
@@ -46,7 +39,7 @@
|
|
46
39
|
# fallbacks[:"ar-PS"] # => [:"ar-PS", :ar, :"he-IL", :he, :"en-US", :en]
|
47
40
|
# fallbacks[:"ar-EG"] # => [:"ar-EG", :ar, :"en-US", :en]
|
48
41
|
#
|
49
|
-
# # people speaking Sami as spoken in
|
42
|
+
# # people speaking Sami as spoken in Finland also speak Swedish and Finnish as spoken in Finland
|
50
43
|
# fallbacks.map(:sms => [:"se-FI", :"fi-FI"])
|
51
44
|
# fallbacks[:sms] # => [:sms, :"se-FI", :se, :"fi-FI", :fi, :"en-US", :en]
|
52
45
|
|
@@ -71,13 +64,18 @@ module I18n
|
|
71
64
|
super || store(locale, compute(locale))
|
72
65
|
end
|
73
66
|
|
74
|
-
def map(
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
67
|
+
def map(*args, &block)
|
68
|
+
if args.count == 1 && !block_given?
|
69
|
+
mappings = args.first
|
70
|
+
mappings.each do |from, to|
|
71
|
+
from, to = from.to_sym, Array(to)
|
72
|
+
to.each do |_to|
|
73
|
+
@map[from] ||= []
|
74
|
+
@map[from] << _to.to_sym
|
75
|
+
end
|
80
76
|
end
|
77
|
+
else
|
78
|
+
@map.map(*args, &block)
|
81
79
|
end
|
82
80
|
end
|
83
81
|
|
data/lib/i18n/tests/basics.rb
CHANGED
@@ -5,12 +5,11 @@ module I18n
|
|
5
5
|
I18n.available_locales = nil
|
6
6
|
end
|
7
7
|
|
8
|
-
test "available_locales returns the
|
8
|
+
test "available_locales returns the available_locales produced by the backend, by default" do
|
9
9
|
I18n.backend.store_translations('de', :foo => 'bar')
|
10
10
|
I18n.backend.store_translations('en', :foo => 'foo')
|
11
11
|
|
12
|
-
|
13
|
-
assert I18n.available_locales.include?(:en)
|
12
|
+
assert_equal I18n.available_locales, I18n.backend.available_locales
|
14
13
|
end
|
15
14
|
|
16
15
|
test "available_locales can be set to something else independently from the actual locale data" do
|
@@ -24,11 +23,10 @@ module I18n
|
|
24
23
|
assert_equal [:foo, :bar], I18n.available_locales
|
25
24
|
|
26
25
|
I18n.available_locales = nil
|
27
|
-
|
28
|
-
assert I18n.available_locales.include?(:en)
|
26
|
+
assert_equal I18n.available_locales, I18n.backend.available_locales
|
29
27
|
end
|
30
28
|
|
31
|
-
test "available_locales memoizes when set
|
29
|
+
test "available_locales memoizes when set explicitly" do
|
32
30
|
I18n.backend.expects(:available_locales).never
|
33
31
|
I18n.available_locales = [:foo]
|
34
32
|
I18n.backend.store_translations('de', :bar => 'baz')
|
@@ -36,7 +34,7 @@ module I18n
|
|
36
34
|
assert_equal [:foo], I18n.available_locales
|
37
35
|
end
|
38
36
|
|
39
|
-
test "available_locales delegates to the backend when not set
|
37
|
+
test "available_locales delegates to the backend when not set explicitly" do
|
40
38
|
original_available_locales_value = I18n.backend.available_locales
|
41
39
|
I18n.backend.expects(:available_locales).returns(original_available_locales_value).twice
|
42
40
|
assert_equal I18n.backend.available_locales, I18n.available_locales
|
data/lib/i18n/tests/defaults.rb
CHANGED
@@ -37,7 +37,7 @@ module I18n
|
|
37
37
|
end
|
38
38
|
|
39
39
|
test "defaults: given an array of missing keys it raises a MissingTranslationData exception" do
|
40
|
-
|
40
|
+
assert_raises I18n::MissingTranslationData do
|
41
41
|
I18n.t(:does_not_exist, :default => [:does_not_exist_2, :does_not_exist_3], :raise => true)
|
42
42
|
end
|
43
43
|
end
|
@@ -41,7 +41,7 @@ module I18n
|
|
41
41
|
end
|
42
42
|
|
43
43
|
test "interpolation: given values but missing a key it raises I18n::MissingInterpolationArgument" do
|
44
|
-
|
44
|
+
assert_raises(I18n::MissingInterpolationArgument) do
|
45
45
|
interpolate(:default => '%{foo}', :bar => 'bar')
|
46
46
|
end
|
47
47
|
end
|
@@ -77,13 +77,13 @@ module I18n
|
|
77
77
|
|
78
78
|
if Object.const_defined?(:Encoding)
|
79
79
|
test "interpolation: given a euc-jp translation and a utf-8 value it raises Encoding::CompatibilityError" do
|
80
|
-
|
80
|
+
assert_raises(Encoding::CompatibilityError) do
|
81
81
|
interpolate(:default => euc_jp('こんにちは、%{name}さん!'), :name => 'ゆきひろ')
|
82
82
|
end
|
83
83
|
end
|
84
84
|
|
85
85
|
test "interpolation: given a utf-8 translation and a euc-jp value it raises Encoding::CompatibilityError" do
|
86
|
-
|
86
|
+
assert_raises(Encoding::CompatibilityError) do
|
87
87
|
interpolate(:default => 'こんにちは、%{name}さん!', :name => euc_jp('ゆきひろ'))
|
88
88
|
end
|
89
89
|
end
|
@@ -108,10 +108,10 @@ module I18n
|
|
108
108
|
end
|
109
109
|
|
110
110
|
test "interpolation: given a translations containing a reserved key it raises I18n::ReservedInterpolationKey" do
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
111
|
+
assert_raises(I18n::ReservedInterpolationKey) { interpolate(:foo => :bar, :default => '%{exception_handler}') }
|
112
|
+
assert_raises(I18n::ReservedInterpolationKey) { interpolate(:foo => :bar, :default => '%{default}') }
|
113
|
+
assert_raises(I18n::ReservedInterpolationKey) { interpolate(:foo => :bar, :default => '%{separator}') }
|
114
|
+
assert_raises(I18n::ReservedInterpolationKey) { interpolate(:foo => :bar, :default => '%{scope}') }
|
115
115
|
end
|
116
116
|
|
117
117
|
test "interpolation: deep interpolation for default string" do
|
@@ -34,6 +34,11 @@ module I18n
|
|
34
34
|
assert_equal 'Sa', I18n.l(@date, :format => '%a', :locale => :de)
|
35
35
|
end
|
36
36
|
|
37
|
+
test "localize Date: given an meridian indicator format it returns the correct meridian indicator" do
|
38
|
+
assert_equal 'AM', I18n.l(@date, :format => '%p', :locale => :de)
|
39
|
+
assert_equal 'am', I18n.l(@date, :format => '%P', :locale => :de)
|
40
|
+
end
|
41
|
+
|
37
42
|
test "localize Date: given an abbreviated and uppercased day name format it returns the correct abbreviated day name in upcase" do
|
38
43
|
assert_equal 'sa'.upcase, I18n.l(@date, :format => '%^a', :locale => :de)
|
39
44
|
end
|
@@ -59,7 +64,7 @@ module I18n
|
|
59
64
|
end
|
60
65
|
|
61
66
|
test "localize Date: given missing translations it returns the correct error message" do
|
62
|
-
assert_equal '
|
67
|
+
assert_equal 'Translation missing: fr.date.abbr_month_names', I18n.l(@date, :format => '%b', :locale => :fr)
|
63
68
|
end
|
64
69
|
|
65
70
|
test "localize Date: given an unknown format it does not fail" do
|
@@ -78,15 +83,15 @@ module I18n
|
|
78
83
|
end
|
79
84
|
|
80
85
|
test "localize Date: given nil it raises I18n::ArgumentError" do
|
81
|
-
|
86
|
+
assert_raises(I18n::ArgumentError) { I18n.l(nil) }
|
82
87
|
end
|
83
88
|
|
84
89
|
test "localize Date: given a plain Object it raises I18n::ArgumentError" do
|
85
|
-
|
90
|
+
assert_raises(I18n::ArgumentError) { I18n.l(Object.new) }
|
86
91
|
end
|
87
92
|
|
88
93
|
test "localize Date: given a format is missing it raises I18n::MissingTranslationData" do
|
89
|
-
|
94
|
+
assert_raises(I18n::MissingTranslationData) { I18n.l(@date, :format => :missing) }
|
90
95
|
end
|
91
96
|
|
92
97
|
test "localize Date: it does not alter the format string" do
|
@@ -60,7 +60,7 @@ module I18n
|
|
60
60
|
end
|
61
61
|
|
62
62
|
test "localize DateTime: given missing translations it returns the correct error message" do
|
63
|
-
assert_equal '
|
63
|
+
assert_equal 'Translation missing: fr.date.abbr_month_names', I18n.l(@datetime, :format => '%b', :locale => :fr)
|
64
64
|
end
|
65
65
|
|
66
66
|
test "localize DateTime: given a meridian indicator format it returns the correct meridian indicator" do
|
@@ -78,7 +78,7 @@ module I18n
|
|
78
78
|
end
|
79
79
|
|
80
80
|
test "localize DateTime: given a format is missing it raises I18n::MissingTranslationData" do
|
81
|
-
|
81
|
+
assert_raises(I18n::MissingTranslationData) { I18n.l(@datetime, :format => :missing) }
|
82
82
|
end
|
83
83
|
|
84
84
|
protected
|
@@ -61,7 +61,7 @@ module I18n
|
|
61
61
|
end
|
62
62
|
|
63
63
|
test "localize Time: given missing translations it returns the correct error message" do
|
64
|
-
assert_equal '
|
64
|
+
assert_equal 'Translation missing: fr.date.abbr_month_names', I18n.l(@time, :format => '%b', :locale => :fr)
|
65
65
|
end
|
66
66
|
|
67
67
|
test "localize Time: given a meridian indicator format it returns the correct meridian indicator" do
|
@@ -79,7 +79,7 @@ module I18n
|
|
79
79
|
end
|
80
80
|
|
81
81
|
test "localize Time: given a format is missing it raises I18n::MissingTranslationData" do
|
82
|
-
|
82
|
+
assert_raises(I18n::MissingTranslationData) { I18n.l(@time, :format => :missing) }
|
83
83
|
end
|
84
84
|
|
85
85
|
protected
|
data/lib/i18n/tests/lookup.rb
CHANGED
@@ -30,11 +30,11 @@ module I18n
|
|
30
30
|
end
|
31
31
|
|
32
32
|
test "lookup: given a missing key, no default and no raise option it returns an error message" do
|
33
|
-
assert_equal "
|
33
|
+
assert_equal "Translation missing: en.missing", I18n.t(:missing)
|
34
34
|
end
|
35
35
|
|
36
36
|
test "lookup: given a missing key, no default and the raise option it raises MissingTranslationData" do
|
37
|
-
|
37
|
+
assert_raises(I18n::MissingTranslationData) { I18n.t(:missing, :raise => true) }
|
38
38
|
end
|
39
39
|
|
40
40
|
test "lookup: does not raise an exception if no translation data is present for the given locale" do
|
@@ -61,7 +61,7 @@ module I18n
|
|
61
61
|
# In fact it probably *should* fail but Rails currently relies on using the default locale instead.
|
62
62
|
# So we'll stick to this for now until we get it fixed in Rails.
|
63
63
|
test "lookup: given nil as a locale it does not raise but use the default locale" do
|
64
|
-
#
|
64
|
+
# assert_raises(I18n::InvalidLocale) { I18n.t(:bar, :locale => nil) }
|
65
65
|
assert_nothing_raised { I18n.t(:bar, :locale => nil) }
|
66
66
|
end
|
67
67
|
|
@@ -28,7 +28,7 @@ module I18n
|
|
28
28
|
end
|
29
29
|
|
30
30
|
test "pluralization: given incomplete pluralization data it raises I18n::InvalidPluralizationData" do
|
31
|
-
|
31
|
+
assert_raises(I18n::InvalidPluralizationData) { I18n.t(:default => { :one => 'bar' }, :count => 2) }
|
32
32
|
end
|
33
33
|
end
|
34
34
|
end
|
data/lib/i18n/tests/procs.rb
CHANGED
@@ -53,7 +53,13 @@ module I18n
|
|
53
53
|
|
54
54
|
|
55
55
|
def self.filter_args(*args)
|
56
|
-
args.map
|
56
|
+
args.map do |arg|
|
57
|
+
if arg.is_a?(Hash)
|
58
|
+
arg.delete(:fallback_in_progress)
|
59
|
+
arg.delete(:fallback_original_locale)
|
60
|
+
end
|
61
|
+
arg
|
62
|
+
end.inspect
|
57
63
|
end
|
58
64
|
end
|
59
65
|
end
|
data/lib/i18n/utils.rb
ADDED
@@ -0,0 +1,55 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module I18n
|
4
|
+
module Utils
|
5
|
+
class << self
|
6
|
+
if Hash.method_defined?(:except)
|
7
|
+
def except(hash, *keys)
|
8
|
+
hash.except(*keys)
|
9
|
+
end
|
10
|
+
else
|
11
|
+
def except(hash, *keys)
|
12
|
+
hash = hash.dup
|
13
|
+
keys.each { |k| hash.delete(k) }
|
14
|
+
hash
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def deep_merge(hash, other_hash, &block)
|
19
|
+
deep_merge!(hash.dup, other_hash, &block)
|
20
|
+
end
|
21
|
+
|
22
|
+
def deep_merge!(hash, other_hash, &block)
|
23
|
+
hash.merge!(other_hash) do |key, this_val, other_val|
|
24
|
+
if this_val.is_a?(Hash) && other_val.is_a?(Hash)
|
25
|
+
deep_merge(this_val, other_val, &block)
|
26
|
+
elsif block_given?
|
27
|
+
yield key, this_val, other_val
|
28
|
+
else
|
29
|
+
other_val
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def deep_symbolize_keys(hash)
|
35
|
+
hash.each_with_object({}) do |(key, value), result|
|
36
|
+
result[key.respond_to?(:to_sym) ? key.to_sym : key] = deep_symbolize_keys_in_object(value)
|
37
|
+
result
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
private
|
42
|
+
|
43
|
+
def deep_symbolize_keys_in_object(value)
|
44
|
+
case value
|
45
|
+
when Hash
|
46
|
+
deep_symbolize_keys(value)
|
47
|
+
when Array
|
48
|
+
value.map { |e| deep_symbolize_keys_in_object(e) }
|
49
|
+
else
|
50
|
+
value
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
data/lib/i18n/version.rb
CHANGED