Improve locale selection algorithm

Don't include locales which only have rails translations in
the candidates, and ensure that user specified options take
priority over less specific variants of earlier choices.
This commit is contained in:
Tom Hughes 2020-06-04 17:23:16 +01:00
parent b16388d099
commit bf22c69286
4 changed files with 25 additions and 17 deletions

View file

@ -18,7 +18,7 @@ require:
# Configuration parameters: AutoCorrect, AllowHeredoc, AllowURI, URISchemes, IgnoreCopDirectives, IgnoredPatterns.
# URISchemes: http, https
Layout/LineLength:
Max: 260
Max: 370
# Offense count: 35
# Configuration parameters: AllowSafeAssignment.

View file

@ -15,7 +15,11 @@ class Locale < I18n::Locale::Tag::Rfc4646
end
def expand
map(&:candidates).flatten.uniq << Locale.default
List.new(reverse.each_with_object([]) do |locale, expanded|
locale.candidates.uniq.reverse_each do |candidate|
expanded << candidate if candidate == locale || !expanded.include?(candidate)
end
end.reverse.uniq << Locale.default)
end
end
@ -28,17 +32,23 @@ class Locale < I18n::Locale::Tag::Rfc4646
end
def self.available
@available ||= List.new(I18n.available_locales)
@available ||= List.new(I18n.available_locales).reject!(&:invalid?)
end
def invalid?
I18n.t("activerecord.models.acl", :locale => self, :fallback => false, :raise => true).nil?
rescue I18n::MissingTranslationData
true
end
def candidates
[self.class.new(language, script, region, variant),
self.class.new(language, script, region),
self.class.new(language, script, nil, variant),
self.class.new(language, script),
self.class.new(language, nil, region, variant),
self.class.new(language, nil, region),
self.class.new(language, nil, nil, variant),
self.class.new(language)]
List.new([self.class.new(language, script, region, variant),
self.class.new(language, script, region),
self.class.new(language, script, nil, variant),
self.class.new(language, script),
self.class.new(language, nil, region, variant),
self.class.new(language, nil, region),
self.class.new(language, nil, nil, variant),
self.class.new(language)])
end
end

View file

@ -32,7 +32,7 @@ class UserCreationTest < ActionDispatch::IntegrationTest
end
def test_user_create_submit_duplicate_email
I18n.available_locales.each do |locale|
Locale.available.each do |locale|
dup_email = create(:user).email
display_name = "#{locale}_new_tester"
assert_difference("User.count", 0) do
@ -50,7 +50,7 @@ class UserCreationTest < ActionDispatch::IntegrationTest
end
assert_response :success
assert_template "users/new"
assert_equal locale.to_s, response.headers["Content-Language"] unless locale == :root
assert_equal locale.to_s, response.headers["Content-Language"]
assert_select "form > fieldset > div.standard-form-row > input.field_with_errors#user_email"
assert_no_missing_translations
end

View file

@ -80,7 +80,7 @@ class LocaleTest < ActiveSupport::TestCase
end
def test_available
assert_equal I18n.available_locales.count, Locale.available.count
assert Locale.available.count <= I18n.available_locales.count
end
def test_preferred
@ -91,9 +91,7 @@ class LocaleTest < ActiveSupport::TestCase
assert_equal "de", Locale.available.preferred(Locale.list("zh-Hant", "de")).to_s
assert_equal "zh-TW", Locale.available.preferred(Locale.list("zh-Hant-TW", "de")).to_s
assert_equal "zh-TW", Locale.available.preferred(Locale.list("zh-TW", "de")).to_s
assert_equal "zh-HK", Locale.available.preferred(Locale.list("yue", "zh-HK", "de")).to_s
assert_equal "zh-yue", Locale.available.preferred(Locale.list("yue", "zh-yue", "zh-HK", "de")).to_s
assert_equal "zh-yue", Locale.available.preferred(Locale.list("yue", "zh-YUE", "zh-HK", "de")).to_s
assert_equal "zh-TW", Locale.available.preferred(Locale.list("zh-HK", "zh-hk", "zh-Hant", "zh-hant", "zh-TW", "zh-tw", "zh", "zh-yue", "yue", "yue-Hant", "yue-HK", "yue-Hans", "zh-classical", "lzh", "ja-Hani", "ko-Hani", "ko_hanja", "vi-Hani", "ja-hani", "ko-hani", "vi-hani", "en-HK", "en-hk", "en-SG", "en-sg", "en-GB", "en-gb", "en-US", "en-us", "en", "ja")).to_s
assert_equal "en", Locale.available.preferred(Locale.list("yue")).to_s
end
end