New Upstream Release - ruby-i18n
Ready changes
Summary
Merged new upstream version: 1.14.1 (was: 1.12.0).
Resulting package
Built on 2023-06-09T05:40 (took 5m27s)
The resulting binary packages can be installed (if you have the apt repository enabled) by running one of:
apt install -t fresh-releases ruby-i18n
Lintian Result
Diff
diff --git a/.github/funding.yml b/.github/funding.yml
new file mode 100644
index 0000000..2dda82a
--- /dev/null
+++ b/.github/funding.yml
@@ -0,0 +1 @@
+github: [radar]
diff --git a/.github/workflows/ruby.yml b/.github/workflows/ruby.yml
index 81c1295..3e33190 100644
--- a/.github/workflows/ruby.yml
+++ b/.github/workflows/ruby.yml
@@ -17,7 +17,7 @@ jobs:
strategy:
fail-fast: false
matrix:
- ruby_version: [3.1, "3.0", 2.7, 2.6, jruby]
+ ruby_version: [3.2, 3.1, "3.0", 2.7, 2.6, jruby]
gemfile:
- Gemfile
- gemfiles/Gemfile.rails-5.2.x
@@ -26,6 +26,10 @@ jobs:
- gemfiles/Gemfile.rails-7.0.x
- gemfiles/Gemfile.rails-main
exclude:
+ # Ruby 3.2 is not supported by Rails 5.2.x
+ - ruby_version: 3.2
+ gemfile: gemfiles/Gemfile.rails-5.2.x
+
# Ruby 3.1 is not supported by Rails 5.2.x
- ruby_version: 3.1
gemfile: gemfiles/Gemfile.rails-5.2.x
@@ -42,6 +46,10 @@ jobs:
- ruby_version: 2.6
gemfile: gemfiles/Gemfile.rails-7.0.x
+ # JRuby 9.4.2.0 (3.1.0) is not supported by Rails 5.2.x
+ - ruby_version: jruby
+ gemfile: gemfiles/Gemfile.rails-5.2.x
+
# JRuby is not supported by Rails 7.0.x
- ruby_version: jruby
gemfile: gemfiles/Gemfile.rails-7.0.x
@@ -53,7 +61,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- - uses: actions/checkout@v2
+ - uses: actions/checkout@v3
- name: Set up Ruby
uses: ruby/setup-ruby@v1
with:
diff --git a/README.md b/README.md
index 318e05d..1d174dd 100644
--- a/README.md
+++ b/README.md
@@ -26,7 +26,7 @@ gem 'i18n'
Then configure I18n with some translations, and a default locale:
```ruby
-I18n.load_path << Dir[File.expand_path("config/locales") + "/*.yml"]
+I18n.load_path += Dir[File.expand_path("config/locales") + "/*.yml"]
I18n.default_locale = :en # (note that `en` is already the default!)
```
diff --git a/debian/changelog b/debian/changelog
index 95bae5e..aac06d1 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,3 +1,10 @@
+ruby-i18n (1.14.1-1) UNRELEASED; urgency=low
+
+ * New upstream release.
+ * New upstream release.
+
+ -- Debian Janitor <janitor@jelmer.uk> Fri, 09 Jun 2023 05:35:48 -0000
+
ruby-i18n (1.10.0-2) unstable; urgency=medium
* Team upload.
diff --git a/debian/patches/0001-disable-bundler-on-build-time-do-not-install-stuff-a.patch b/debian/patches/0001-disable-bundler-on-build-time-do-not-install-stuff-a.patch
index 72de208..2a6c70b 100644
--- a/debian/patches/0001-disable-bundler-on-build-time-do-not-install-stuff-a.patch
+++ b/debian/patches/0001-disable-bundler-on-build-time-do-not-install-stuff-a.patch
@@ -7,8 +7,10 @@ Forwarded: not-needed
test/test_helper.rb | 1 -
1 file changed, 1 deletion(-)
---- a/test/test_helper.rb
-+++ b/test/test_helper.rb
+Index: ruby-i18n.git/test/test_helper.rb
+===================================================================
+--- ruby-i18n.git.orig/test/test_helper.rb
++++ ruby-i18n.git/test/test_helper.rb
@@ -1,5 +1,4 @@
require 'minitest/autorun'
-require 'bundler/setup'
diff --git a/debian/patches/0002-gemspec-prepend-local-directory-to-the-LOAD_PATH.patch b/debian/patches/0002-gemspec-prepend-local-directory-to-the-LOAD_PATH.patch
index 53da29c..709971c 100644
--- a/debian/patches/0002-gemspec-prepend-local-directory-to-the-LOAD_PATH.patch
+++ b/debian/patches/0002-gemspec-prepend-local-directory-to-the-LOAD_PATH.patch
@@ -6,10 +6,10 @@ Subject: gemspec: prepend local directory to the $LOAD_PATH
i18n.gemspec | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
-diff --git a/i18n.gemspec b/i18n.gemspec
-index 0e67209..f4211e9 100644
---- a/i18n.gemspec
-+++ b/i18n.gemspec
+Index: ruby-i18n.git/i18n.gemspec
+===================================================================
+--- ruby-i18n.git.orig/i18n.gemspec
++++ ruby-i18n.git/i18n.gemspec
@@ -1,6 +1,6 @@
# encoding: utf-8
diff --git a/debian/patches/0003-test_helper-load-gem-i18n-before-requiring-i18n.patch b/debian/patches/0003-test_helper-load-gem-i18n-before-requiring-i18n.patch
index 41d4393..599a770 100644
--- a/debian/patches/0003-test_helper-load-gem-i18n-before-requiring-i18n.patch
+++ b/debian/patches/0003-test_helper-load-gem-i18n-before-requiring-i18n.patch
@@ -10,8 +10,10 @@ in the require.
test/test_helper.rb | 1 +
1 file changed, 1 insertion(+)
---- a/test/test_helper.rb
-+++ b/test/test_helper.rb
+Index: ruby-i18n.git/test/test_helper.rb
+===================================================================
+--- ruby-i18n.git.orig/test/test_helper.rb
++++ ruby-i18n.git/test/test_helper.rb
@@ -1,4 +1,5 @@
require 'minitest/autorun'
+gem "i18n"
diff --git a/lib/i18n.rb b/lib/i18n.rb
index e197e2b..d336970 100644
--- a/lib/i18n.rb
+++ b/lib/i18n.rb
@@ -214,18 +214,12 @@ module I18n
backend = config.backend
- result = catch(:exception) do
- if key.is_a?(Array)
- key.map { |k| backend.translate(locale, k, options) }
- else
- backend.translate(locale, key, options)
+ if key.is_a?(Array)
+ key.map do |k|
+ translate_key(k, throw, raise, locale, backend, options)
end
- end
-
- if result.is_a?(MissingTranslation)
- handle_exception((throw && :throw || raise && :raise), result, locale, key, options)
else
- result
+ translate_key(key, throw, raise, locale, backend, options)
end
end
alias :t :translate
@@ -364,6 +358,18 @@ module I18n
private
+ def translate_key(key, throw, raise, locale, backend, options)
+ result = catch(:exception) do
+ backend.translate(locale, key, options)
+ end
+
+ if result.is_a?(MissingTranslation)
+ handle_exception((throw && :throw || raise && :raise), result, locale, key, options)
+ else
+ result
+ end
+ end
+
# Any exceptions thrown in translate will be sent to the @@exception_handler
# which can be a Symbol, a Proc or any other Object unless they're forced to
# be raised or thrown (MissingTranslation).
diff --git a/lib/i18n/backend/base.rb b/lib/i18n/backend/base.rb
index 4cbcc3c..5775675 100644
--- a/lib/i18n/backend/base.rb
+++ b/lib/i18n/backend/base.rb
@@ -54,7 +54,7 @@ module I18n
end
deep_interpolation = options[:deep_interpolation]
- values = Utils.except(options, *RESERVED_KEYS)
+ values = Utils.except(options, *RESERVED_KEYS) unless options.empty?
if values
entry = if deep_interpolation
deep_interpolate(locale, entry, values)
@@ -66,7 +66,7 @@ module I18n
end
def exists?(locale, key, options = EMPTY_HASH)
- lookup(locale, key) != nil
+ lookup(locale, key, options[:scope]) != nil
end
# Acts the same as +strftime+, but uses a localized version of the
@@ -123,7 +123,12 @@ module I18n
# first translation that can be resolved. Otherwise it tries to resolve
# the translation directly.
def default(locale, object, subject, options = EMPTY_HASH)
- options = options.reject { |key, value| key == :default }
+ if options.size == 1 && options.has_key?(:default)
+ options = {}
+ else
+ options = Utils.except(options, :default)
+ end
+
case subject
when Array
subject.each do |item|
@@ -166,7 +171,7 @@ module I18n
# Other backends can implement more flexible or complex pluralization rules.
def pluralize(locale, entry, count)
entry = entry.reject { |k, _v| k == :attributes } if entry.is_a?(Hash)
- return entry unless entry.is_a?(Hash) && count && entry.values.none? { |v| v.is_a?(Hash) }
+ return entry unless entry.is_a?(Hash) && count
key = pluralization_key(entry, count)
raise InvalidPluralizationData.new(entry, count, key) unless entry.has_key?(key)
@@ -282,8 +287,8 @@ module I18n
when '%^b' then I18n.t!(:"date.abbr_month_names", :locale => locale, :format => format)[object.mon].upcase
when '%B' then I18n.t!(:"date.month_names", :locale => locale, :format => format)[object.mon]
when '%^B' then I18n.t!(:"date.month_names", :locale => locale, :format => format)[object.mon].upcase
- when '%p' then I18n.t!(:"time.#{object.hour < 12 ? :am : :pm}", :locale => locale, :format => format).upcase if object.respond_to? :hour
- when '%P' then I18n.t!(:"time.#{object.hour < 12 ? :am : :pm}", :locale => locale, :format => format).downcase if object.respond_to? :hour
+ when '%p' then I18n.t!(:"time.#{(object.respond_to?(:hour) ? object.hour : 0) < 12 ? :am : :pm}", :locale => locale, :format => format).upcase
+ when '%P' then I18n.t!(:"time.#{(object.respond_to?(:hour) ? object.hour : 0) < 12 ? :am : :pm}", :locale => locale, :format => format).downcase
end
end
rescue MissingTranslationData => e
diff --git a/lib/i18n/backend/chain.rb b/lib/i18n/backend/chain.rb
index 525dd2d..e081a91 100644
--- a/lib/i18n/backend/chain.rb
+++ b/lib/i18n/backend/chain.rb
@@ -16,6 +16,8 @@ module I18n
#
# The implementation assumes that all backends added to the Chain implement
# a lookup method with the same API as Simple backend does.
+ #
+ # Fallback translations using the :default option are only used by the last backend of a chain.
class Chain
module Implementation
include Base
diff --git a/lib/i18n/backend/fallbacks.rb b/lib/i18n/backend/fallbacks.rb
index 7afbfe3..6d4d6e1 100644
--- a/lib/i18n/backend/fallbacks.rb
+++ b/lib/i18n/backend/fallbacks.rb
@@ -107,7 +107,7 @@ module I18n
private
# Overwrite on_fallback to add specified logic when the fallback succeeds.
- def on_fallback(_original_locale, _fallback_locale, _key, _optoins)
+ def on_fallback(_original_locale, _fallback_locale, _key, _options)
nil
end
end
diff --git a/lib/i18n/backend/lazy_loadable.rb b/lib/i18n/backend/lazy_loadable.rb
index 60f21fa..575b32b 100644
--- a/lib/i18n/backend/lazy_loadable.rb
+++ b/lib/i18n/backend/lazy_loadable.rb
@@ -98,7 +98,7 @@ module I18n
# Parse the load path and extract all locales.
def available_locales
if lazy_load?
- I18n.load_path.map { |path| LocaleExtractor.locale_from_path(path) }
+ I18n.load_path.map { |path| LocaleExtractor.locale_from_path(path) }.uniq
else
super
end
diff --git a/lib/i18n/backend/pluralization.rb b/lib/i18n/backend/pluralization.rb
index b602657..1d3277b 100644
--- a/lib/i18n/backend/pluralization.rb
+++ b/lib/i18n/backend/pluralization.rb
@@ -16,26 +16,57 @@ module I18n
module Pluralization
# Overwrites the Base backend translate method so that it will check the
# translation meta data space (:i18n) for a locale specific pluralization
- # rule and use it to pluralize the given entry. I.e. the library expects
+ # rule and use it to pluralize the given entry. I.e., the library expects
# pluralization rules to be stored at I18n.t(:'i18n.plural.rule')
#
# Pluralization rules are expected to respond to #call(count) and
- # return a pluralization key. Valid keys depend on the translation data
- # hash (entry) but it is generally recommended to follow CLDR's style,
- # i.e., return one of the keys :zero, :one, :few, :many, :other.
+ # return a pluralization key. Valid keys depend on the pluralization
+ # rules for the locale, as defined in the CLDR.
+ # As of v41, 6 locale-specific plural categories are defined:
+ # :few, :many, :one, :other, :two, :zero
#
- # The :zero key is always picked directly when count equals 0 AND the
- # translation data has the key :zero. This way translators are free to
- # either pick a special :zero translation even for languages where the
- # pluralizer does not return a :zero key.
+ # n.b., The :one plural category does not imply the number 1.
+ # Instead, :one is a category for any number that behaves like 1 in
+ # that locale. For example, in some locales, :one is used for numbers
+ # that end in "1" (like 1, 21, 151) but that don't end in
+ # 11 (like 11, 111, 10311).
+ # Similar notes apply to the :two, and :zero plural categories.
+ #
+ # If you want to have different strings for the categories of count == 0
+ # (e.g. "I don't have any cars") or count == 1 (e.g. "I have a single car")
+ # use the explicit `"0"` and `"1"` keys.
+ # https://unicode-org.github.io/cldr/ldml/tr35-numbers.html#Explicit_0_1_rules
def pluralize(locale, entry, count)
return entry unless entry.is_a?(Hash) && count
pluralizer = pluralizer(locale)
if pluralizer.respond_to?(:call)
- key = count == 0 && entry.has_key?(:zero) ? :zero : pluralizer.call(count)
- raise InvalidPluralizationData.new(entry, count, key) unless entry.has_key?(key)
- entry[key]
+ # Deprecation: The use of the `zero` key in this way is incorrect.
+ # Users that want a different string for the case of `count == 0` should use the explicit "0" key instead.
+ # We keep this incorrect behaviour for now for backwards compatibility until we can remove it.
+ # Ref: https://github.com/ruby-i18n/i18n/issues/629
+ return entry[:zero] if count == 0 && entry.has_key?(:zero)
+
+ # "0" and "1" are special cases
+ # https://unicode-org.github.io/cldr/ldml/tr35-numbers.html#Explicit_0_1_rules
+ if count == 0 || count == 1
+ value = entry[symbolic_count(count)]
+ return value if value
+ end
+
+ # Lateral Inheritance of "count" attribute (http://www.unicode.org/reports/tr35/#Lateral_Inheritance):
+ # > If there is no value for a path, and that path has a [@count="x"] attribute and value, then:
+ # > 1. If "x" is numeric, the path falls back to the path with [@count=«the plural rules category for x for that locale»], within that the same locale.
+ # > 2. If "x" is anything but "other", it falls back to a path [@count="other"], within that the same locale.
+ # > 3. If "x" is "other", it falls back to the path that is completely missing the count item, within that the same locale.
+ # Note: We don't yet implement #3 above, since we haven't decided how lateral inheritance attributes should be represented.
+ plural_rule_category = pluralizer.call(count)
+
+ value = if entry.has_key?(plural_rule_category) || entry.has_key?(:other)
+ entry[plural_rule_category] || entry[:other]
+ else
+ raise InvalidPluralizationData.new(entry, count, plural_rule_category)
+ end
else
super
end
@@ -43,13 +74,23 @@ module I18n
protected
- def pluralizers
- @pluralizers ||= {}
- end
+ def pluralizers
+ @pluralizers ||= {}
+ end
- def pluralizer(locale)
- pluralizers[locale] ||= I18n.t(:'i18n.plural.rule', :locale => locale, :resolve => false)
- end
+ def pluralizer(locale)
+ pluralizers[locale] ||= I18n.t(:'i18n.plural.rule', :locale => locale, :resolve => false)
+ end
+
+ private
+
+ # Normalizes categories of 0.0 and 1.0
+ # and returns the symbolic version
+ def symbolic_count(count)
+ count = 0 if count == 0
+ count = 1 if count == 1
+ count.to_s.to_sym
+ end
end
end
end
diff --git a/lib/i18n/backend/simple.rb b/lib/i18n/backend/simple.rb
index 0c49de8..7caa7dd 100644
--- a/lib/i18n/backend/simple.rb
+++ b/lib/i18n/backend/simple.rb
@@ -21,6 +21,9 @@ module I18n
class Simple
module Implementation
include Base
+
+ # Mutex to ensure that concurrent translations loading will be thread-safe
+ MUTEX = Mutex.new
def initialized?
@initialized ||= false
@@ -68,7 +71,11 @@ module I18n
# call `init_translations`
init_translations if do_init && !initialized?
- @translations ||= Concurrent::Hash.new { |h, k| h[k] = Concurrent::Hash.new }
+ @translations ||= Concurrent::Hash.new do |h, k|
+ MUTEX.synchronize do
+ h[k] = Concurrent::Hash.new
+ end
+ end
end
protected
@@ -94,7 +101,7 @@ module I18n
return nil unless result.has_key?(_key)
end
result = result[_key]
- result = resolve_entry(locale, _key, result, options.merge(:scope => nil)) if result.is_a?(Symbol)
+ result = resolve_entry(locale, _key, result, Utils.except(options.merge(:scope => nil), :count)) if result.is_a?(Symbol)
result
end
end
diff --git a/lib/i18n/backend/transliterator.rb b/lib/i18n/backend/transliterator.rb
index bb704ab..70c0df3 100644
--- a/lib/i18n/backend/transliterator.rb
+++ b/lib/i18n/backend/transliterator.rb
@@ -45,30 +45,30 @@ module I18n
"Ç"=>"C", "È"=>"E", "É"=>"E", "Ê"=>"E", "Ë"=>"E", "Ì"=>"I", "Í"=>"I",
"Î"=>"I", "Ï"=>"I", "Ð"=>"D", "Ñ"=>"N", "Ò"=>"O", "Ó"=>"O", "Ô"=>"O",
"Õ"=>"O", "Ö"=>"O", "×"=>"x", "Ø"=>"O", "Ù"=>"U", "Ú"=>"U", "Û"=>"U",
- "Ü"=>"U", "Ý"=>"Y", "Þ"=>"Th", "ß"=>"ss", "à"=>"a", "á"=>"a", "â"=>"a",
- "ã"=>"a", "ä"=>"a", "å"=>"a", "æ"=>"ae", "ç"=>"c", "è"=>"e", "é"=>"e",
- "ê"=>"e", "ë"=>"e", "ì"=>"i", "í"=>"i", "î"=>"i", "ï"=>"i", "ð"=>"d",
- "ñ"=>"n", "ò"=>"o", "ó"=>"o", "ô"=>"o", "õ"=>"o", "ö"=>"o", "ø"=>"o",
- "ù"=>"u", "ú"=>"u", "û"=>"u", "ü"=>"u", "ý"=>"y", "þ"=>"th", "ÿ"=>"y",
- "Ā"=>"A", "ā"=>"a", "Ă"=>"A", "ă"=>"a", "Ą"=>"A", "ą"=>"a", "Ć"=>"C",
- "ć"=>"c", "Ĉ"=>"C", "ĉ"=>"c", "Ċ"=>"C", "ċ"=>"c", "Č"=>"C", "č"=>"c",
- "Ď"=>"D", "ď"=>"d", "Đ"=>"D", "đ"=>"d", "Ē"=>"E", "ē"=>"e", "Ĕ"=>"E",
- "ĕ"=>"e", "Ė"=>"E", "ė"=>"e", "Ę"=>"E", "ę"=>"e", "Ě"=>"E", "ě"=>"e",
- "Ĝ"=>"G", "ĝ"=>"g", "Ğ"=>"G", "ğ"=>"g", "Ġ"=>"G", "ġ"=>"g", "Ģ"=>"G",
- "ģ"=>"g", "Ĥ"=>"H", "ĥ"=>"h", "Ħ"=>"H", "ħ"=>"h", "Ĩ"=>"I", "ĩ"=>"i",
- "Ī"=>"I", "ī"=>"i", "Ĭ"=>"I", "ĭ"=>"i", "Į"=>"I", "į"=>"i", "İ"=>"I",
- "ı"=>"i", "IJ"=>"IJ", "ij"=>"ij", "Ĵ"=>"J", "ĵ"=>"j", "Ķ"=>"K", "ķ"=>"k",
- "ĸ"=>"k", "Ĺ"=>"L", "ĺ"=>"l", "Ļ"=>"L", "ļ"=>"l", "Ľ"=>"L", "ľ"=>"l",
- "Ŀ"=>"L", "ŀ"=>"l", "Ł"=>"L", "ł"=>"l", "Ń"=>"N", "ń"=>"n", "Ņ"=>"N",
- "ņ"=>"n", "Ň"=>"N", "ň"=>"n", "ʼn"=>"'n", "Ŋ"=>"NG", "ŋ"=>"ng",
- "Ō"=>"O", "ō"=>"o", "Ŏ"=>"O", "ŏ"=>"o", "Ő"=>"O", "ő"=>"o", "Œ"=>"OE",
- "œ"=>"oe", "Ŕ"=>"R", "ŕ"=>"r", "Ŗ"=>"R", "ŗ"=>"r", "Ř"=>"R", "ř"=>"r",
- "Ś"=>"S", "ś"=>"s", "Ŝ"=>"S", "ŝ"=>"s", "Ş"=>"S", "ş"=>"s", "Š"=>"S",
- "š"=>"s", "Ţ"=>"T", "ţ"=>"t", "Ť"=>"T", "ť"=>"t", "Ŧ"=>"T", "ŧ"=>"t",
- "Ũ"=>"U", "ũ"=>"u", "Ū"=>"U", "ū"=>"u", "Ŭ"=>"U", "ŭ"=>"u", "Ů"=>"U",
- "ů"=>"u", "Ű"=>"U", "ű"=>"u", "Ų"=>"U", "ų"=>"u", "Ŵ"=>"W", "ŵ"=>"w",
- "Ŷ"=>"Y", "ŷ"=>"y", "Ÿ"=>"Y", "Ź"=>"Z", "ź"=>"z", "Ż"=>"Z", "ż"=>"z",
- "Ž"=>"Z", "ž"=>"z"
+ "Ü"=>"U", "Ý"=>"Y", "Þ"=>"Th", "ß"=>"ss", "ẞ"=>"SS", "à"=>"a",
+ "á"=>"a", "â"=>"a", "ã"=>"a", "ä"=>"a", "å"=>"a", "æ"=>"ae", "ç"=>"c",
+ "è"=>"e", "é"=>"e", "ê"=>"e", "ë"=>"e", "ì"=>"i", "í"=>"i", "î"=>"i",
+ "ï"=>"i", "ð"=>"d", "ñ"=>"n", "ò"=>"o", "ó"=>"o", "ô"=>"o", "õ"=>"o",
+ "ö"=>"o", "ø"=>"o", "ù"=>"u", "ú"=>"u", "û"=>"u", "ü"=>"u", "ý"=>"y",
+ "þ"=>"th", "ÿ"=>"y", "Ā"=>"A", "ā"=>"a", "Ă"=>"A", "ă"=>"a", "Ą"=>"A",
+ "ą"=>"a", "Ć"=>"C", "ć"=>"c", "Ĉ"=>"C", "ĉ"=>"c", "Ċ"=>"C", "ċ"=>"c",
+ "Č"=>"C", "č"=>"c", "Ď"=>"D", "ď"=>"d", "Đ"=>"D", "đ"=>"d", "Ē"=>"E",
+ "ē"=>"e", "Ĕ"=>"E", "ĕ"=>"e", "Ė"=>"E", "ė"=>"e", "Ę"=>"E", "ę"=>"e",
+ "Ě"=>"E", "ě"=>"e", "Ĝ"=>"G", "ĝ"=>"g", "Ğ"=>"G", "ğ"=>"g", "Ġ"=>"G",
+ "ġ"=>"g", "Ģ"=>"G", "ģ"=>"g", "Ĥ"=>"H", "ĥ"=>"h", "Ħ"=>"H", "ħ"=>"h",
+ "Ĩ"=>"I", "ĩ"=>"i", "Ī"=>"I", "ī"=>"i", "Ĭ"=>"I", "ĭ"=>"i", "Į"=>"I",
+ "į"=>"i", "İ"=>"I", "ı"=>"i", "IJ"=>"IJ", "ij"=>"ij", "Ĵ"=>"J", "ĵ"=>"j",
+ "Ķ"=>"K", "ķ"=>"k", "ĸ"=>"k", "Ĺ"=>"L", "ĺ"=>"l", "Ļ"=>"L", "ļ"=>"l",
+ "Ľ"=>"L", "ľ"=>"l", "Ŀ"=>"L", "ŀ"=>"l", "Ł"=>"L", "ł"=>"l", "Ń"=>"N",
+ "ń"=>"n", "Ņ"=>"N", "ņ"=>"n", "Ň"=>"N", "ň"=>"n", "ʼn"=>"'n", "Ŋ"=>"NG",
+ "ŋ"=>"ng", "Ō"=>"O", "ō"=>"o", "Ŏ"=>"O", "ŏ"=>"o", "Ő"=>"O", "ő"=>"o",
+ "Œ"=>"OE", "œ"=>"oe", "Ŕ"=>"R", "ŕ"=>"r", "Ŗ"=>"R", "ŗ"=>"r", "Ř"=>"R",
+ "ř"=>"r", "Ś"=>"S", "ś"=>"s", "Ŝ"=>"S", "ŝ"=>"s", "Ş"=>"S", "ş"=>"s",
+ "Š"=>"S", "š"=>"s", "Ţ"=>"T", "ţ"=>"t", "Ť"=>"T", "ť"=>"t", "Ŧ"=>"T",
+ "ŧ"=>"t", "Ũ"=>"U", "ũ"=>"u", "Ū"=>"U", "ū"=>"u", "Ŭ"=>"U", "ŭ"=>"u",
+ "Ů"=>"U", "ů"=>"u", "Ű"=>"U", "ű"=>"u", "Ų"=>"U", "ų"=>"u", "Ŵ"=>"W",
+ "ŵ"=>"w", "Ŷ"=>"Y", "ŷ"=>"y", "Ÿ"=>"Y", "Ź"=>"Z", "ź"=>"z", "Ż"=>"Z",
+ "ż"=>"z", "Ž"=>"Z", "ž"=>"z"
}.freeze
def initialize(rule = nil)
diff --git a/lib/i18n/config.rb b/lib/i18n/config.rb
index ea3dd1e..9878e02 100644
--- a/lib/i18n/config.rb
+++ b/lib/i18n/config.rb
@@ -38,7 +38,7 @@ module I18n
end
# Returns an array of locales for which translations are available.
- # Unless you explicitely set these through I18n.available_locales=
+ # Unless you explicitly set these through I18n.available_locales=
# the call will be delegated to the backend.
def available_locales
@@available_locales ||= nil
@@ -106,7 +106,7 @@ module I18n
# if you don't care about arity.
#
# == Example:
- # You can supress raising an exception and return string instead:
+ # You can suppress raising an exception and return string instead:
#
# I18n.config.missing_interpolation_argument_handler = Proc.new do |key|
# "#{key} is missing"
diff --git a/lib/i18n/exceptions.rb b/lib/i18n/exceptions.rb
index f66e207..23ca46e 100644
--- a/lib/i18n/exceptions.rb
+++ b/lib/i18n/exceptions.rb
@@ -24,7 +24,7 @@ module I18n
been set is likely to display text from the wrong locale to some users.
If you have a legitimate reason to access i18n data outside of the user flow, you can do so by passing
- the desired locale explictly with the `locale` argument, e.g. `I18n.#{method}(..., locale: :en)`
+ the desired locale explicitly with the `locale` argument, e.g. `I18n.#{method}(..., locale: :en)`
MESSAGE
end
end
@@ -47,7 +47,7 @@ module I18n
class MissingTranslation < ArgumentError
module Base
- PERMITTED_KEYS = [:scope].freeze
+ PERMITTED_KEYS = [:scope, :default].freeze
attr_reader :locale, :key, :options
@@ -63,8 +63,18 @@ module I18n
end
def message
- "translation missing: #{keys.join('.')}"
+ if (default = options[:default]).is_a?(Array) && default.any?
+ other_options = ([key, *default]).map { |k| normalized_option(k).prepend('- ') }.join("\n")
+ "Translation missing. Options considered were:\n#{other_options}"
+ else
+ "Translation missing: #{keys.join('.')}"
+ end
+ end
+
+ def normalized_option(key)
+ I18n.normalize_keys(locale, key, options[:scope]).join('.')
end
+
alias :to_s :message
def to_exception
diff --git a/lib/i18n/interpolate/ruby.rb b/lib/i18n/interpolate/ruby.rb
index dab8f0e..5b50593 100644
--- a/lib/i18n/interpolate/ruby.rb
+++ b/lib/i18n/interpolate/ruby.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
# heavily based on Masao Mutoh's gettext String interpolation extension
# http://github.com/mutoh/gettext/blob/f6566738b981fe0952548c421042ad1e0cdfb31e/lib/gettext/core_ext/string.rb
@@ -10,6 +12,11 @@ module I18n
INTERPOLATION_PATTERN = Regexp.union(DEFAULT_INTERPOLATION_PATTERNS)
deprecate_constant :INTERPOLATION_PATTERN
+ INTERPOLATION_PATTERNS_CACHE = Hash.new do |hash, patterns|
+ hash[patterns] = Regexp.union(patterns)
+ end
+ private_constant :INTERPOLATION_PATTERNS_CACHE
+
class << self
# Return String or raises MissingInterpolationArgument exception.
# Missing argument's logic is handled by I18n.config.missing_interpolation_argument_handler.
@@ -20,7 +27,12 @@ module I18n
end
def interpolate_hash(string, values)
- string.gsub(Regexp.union(config.interpolation_patterns)) do |match|
+ pattern = INTERPOLATION_PATTERNS_CACHE[config.interpolation_patterns]
+ interpolated = false
+
+ interpolated_string = string.gsub(pattern) do |match|
+ interpolated = true
+
if match == '%%'
'%'
else
@@ -34,6 +46,8 @@ module I18n
$3 ? sprintf("%#{$3}", value) : value
end
end
+
+ interpolated ? interpolated_string : string
end
end
end
diff --git a/lib/i18n/locale/tag/simple.rb b/lib/i18n/locale/tag/simple.rb
index 6d9ab56..18d55c2 100644
--- a/lib/i18n/locale/tag/simple.rb
+++ b/lib/i18n/locale/tag/simple.rb
@@ -1,5 +1,5 @@
# Simple Locale tag implementation that computes subtags by simply splitting
-# the locale tag at '-' occurences.
+# the locale tag at '-' occurrences.
module I18n
module Locale
module Tag
diff --git a/lib/i18n/tests/basics.rb b/lib/i18n/tests/basics.rb
index be82430..833762b 100644
--- a/lib/i18n/tests/basics.rb
+++ b/lib/i18n/tests/basics.rb
@@ -26,7 +26,7 @@ module I18n
assert_equal I18n.available_locales, I18n.backend.available_locales
end
- test "available_locales memoizes when set explicitely" do
+ test "available_locales memoizes when set explicitly" do
I18n.backend.expects(:available_locales).never
I18n.available_locales = [:foo]
I18n.backend.store_translations('de', :bar => 'baz')
@@ -34,7 +34,7 @@ module I18n
assert_equal [:foo], I18n.available_locales
end
- test "available_locales delegates to the backend when not set explicitely" do
+ test "available_locales delegates to the backend when not set explicitly" do
original_available_locales_value = I18n.backend.available_locales
I18n.backend.expects(:available_locales).returns(original_available_locales_value).twice
assert_equal I18n.backend.available_locales, I18n.available_locales
diff --git a/lib/i18n/tests/localization/date.rb b/lib/i18n/tests/localization/date.rb
index 2a44371..c21fbbf 100644
--- a/lib/i18n/tests/localization/date.rb
+++ b/lib/i18n/tests/localization/date.rb
@@ -34,6 +34,11 @@ module I18n
assert_equal 'Sa', I18n.l(@date, :format => '%a', :locale => :de)
end
+ test "localize Date: given an meridian indicator format it returns the correct meridian indicator" do
+ assert_equal 'AM', I18n.l(@date, :format => '%p', :locale => :de)
+ assert_equal 'am', I18n.l(@date, :format => '%P', :locale => :de)
+ end
+
test "localize Date: given an abbreviated and uppercased day name format it returns the correct abbreviated day name in upcase" do
assert_equal 'sa'.upcase, I18n.l(@date, :format => '%^a', :locale => :de)
end
@@ -59,7 +64,7 @@ module I18n
end
test "localize Date: given missing translations it returns the correct error message" do
- assert_equal 'translation missing: fr.date.abbr_month_names', I18n.l(@date, :format => '%b', :locale => :fr)
+ assert_equal 'Translation missing: fr.date.abbr_month_names', I18n.l(@date, :format => '%b', :locale => :fr)
end
test "localize Date: given an unknown format it does not fail" do
diff --git a/lib/i18n/tests/localization/date_time.rb b/lib/i18n/tests/localization/date_time.rb
index b09b888..b5d3527 100644
--- a/lib/i18n/tests/localization/date_time.rb
+++ b/lib/i18n/tests/localization/date_time.rb
@@ -60,7 +60,7 @@ module I18n
end
test "localize DateTime: given missing translations it returns the correct error message" do
- assert_equal 'translation missing: fr.date.abbr_month_names', I18n.l(@datetime, :format => '%b', :locale => :fr)
+ assert_equal 'Translation missing: fr.date.abbr_month_names', I18n.l(@datetime, :format => '%b', :locale => :fr)
end
test "localize DateTime: given a meridian indicator format it returns the correct meridian indicator" do
diff --git a/lib/i18n/tests/localization/time.rb b/lib/i18n/tests/localization/time.rb
index 7afe176..456a760 100644
--- a/lib/i18n/tests/localization/time.rb
+++ b/lib/i18n/tests/localization/time.rb
@@ -61,7 +61,7 @@ module I18n
end
test "localize Time: given missing translations it returns the correct error message" do
- assert_equal 'translation missing: fr.date.abbr_month_names', I18n.l(@time, :format => '%b', :locale => :fr)
+ assert_equal 'Translation missing: fr.date.abbr_month_names', I18n.l(@time, :format => '%b', :locale => :fr)
end
test "localize Time: given a meridian indicator format it returns the correct meridian indicator" do
diff --git a/lib/i18n/tests/lookup.rb b/lib/i18n/tests/lookup.rb
index 3bd46b8..bbd775f 100644
--- a/lib/i18n/tests/lookup.rb
+++ b/lib/i18n/tests/lookup.rb
@@ -30,7 +30,7 @@ module I18n
end
test "lookup: given a missing key, no default and no raise option it returns an error message" do
- assert_equal "translation missing: en.missing", I18n.t(:missing)
+ assert_equal "Translation missing: en.missing", I18n.t(:missing)
end
test "lookup: given a missing key, no default and the raise option it raises MissingTranslationData" do
diff --git a/lib/i18n/version.rb b/lib/i18n/version.rb
index bc754ba..965f5dd 100644
--- a/lib/i18n/version.rb
+++ b/lib/i18n/version.rb
@@ -1,5 +1,5 @@
# frozen_string_literal: true
module I18n
- VERSION = "1.10.0"
+ VERSION = "1.14.1"
end
diff --git a/test/backend/cache_test.rb b/test/backend/cache_test.rb
index e253393..3ca4f19 100644
--- a/test/backend/cache_test.rb
+++ b/test/backend/cache_test.rb
@@ -62,8 +62,9 @@ class I18nBackendCacheTest < I18n::TestCase
I18n.t(:missing, :scope => :foo, :extra => true)
assert_equal 1, I18n.cache_store.instance_variable_get(:@data).size
- _, entry = I18n.cache_store.instance_variable_get(:@data).first
- assert_equal({ scope: :foo }, entry.value.options)
+ value = I18n.cache_store.read(I18n.cache_store.instance_variable_get(:@data).keys.first)
+
+ assert_equal({ scope: :foo }, value.options)
end
test "uses 'i18n' as a cache key namespace by default" do
diff --git a/test/backend/chain_test.rb b/test/backend/chain_test.rb
index b563374..acb50ef 100644
--- a/test/backend/chain_test.rb
+++ b/test/backend/chain_test.rb
@@ -78,7 +78,7 @@ class I18nBackendChainTest < I18n::TestCase
"Bah"], I18n.t([:formats, :plural_2, :bah], :default => 'Bah')
end
- test "store_translations options are not dropped while transfering to backend" do
+ test "store_translations options are not dropped while transferring to backend" do
@first.expects(:store_translations).with(:foo, {:bar => :baz}, {:option => 'persists'})
I18n.backend.store_translations :foo, {:bar => :baz}, {:option => 'persists'}
end
diff --git a/test/backend/exceptions_test.rb b/test/backend/exceptions_test.rb
index cc22166..e19c812 100644
--- a/test/backend/exceptions_test.rb
+++ b/test/backend/exceptions_test.rb
@@ -10,7 +10,7 @@ class I18nBackendExceptionsTest < I18n::TestCase
exception = catch(:exception) do
I18n.t(:'baz.missing', :scope => :'foo.bar', :throw => true)
end
- assert_equal "translation missing: en.foo.bar.baz.missing", exception.message
+ assert_equal "Translation missing: en.foo.bar.baz.missing", exception.message
end
test "exceptions: MissingTranslationData message from #translate includes the given scope and full key" do
@@ -18,7 +18,7 @@ class I18nBackendExceptionsTest < I18n::TestCase
I18n.t(:'baz.missing', :scope => :'foo.bar', :raise => true)
rescue I18n::MissingTranslationData => exception
end
- assert_equal "translation missing: en.foo.bar.baz.missing", exception.message
+ assert_equal "Translation missing: en.foo.bar.baz.missing", exception.message
end
test "exceptions: MissingTranslationData message from #localize includes the given scope and full key" do
@@ -26,7 +26,7 @@ class I18nBackendExceptionsTest < I18n::TestCase
I18n.l(Time.now, :format => :foo)
rescue I18n::MissingTranslationData => exception
end
- assert_equal "translation missing: en.time.formats.foo", exception.message
+ assert_equal "Translation missing: en.time.formats.foo", exception.message
end
test "exceptions: MissingInterpolationArgument message includes missing key, provided keys and full string" do
diff --git a/test/backend/fallbacks_test.rb b/test/backend/fallbacks_test.rb
index a215f73..8c20a04 100644
--- a/test/backend/fallbacks_test.rb
+++ b/test/backend/fallbacks_test.rb
@@ -29,7 +29,7 @@ class I18nBackendFallbacksTranslateTest < I18n::TestCase
end
test "keeps the count option when defaulting to a different key" do
- assert_equal 'Interpolate 5 10', I18n.t(:non_existant, default: :interpolate_count, count: 10, value: 5)
+ assert_equal 'Interpolate 5 10', I18n.t(:non_existent, default: :interpolate_count, count: 10, value: 5)
end
test "returns the :de translation for a missing :'de-DE' when :default is a String" do
@@ -60,8 +60,18 @@ class I18nBackendFallbacksTranslateTest < I18n::TestCase
assert_nil I18n.t(:missing_bar, :locale => :'de-DE', :default => nil)
end
- test "returns the translation missing message if the default is also missing" do
- assert_equal 'translation missing: de-DE.missing_bar', I18n.t(:missing_bar, :locale => :'de-DE', :default => [:missing_baz])
+ test "returns the Translation missing: message if the default is also missing" do
+ translation_missing_message = <<~MSG
+ Translation missing. Options considered were:
+ - de-DE.missing_bar
+ - de-DE.missing_baz
+ MSG
+
+ assert_equal translation_missing_message.chomp, I18n.t(:missing_bar, :locale => :'de-DE', :default => [:missing_baz])
+ end
+
+ test "returns the simple Translation missing: message when default is an empty Array" do
+ assert_equal "Translation missing: de-DE.missing_bar", I18n.t(:missing_bar, :locale => :'de-DE', :default => [])
end
test "returns the :'de-DE' default :baz translation for a missing :'de-DE' when defaults contains Symbol" do
@@ -192,7 +202,7 @@ class I18nBackendFallbacksLocalizeTestWithMultipleThreads < I18n::TestCase
end
# See Issue #590
-class I18nBackendFallbacksSymbolReolveRestartsLookupAtOriginalLocale < I18n::TestCase
+class I18nBackendFallbacksSymbolResolveRestartsLookupAtOriginalLocale < I18n::TestCase
class Backend < I18n::Backend::Simple
include I18n::Backend::Fallbacks
end
diff --git a/test/backend/key_value_test.rb b/test/backend/key_value_test.rb
index aefa9ce..34bce7b 100644
--- a/test/backend/key_value_test.rb
+++ b/test/backend/key_value_test.rb
@@ -21,7 +21,7 @@ class I18nBackendKeyValueTest < I18n::TestCase
assert_flattens({:"a.b"=>['a', 'b']}, {:a=>{:b =>['a', 'b']}}, true, false)
assert_flattens({:"a.b" => "c"}, {:"a.b" => "c"}, false)
end
-
+
test "store_translations supports numeric keys" do
setup_backend!
store_translations(:en, 1 => 'foo')
@@ -60,8 +60,8 @@ class I18nBackendKeyValueTest < I18n::TestCase
I18n.backend.send(:translations)
expected = { :en => {:foo => { :bar => 'bar', :baz => 'baz' }} }
assert_equal expected, translations
- end
-
+ end
+
test "subtrees enabled: given incomplete pluralization data it raises I18n::InvalidPluralizationData" do
setup_backend!
store_translations(:en, :bar => { :one => "One" })
@@ -71,7 +71,7 @@ class I18nBackendKeyValueTest < I18n::TestCase
test "subtrees disabled: given incomplete pluralization data it returns an error message" do
setup_backend!(false)
store_translations(:en, :bar => { :one => "One" })
- assert_equal "translation missing: en.bar", I18n.t(:bar, :count => 2)
+ assert_equal "Translation missing: en.bar", I18n.t(:bar, :count => 2)
end
test "translate handles subtrees for pluralization" do
@@ -79,7 +79,7 @@ class I18nBackendKeyValueTest < I18n::TestCase
store_translations(:en, :bar => { :one => "One" })
assert_equal("One", I18n.t("bar", :count => 1))
end
-
+
test "subtrees enabled: returns localized string given missing pluralization data" do
setup_backend!(true)
assert_equal 'bar', I18n.t("foo.bar", count: 1)
@@ -89,7 +89,7 @@ class I18nBackendKeyValueTest < I18n::TestCase
setup_backend!(false)
assert_equal 'bar', I18n.t("foo.bar", count: 1)
end
-
+
test "subtrees enabled: Returns fallback default given missing pluralization data" do
setup_backend!(true)
I18n.backend.extend I18n::Backend::Fallbacks
diff --git a/test/backend/lazy_loadable_test.rb b/test/backend/lazy_loadable_test.rb
index a15ab00..01e2efc 100644
--- a/test/backend/lazy_loadable_test.rb
+++ b/test/backend/lazy_loadable_test.rb
@@ -7,7 +7,7 @@ class I18nBackendLazyLoadableTest < I18n::TestCase
@lazy_mode_backend = I18n::Backend::LazyLoadable.new(lazy_load: true)
@eager_mode_backend = I18n::Backend::LazyLoadable.new(lazy_load: false)
- I18n.load_path = [File.join(locales_dir, '/en.yml'), File.join(locales_dir, '/fr.yml')]
+ I18n.load_path = [File.join(locales_dir, '/en.yml'), File.join(locales_dir, '/en.yaml'), File.join(locales_dir, '/fr.yml')]
end
test "lazy mode: only loads translations for current locale" do
diff --git a/test/backend/pluralization_test.rb b/test/backend/pluralization_test.rb
index d955818..0a7321a 100644
--- a/test/backend/pluralization_test.rb
+++ b/test/backend/pluralization_test.rb
@@ -9,16 +9,23 @@ class I18nBackendPluralizationTest < I18n::TestCase
def setup
super
I18n.backend = Backend.new
- @rule = lambda { |n| n == 1 ? :one : n == 0 || (2..10).include?(n % 100) ? :few : (11..19).include?(n % 100) ? :many : :other }
+ @rule = lambda { |n| n % 10 == 1 && n % 100 != 11 ? :one : n == 0 || (2..10).include?(n % 100) ? :few : (11..19).include?(n % 100) ? :many : :other }
store_translations(:xx, :i18n => { :plural => { :rule => @rule } })
- @entry = { :zero => 'zero', :one => 'one', :few => 'few', :many => 'many', :other => 'other' }
+ @entry = { :"0" => 'none', :"1" => 'single', :one => 'one', :few => 'few', :many => 'many', :other => 'other' }
+ @entry_with_zero = @entry.merge( { :zero => 'zero' } )
end
test "pluralization picks a pluralizer from :'i18n.pluralize'" do
assert_equal @rule, I18n.backend.send(:pluralizer, :xx)
end
- test "pluralization picks :one for 1" do
+ test "pluralization picks the explicit 1 rule for count == 1, the explicit rule takes priority over the matching :one rule" do
+ assert_equal 'single', I18n.t(:count => 1, :default => @entry, :locale => :xx)
+ assert_equal 'single', I18n.t(:count => 1.0, :default => @entry, :locale => :xx)
+ end
+
+ test "pluralization picks :one for 1, since in this case that is the matching rule for 1 (when there is no explicit 1 rule)" do
+ @entry.delete(:"1")
assert_equal 'one', I18n.t(:count => 1, :default => @entry, :locale => :xx)
end
@@ -31,20 +38,58 @@ class I18nBackendPluralizationTest < I18n::TestCase
end
test "pluralization picks zero for 0 if the key is contained in the data" do
- assert_equal 'zero', I18n.t(:count => 0, :default => @entry, :locale => :xx)
+ assert_equal 'zero', I18n.t(:count => 0, :default => @entry_with_zero, :locale => :xx)
end
- test "pluralization picks few for 0 if the key is not contained in the data" do
- @entry.delete(:zero)
+ test "pluralization picks explicit 0 rule for count == 0, since the explicit rule takes priority over the matching :few rule" do
+ assert_equal 'none', I18n.t(:count => 0, :default => @entry, :locale => :xx)
+ assert_equal 'none', I18n.t(:count => 0.0, :default => @entry, :locale => :xx)
+ assert_equal 'none', I18n.t(:count => -0, :default => @entry, :locale => :xx)
+ end
+
+ test "pluralization picks :few for 0 (when there is no explicit 0 rule)" do
+ @entry.delete(:"0")
assert_equal 'few', I18n.t(:count => 0, :default => @entry, :locale => :xx)
end
+ test "pluralization does Lateral Inheritance to :other to cover missing data" do
+ @entry.delete(:many)
+ assert_equal 'other', I18n.t(:count => 11, :default => @entry, :locale => :xx)
+ end
+
test "pluralization picks one for 1 if the entry has attributes hash on unknown locale" do
@entry[:attributes] = { :field => 'field', :second => 'second' }
assert_equal 'one', I18n.t(:count => 1, :default => @entry, :locale => :pirate)
end
+ test "Nested keys within pluralization context" do
+ store_translations(:xx,
+ :stars => {
+ one: "%{count} star",
+ other: "%{count} stars",
+ special: {
+ one: "%{count} special star",
+ other: "%{count} special stars",
+ }
+ }
+ )
+ assert_equal "1 star", I18n.t('stars', count: 1, :locale => :xx)
+ assert_equal "20 stars", I18n.t('stars', count: 20, :locale => :xx)
+ assert_equal "1 special star", I18n.t('stars.special', count: 1, :locale => :xx)
+ assert_equal "20 special stars", I18n.t('stars.special', count: 20, :locale => :xx)
+ end
+
test "Fallbacks can pick up rules from fallback locales, too" do
assert_equal @rule, I18n.backend.send(:pluralizer, :'xx-XX')
end
+
+ test "linked lookup works with pluralization backend" do
+ I18n.backend.store_translations(:xx, {
+ :automobiles => :autos,
+ :autos => :cars,
+ :cars => { :porsche => { :one => "I have %{count} Porsche 🚗", :other => "I have %{count} Porsches 🚗" } }
+ })
+ assert_equal "I have 1 Porsche 🚗", I18n.t(:'automobiles.porsche', count: 1, :locale => :xx)
+ assert_equal "I have 20 Porsches 🚗", I18n.t(:'automobiles.porsche', count: 20, :locale => :xx)
+ end
end
diff --git a/test/backend/simple_test.rb b/test/backend/simple_test.rb
index 23de486..d568961 100644
--- a/test/backend/simple_test.rb
+++ b/test/backend/simple_test.rb
@@ -209,6 +209,23 @@ class I18nBackendSimpleTest < I18n::TestCase
assert_equal true, I18n.backend.initialized?
end
+ test "Nested keys within pluralization context" do
+ store_translations(:en,
+ :stars => {
+ one: "%{count} star",
+ other: "%{count} stars",
+ special: {
+ one: "%{count} special star",
+ other: "%{count} special stars",
+ }
+ }
+ )
+ assert_equal "1 star", I18n.t('stars', count: 1, :locale => :en)
+ assert_equal "20 stars", I18n.t('stars', count: 20, :locale => :en)
+ assert_equal "1 special star", I18n.t('stars.special', count: 1, :locale => :en)
+ assert_equal "20 special stars", I18n.t('stars.special', count: 20, :locale => :en)
+ end
+
test "returns localized string given missing pluralization data" do
assert_equal 'baz', I18n.t('foo.bar', count: 1)
end
diff --git a/test/backend/transliterator_test.rb b/test/backend/transliterator_test.rb
index ebd446e..4c2bc22 100644
--- a/test/backend/transliterator_test.rb
+++ b/test/backend/transliterator_test.rb
@@ -42,7 +42,7 @@ class I18nBackendTransliterator < I18n::TestCase
# create string with range of Unicode's western characters with
# diacritics, excluding the division and multiplication signs which for
# some reason or other are floating in the middle of all the letters.
- string = (0xC0..0x17E).to_a.reject {|c| [0xD7, 0xF7].include? c}.pack("U*")
+ string = (0xC0..0x17E).to_a.reject {|c| [0xD7, 0xF7].include? c}.append(0x1E9E).pack("U*")
string.split(//) do |char|
assert_match %r{^[a-zA-Z']*$}, @transliterator.transliterate(string)
end
diff --git a/test/i18n/interpolate_test.rb b/test/i18n/interpolate_test.rb
index 79e59a9..2d54090 100644
--- a/test/i18n/interpolate_test.rb
+++ b/test/i18n/interpolate_test.rb
@@ -65,9 +65,15 @@ class I18nInterpolateTest < I18n::TestCase
end
end
+
test "with String subclass that redefined gsub method" do
assert_equal "Hello mars world", I18n.interpolate(RailsSafeBuffer.new("Hello %{planet} world"), :planet => 'mars')
end
+
+ test "with String subclass that redefined gsub method returns same object if no interpolations" do
+ string = RailsSafeBuffer.new("Hello world")
+ assert_same string, I18n.interpolate(string, :planet => 'mars')
+ end
end
class I18nMissingInterpolationCustomHandlerTest < I18n::TestCase
diff --git a/test/i18n/middleware_test.rb b/test/i18n/middleware_test.rb
index c8f6d36..f0982cb 100644
--- a/test/i18n/middleware_test.rb
+++ b/test/i18n/middleware_test.rb
@@ -16,7 +16,7 @@ class I18nMiddlewareTest < I18n::TestCase
refute_equal updated_i18n_config_object_id, old_i18n_config_object_id
end
- test "succesfully resets i18n locale to default locale by defining new config" do
+ test "successfully resets i18n locale to default locale by defining new config" do
@middleware.call({})
assert_equal :fr, I18n.locale
diff --git a/test/i18n_test.rb b/test/i18n_test.rb
index a0b8105..3f576fb 100644
--- a/test/i18n_test.rb
+++ b/test/i18n_test.rb
@@ -140,6 +140,10 @@ class I18nTest < I18n::TestCase
assert_equal [:en, :foo, :bar, :baz, :buz], I18n.normalize_keys(:en, :'baz|buz', :'foo|bar', '|')
end
+ test "normalize_keys normalizes given locale with separator" do
+ assert_equal [:en, :foo, :bar, :baz], I18n.normalize_keys(:"en.foo", :baz, :bar)
+ end
+
test "can set the exception_handler" do
begin
previous_exception_handler = I18n.exception_handler
@@ -205,11 +209,18 @@ class I18nTest < I18n::TestCase
end
# def test_translate_given_no_args_raises_missing_translation_data
- # assert_equal "translation missing: en, no key", I18n.t
+ # assert_equal "Translation missing: en, no key", I18n.t
# end
test "translate given a bogus key returns an error message" do
- assert_equal "translation missing: en.bogus", I18n.t(:bogus)
+ assert_equal "Translation missing: en.bogus", I18n.t(:bogus)
+ end
+
+ test "translate given multiple bogus keys returns an array of error messages" do
+ assert_equal(
+ ["Translation missing: en.bogus", "Translation missing: en.also_bogus"],
+ I18n.t([:bogus, :also_bogus]),
+ )
end
test "translate given an empty string as a key raises an I18n::ArgumentError" do
@@ -255,7 +266,7 @@ class I18nTest < I18n::TestCase
I18n.t('foo')
end
- assert_equal 'translation missing: en.foo', I18n.t('foo', locale: :en)
+ assert_equal 'Translation missing: en.foo', I18n.t('foo', locale: :en)
end
end
@@ -296,6 +307,10 @@ class I18nTest < I18n::TestCase
assert_equal true, I18n.exists?(:currency, :nl)
end
+ test "exists? given an existing key and a scope will return true" do
+ assert_equal true, I18n.exists?(:delimiter, scope: [:currency, :format])
+ end
+
test "exists? given a non-existing key and an existing locale will return false" do
assert_equal false, I18n.exists?(:bogus, :nl)
end
@@ -379,7 +394,7 @@ class I18nTest < I18n::TestCase
assert_equal I18n.default_locale, I18n.locale
end
- test "I18n.translitarate handles I18n::ArgumentError exception" do
+ test "I18n.transliterate handles I18n::ArgumentError exception" do
I18n::Backend::Transliterator.stubs(:get).raises(I18n::ArgumentError)
I18n.exception_handler.expects(:call).raises(I18n::ArgumentError)
assert_raises(I18n::ArgumentError) {
@@ -387,7 +402,7 @@ class I18nTest < I18n::TestCase
}
end
- test "I18n.translitarate raises I18n::ArgumentError exception" do
+ test "I18n.transliterate raises I18n::ArgumentError exception" do
I18n::Backend::Transliterator.stubs(:get).raises(I18n::ArgumentError)
I18n.exception_handler.expects(:call).never
assert_raises(I18n::ArgumentError) {
@@ -490,18 +505,14 @@ class I18nTest < I18n::TestCase
test "can reserve a key" do
begin
- reserved_keys_were = I18n::RESERVED_KEYS.dup
-
- assert !I18n::RESERVED_KEYS.include?(:foo)
- assert !I18n::RESERVED_KEYS.include?(:bar)
+ stub_const(I18n, :RESERVED_KEYS, []) do
+ I18n.reserve_key(:foo)
+ I18n.reserve_key("bar")
- I18n.reserve_key(:foo)
- I18n.reserve_key("bar")
-
- assert I18n::RESERVED_KEYS.include?(:foo)
- assert I18n::RESERVED_KEYS.include?(:bar)
+ assert I18n::RESERVED_KEYS.include?(:foo)
+ assert I18n::RESERVED_KEYS.include?(:bar)
+ end
ensure
- I18n::RESERVED_KEYS = reserved_keys_were
I18n.instance_variable_set(:@reserved_keys_pattern, nil)
end
end
diff --git a/test/test_helper.rb b/test/test_helper.rb
index 78b9635..f36b20b 100644
--- a/test/test_helper.rb
+++ b/test/test_helper.rb
@@ -44,6 +44,16 @@ class I18n::TestCase < Minitest::Test
def locales_dir
File.dirname(__FILE__) + '/test_data/locales'
end
+
+ def stub_const(klass, constant, new_value)
+ old_value = klass.const_get(constant)
+ klass.send(:remove_const, constant)
+ klass.const_set(constant, new_value)
+ yield
+ ensure
+ klass.send(:remove_const, constant)
+ klass.const_set(constant, old_value)
+ end
end
class DummyRackApp
Debdiff
[The following lists of changes regard files as different if they have different names, permissions or owners.]
Files in second set of .debs but not in first
-rw-r--r-- root/root /usr/share/rubygems-integration/all/gems/i18n-1.14.1/lib/i18n.rb -rw-r--r-- root/root /usr/share/rubygems-integration/all/gems/i18n-1.14.1/lib/i18n/backend.rb -rw-r--r-- root/root /usr/share/rubygems-integration/all/gems/i18n-1.14.1/lib/i18n/backend/base.rb -rw-r--r-- root/root /usr/share/rubygems-integration/all/gems/i18n-1.14.1/lib/i18n/backend/cache.rb -rw-r--r-- root/root /usr/share/rubygems-integration/all/gems/i18n-1.14.1/lib/i18n/backend/cache_file.rb -rw-r--r-- root/root /usr/share/rubygems-integration/all/gems/i18n-1.14.1/lib/i18n/backend/cascade.rb -rw-r--r-- root/root /usr/share/rubygems-integration/all/gems/i18n-1.14.1/lib/i18n/backend/chain.rb -rw-r--r-- root/root /usr/share/rubygems-integration/all/gems/i18n-1.14.1/lib/i18n/backend/fallbacks.rb -rw-r--r-- root/root /usr/share/rubygems-integration/all/gems/i18n-1.14.1/lib/i18n/backend/flatten.rb -rw-r--r-- root/root /usr/share/rubygems-integration/all/gems/i18n-1.14.1/lib/i18n/backend/gettext.rb -rw-r--r-- root/root /usr/share/rubygems-integration/all/gems/i18n-1.14.1/lib/i18n/backend/interpolation_compiler.rb -rw-r--r-- root/root /usr/share/rubygems-integration/all/gems/i18n-1.14.1/lib/i18n/backend/key_value.rb -rw-r--r-- root/root /usr/share/rubygems-integration/all/gems/i18n-1.14.1/lib/i18n/backend/lazy_loadable.rb -rw-r--r-- root/root /usr/share/rubygems-integration/all/gems/i18n-1.14.1/lib/i18n/backend/memoize.rb -rw-r--r-- root/root /usr/share/rubygems-integration/all/gems/i18n-1.14.1/lib/i18n/backend/metadata.rb -rw-r--r-- root/root /usr/share/rubygems-integration/all/gems/i18n-1.14.1/lib/i18n/backend/pluralization.rb -rw-r--r-- root/root /usr/share/rubygems-integration/all/gems/i18n-1.14.1/lib/i18n/backend/simple.rb -rw-r--r-- root/root /usr/share/rubygems-integration/all/gems/i18n-1.14.1/lib/i18n/backend/transliterator.rb -rw-r--r-- root/root /usr/share/rubygems-integration/all/gems/i18n-1.14.1/lib/i18n/config.rb -rw-r--r-- root/root /usr/share/rubygems-integration/all/gems/i18n-1.14.1/lib/i18n/exceptions.rb -rw-r--r-- root/root /usr/share/rubygems-integration/all/gems/i18n-1.14.1/lib/i18n/gettext.rb -rw-r--r-- root/root /usr/share/rubygems-integration/all/gems/i18n-1.14.1/lib/i18n/gettext/helpers.rb -rw-r--r-- root/root /usr/share/rubygems-integration/all/gems/i18n-1.14.1/lib/i18n/gettext/po_parser.rb -rw-r--r-- root/root /usr/share/rubygems-integration/all/gems/i18n-1.14.1/lib/i18n/interpolate/ruby.rb -rw-r--r-- root/root /usr/share/rubygems-integration/all/gems/i18n-1.14.1/lib/i18n/locale.rb -rw-r--r-- root/root /usr/share/rubygems-integration/all/gems/i18n-1.14.1/lib/i18n/locale/fallbacks.rb -rw-r--r-- root/root /usr/share/rubygems-integration/all/gems/i18n-1.14.1/lib/i18n/locale/tag.rb -rw-r--r-- root/root /usr/share/rubygems-integration/all/gems/i18n-1.14.1/lib/i18n/locale/tag/parents.rb -rw-r--r-- root/root /usr/share/rubygems-integration/all/gems/i18n-1.14.1/lib/i18n/locale/tag/rfc4646.rb -rw-r--r-- root/root /usr/share/rubygems-integration/all/gems/i18n-1.14.1/lib/i18n/locale/tag/simple.rb -rw-r--r-- root/root /usr/share/rubygems-integration/all/gems/i18n-1.14.1/lib/i18n/middleware.rb -rw-r--r-- root/root /usr/share/rubygems-integration/all/gems/i18n-1.14.1/lib/i18n/tests.rb -rw-r--r-- root/root /usr/share/rubygems-integration/all/gems/i18n-1.14.1/lib/i18n/tests/basics.rb -rw-r--r-- root/root /usr/share/rubygems-integration/all/gems/i18n-1.14.1/lib/i18n/tests/defaults.rb -rw-r--r-- root/root /usr/share/rubygems-integration/all/gems/i18n-1.14.1/lib/i18n/tests/interpolation.rb -rw-r--r-- root/root /usr/share/rubygems-integration/all/gems/i18n-1.14.1/lib/i18n/tests/link.rb -rw-r--r-- root/root /usr/share/rubygems-integration/all/gems/i18n-1.14.1/lib/i18n/tests/localization.rb -rw-r--r-- root/root /usr/share/rubygems-integration/all/gems/i18n-1.14.1/lib/i18n/tests/localization/date.rb -rw-r--r-- root/root /usr/share/rubygems-integration/all/gems/i18n-1.14.1/lib/i18n/tests/localization/date_time.rb -rw-r--r-- root/root /usr/share/rubygems-integration/all/gems/i18n-1.14.1/lib/i18n/tests/localization/procs.rb -rw-r--r-- root/root /usr/share/rubygems-integration/all/gems/i18n-1.14.1/lib/i18n/tests/localization/time.rb -rw-r--r-- root/root /usr/share/rubygems-integration/all/gems/i18n-1.14.1/lib/i18n/tests/lookup.rb -rw-r--r-- root/root /usr/share/rubygems-integration/all/gems/i18n-1.14.1/lib/i18n/tests/pluralization.rb -rw-r--r-- root/root /usr/share/rubygems-integration/all/gems/i18n-1.14.1/lib/i18n/tests/procs.rb -rw-r--r-- root/root /usr/share/rubygems-integration/all/gems/i18n-1.14.1/lib/i18n/utils.rb -rw-r--r-- root/root /usr/share/rubygems-integration/all/gems/i18n-1.14.1/lib/i18n/version.rb -rw-r--r-- root/root /usr/share/rubygems-integration/all/specifications/i18n-1.14.1.gemspec
Files in first set of .debs but not in second
-rw-r--r-- root/root /usr/share/rubygems-integration/all/gems/i18n-1.10.0/lib/i18n.rb -rw-r--r-- root/root /usr/share/rubygems-integration/all/gems/i18n-1.10.0/lib/i18n/backend.rb -rw-r--r-- root/root /usr/share/rubygems-integration/all/gems/i18n-1.10.0/lib/i18n/backend/base.rb -rw-r--r-- root/root /usr/share/rubygems-integration/all/gems/i18n-1.10.0/lib/i18n/backend/cache.rb -rw-r--r-- root/root /usr/share/rubygems-integration/all/gems/i18n-1.10.0/lib/i18n/backend/cache_file.rb -rw-r--r-- root/root /usr/share/rubygems-integration/all/gems/i18n-1.10.0/lib/i18n/backend/cascade.rb -rw-r--r-- root/root /usr/share/rubygems-integration/all/gems/i18n-1.10.0/lib/i18n/backend/chain.rb -rw-r--r-- root/root /usr/share/rubygems-integration/all/gems/i18n-1.10.0/lib/i18n/backend/fallbacks.rb -rw-r--r-- root/root /usr/share/rubygems-integration/all/gems/i18n-1.10.0/lib/i18n/backend/flatten.rb -rw-r--r-- root/root /usr/share/rubygems-integration/all/gems/i18n-1.10.0/lib/i18n/backend/gettext.rb -rw-r--r-- root/root /usr/share/rubygems-integration/all/gems/i18n-1.10.0/lib/i18n/backend/interpolation_compiler.rb -rw-r--r-- root/root /usr/share/rubygems-integration/all/gems/i18n-1.10.0/lib/i18n/backend/key_value.rb -rw-r--r-- root/root /usr/share/rubygems-integration/all/gems/i18n-1.10.0/lib/i18n/backend/lazy_loadable.rb -rw-r--r-- root/root /usr/share/rubygems-integration/all/gems/i18n-1.10.0/lib/i18n/backend/memoize.rb -rw-r--r-- root/root /usr/share/rubygems-integration/all/gems/i18n-1.10.0/lib/i18n/backend/metadata.rb -rw-r--r-- root/root /usr/share/rubygems-integration/all/gems/i18n-1.10.0/lib/i18n/backend/pluralization.rb -rw-r--r-- root/root /usr/share/rubygems-integration/all/gems/i18n-1.10.0/lib/i18n/backend/simple.rb -rw-r--r-- root/root /usr/share/rubygems-integration/all/gems/i18n-1.10.0/lib/i18n/backend/transliterator.rb -rw-r--r-- root/root /usr/share/rubygems-integration/all/gems/i18n-1.10.0/lib/i18n/config.rb -rw-r--r-- root/root /usr/share/rubygems-integration/all/gems/i18n-1.10.0/lib/i18n/exceptions.rb -rw-r--r-- root/root /usr/share/rubygems-integration/all/gems/i18n-1.10.0/lib/i18n/gettext.rb -rw-r--r-- root/root /usr/share/rubygems-integration/all/gems/i18n-1.10.0/lib/i18n/gettext/helpers.rb -rw-r--r-- root/root /usr/share/rubygems-integration/all/gems/i18n-1.10.0/lib/i18n/gettext/po_parser.rb -rw-r--r-- root/root /usr/share/rubygems-integration/all/gems/i18n-1.10.0/lib/i18n/interpolate/ruby.rb -rw-r--r-- root/root /usr/share/rubygems-integration/all/gems/i18n-1.10.0/lib/i18n/locale.rb -rw-r--r-- root/root /usr/share/rubygems-integration/all/gems/i18n-1.10.0/lib/i18n/locale/fallbacks.rb -rw-r--r-- root/root /usr/share/rubygems-integration/all/gems/i18n-1.10.0/lib/i18n/locale/tag.rb -rw-r--r-- root/root /usr/share/rubygems-integration/all/gems/i18n-1.10.0/lib/i18n/locale/tag/parents.rb -rw-r--r-- root/root /usr/share/rubygems-integration/all/gems/i18n-1.10.0/lib/i18n/locale/tag/rfc4646.rb -rw-r--r-- root/root /usr/share/rubygems-integration/all/gems/i18n-1.10.0/lib/i18n/locale/tag/simple.rb -rw-r--r-- root/root /usr/share/rubygems-integration/all/gems/i18n-1.10.0/lib/i18n/middleware.rb -rw-r--r-- root/root /usr/share/rubygems-integration/all/gems/i18n-1.10.0/lib/i18n/tests.rb -rw-r--r-- root/root /usr/share/rubygems-integration/all/gems/i18n-1.10.0/lib/i18n/tests/basics.rb -rw-r--r-- root/root /usr/share/rubygems-integration/all/gems/i18n-1.10.0/lib/i18n/tests/defaults.rb -rw-r--r-- root/root /usr/share/rubygems-integration/all/gems/i18n-1.10.0/lib/i18n/tests/interpolation.rb -rw-r--r-- root/root /usr/share/rubygems-integration/all/gems/i18n-1.10.0/lib/i18n/tests/link.rb -rw-r--r-- root/root /usr/share/rubygems-integration/all/gems/i18n-1.10.0/lib/i18n/tests/localization.rb -rw-r--r-- root/root /usr/share/rubygems-integration/all/gems/i18n-1.10.0/lib/i18n/tests/localization/date.rb -rw-r--r-- root/root /usr/share/rubygems-integration/all/gems/i18n-1.10.0/lib/i18n/tests/localization/date_time.rb -rw-r--r-- root/root /usr/share/rubygems-integration/all/gems/i18n-1.10.0/lib/i18n/tests/localization/procs.rb -rw-r--r-- root/root /usr/share/rubygems-integration/all/gems/i18n-1.10.0/lib/i18n/tests/localization/time.rb -rw-r--r-- root/root /usr/share/rubygems-integration/all/gems/i18n-1.10.0/lib/i18n/tests/lookup.rb -rw-r--r-- root/root /usr/share/rubygems-integration/all/gems/i18n-1.10.0/lib/i18n/tests/pluralization.rb -rw-r--r-- root/root /usr/share/rubygems-integration/all/gems/i18n-1.10.0/lib/i18n/tests/procs.rb -rw-r--r-- root/root /usr/share/rubygems-integration/all/gems/i18n-1.10.0/lib/i18n/utils.rb -rw-r--r-- root/root /usr/share/rubygems-integration/all/gems/i18n-1.10.0/lib/i18n/version.rb -rw-r--r-- root/root /usr/share/rubygems-integration/all/specifications/i18n-1.10.0.gemspec
No differences were encountered in the control files