What I tried to do
When using I18n::Locale::Tag::Rfc4646, I18n::Locale::Fallbacks#[] will throw a NoMethodError exception if the locale isn't an RFC 4646 locale.
What I expected to happen
I expected it to return the locale itself with no fallbacks, similar to the behaviour of I18n::Locale::Tag::Simple.
Alternatively, raise an exception related to the locale.
What actually happened
NoMethodError: undefined method `self_and_parents' for nil:NilClass
lib/i18n/locale/fallbacks.rb:95:in `block in compute'
lib/i18n/locale/fallbacks.rb:94:in `each'
lib/i18n/locale/fallbacks.rb:94:in `compute'
lib/i18n/locale/fallbacks.rb:64:in `[]'
test/locale/fallbacks_test.rb:19:in `block in <class:I18nFallbacksDefaultsTest>'
This is due to I18n::Locale::Fallbacks assuming that I18n::Locale::Tag#tag cannot return nil, which is the case for I18n::Locale::Tag::Simple, but not I18n::Locale::Tag::Rfc4646.
There's a type mismatch. Which case is wrong is up for debate: is the return type of I18n::Locale::Tag#tag String or T.nilable(String) (using Sorbet type syntax)?
Versions of i18n, rails, and anything else you think is necessary
Latest Ruby and i18n, but the problematic code goes back to the 2009-07 (when both of these files were introduced):
➜ i18n git:(master) ruby --version
ruby 3.3.4 (2024-07-09 revision be1089c8ec) [arm64-darwin23]
➜ i18n git:(master) bundle list
Gems included by the bundle:
* concurrent-ruby (1.3.4)
* i18n (1.14.6)
* json (2.9.1)
* minitest (5.25.4)
* mocha (2.1.0)
* racc (1.8.1)
* rake (13.2.1)
* ruby2_keywords (0.0.5)
* test_declarative (0.0.6)
Potential tests for test/locale/fallbacks_test.rb:
test "handles invalid RFC 4646 locales with I18n::Locale::Tag::Simple" do
I18n::Locale::Tag.implementation = I18n::Locale::Tag::Simple
fallbacks = Fallbacks.new
invalid_locale = :"123" # Invalid RFC 4646 locale
assert_equal([:"123"], fallbacks[invalid_locale])
end
test "handles invalid RFC 4646 locales with I18n::Locale::Tag::Rfc4646" do
I18n::Locale::Tag.implementation = I18n::Locale::Tag::Rfc4646
fallbacks = Fallbacks.new
invalid_locale = :"123" # Invalid RFC 4646 locale
assert_equal([:"123"], fallbacks[invalid_locale])
end
What I tried to do
When using
I18n::Locale::Tag::Rfc4646,I18n::Locale::Fallbacks#[]will throw aNoMethodErrorexception if the locale isn't an RFC 4646 locale.What I expected to happen
I expected it to return the locale itself with no fallbacks, similar to the behaviour of
I18n::Locale::Tag::Simple.Alternatively, raise an exception related to the locale.
What actually happened
This is due to
I18n::Locale::Fallbacksassuming thatI18n::Locale::Tag#tagcannot returnnil, which is the case forI18n::Locale::Tag::Simple, but notI18n::Locale::Tag::Rfc4646.There's a type mismatch. Which case is wrong is up for debate: is the return type of
I18n::Locale::Tag#tagStringorT.nilable(String)(using Sorbet type syntax)?Versions of i18n, rails, and anything else you think is necessary
Latest Ruby and i18n, but the problematic code goes back to the 2009-07 (when both of these files were introduced):
Potential tests for
test/locale/fallbacks_test.rb: