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. # Configuration parameters: AutoCorrect, AllowHeredoc, AllowURI, URISchemes, IgnoreCopDirectives, IgnoredPatterns.
# URISchemes: http, https # URISchemes: http, https
Layout/LineLength: Layout/LineLength:
Max: 260 Max: 370
# Offense count: 35 # Offense count: 35
# Configuration parameters: AllowSafeAssignment. # Configuration parameters: AllowSafeAssignment.

View file

@ -15,7 +15,11 @@ class Locale < I18n::Locale::Tag::Rfc4646
end end
def expand 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
end end
@ -28,17 +32,23 @@ class Locale < I18n::Locale::Tag::Rfc4646
end end
def self.available 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 end
def candidates def candidates
[self.class.new(language, script, region, variant), List.new([self.class.new(language, script, region, variant),
self.class.new(language, script, region), self.class.new(language, script, region),
self.class.new(language, script, nil, variant), self.class.new(language, script, nil, variant),
self.class.new(language, script), self.class.new(language, script),
self.class.new(language, nil, region, variant), self.class.new(language, nil, region, variant),
self.class.new(language, nil, region), self.class.new(language, nil, region),
self.class.new(language, nil, nil, variant), self.class.new(language, nil, nil, variant),
self.class.new(language)] self.class.new(language)])
end end
end end

View file

@ -32,7 +32,7 @@ class UserCreationTest < ActionDispatch::IntegrationTest
end end
def test_user_create_submit_duplicate_email def test_user_create_submit_duplicate_email
I18n.available_locales.each do |locale| Locale.available.each do |locale|
dup_email = create(:user).email dup_email = create(:user).email
display_name = "#{locale}_new_tester" display_name = "#{locale}_new_tester"
assert_difference("User.count", 0) do assert_difference("User.count", 0) do
@ -50,7 +50,7 @@ class UserCreationTest < ActionDispatch::IntegrationTest
end end
assert_response :success assert_response :success
assert_template "users/new" 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_select "form > fieldset > div.standard-form-row > input.field_with_errors#user_email"
assert_no_missing_translations assert_no_missing_translations
end end

View file

@ -80,7 +80,7 @@ class LocaleTest < ActiveSupport::TestCase
end end
def test_available def test_available
assert_equal I18n.available_locales.count, Locale.available.count assert Locale.available.count <= I18n.available_locales.count
end end
def test_preferred 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 "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-Hant-TW", "de")).to_s
assert_equal "zh-TW", Locale.available.preferred(Locale.list("zh-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-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 "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 "en", Locale.available.preferred(Locale.list("yue")).to_s assert_equal "en", Locale.available.preferred(Locale.list("yue")).to_s
end end
end end