这是indexloc提供的服务,不要输入任何密码
Skip to content

[BUG] I18n::Locale::Tag::Rfc4646 and I18n::Locale::Fallbacks have a type mismatch #711

@movermeyer

Description

@movermeyer

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions