Improve locale comparison

Since 9456454109, country specific locales are always preferred over
country-less locales even when the OS locale country doesn't match. For
example, running the Godot editor with locale es_ES will result in the
es_AR locale being chosen even though the es locale would be better.

The change happened because the score of the es_AR locale and the es
locale are the same when comparing to es_ES. Change this by parsing
locale strings into a Locale structure and decreasing the score when
script, country or variant are set in both but not matched. For the
es_ES case, this causes the es_AR score to be decreased since the
countries don't match. On the other hand, the es locale is not decreased
since it doesn't specify a country.
This commit is contained in:
Dan Nicholson
2024-11-01 13:49:51 -06:00
parent 1bffd6c73b
commit 2dd409fd70
3 changed files with 148 additions and 65 deletions

View File

@@ -110,18 +110,50 @@ TEST_CASE("[TranslationServer] Comparing locales") {
locale_a = "sr-Latn-CS";
locale_b = "sr-Latn-RS";
// Two elements from locales match.
// Script matches (+1) but country doesn't (-1).
res = ts->compare_locales(locale_a, locale_b);
CHECK(res == 2);
CHECK(res == 5);
locale_a = "uz-Cyrl-UZ";
locale_b = "uz-Latn-UZ";
// Two elements match, but they are not sequentual.
// Country matches (+1) but script doesn't (-1).
res = ts->compare_locales(locale_a, locale_b);
CHECK(res == 2);
CHECK(res == 5);
locale_a = "aa-Latn-ER";
locale_b = "aa-Latn-ER-saaho";
// Script and country match (+2) with variant on one locale (+0).
res = ts->compare_locales(locale_a, locale_b);
CHECK(res == 7);
locale_a = "uz-Cyrl-UZ";
locale_b = "uz-Latn-KG";
// Both script and country mismatched (-2).
res = ts->compare_locales(locale_a, locale_b);
CHECK(res == 3);
locale_a = "es-ES";
locale_b = "es-AR";
// Mismatched country (-1).
res = ts->compare_locales(locale_a, locale_b);
CHECK(res == 4);
locale_a = "es";
locale_b = "es-AR";
// No country for one locale (+0).
res = ts->compare_locales(locale_a, locale_b);
CHECK(res == 5);
locale_a = "es-EC";
locale_b = "fr-LU";
@@ -130,6 +162,24 @@ TEST_CASE("[TranslationServer] Comparing locales") {
res = ts->compare_locales(locale_a, locale_b);
CHECK(res == 0);
locale_a = "zh-HK";
locale_b = "zh";
// In full standardization, zh-HK becomes zh_Hant_HK and zh becomes
// zh_Hans_CN. Both script and country mismatch (-2).
res = ts->compare_locales(locale_a, locale_b);
CHECK(res == 3);
locale_a = "zh-CN";
locale_b = "zh";
// In full standardization, zh and zh-CN both become zh_Hans_CN for an
// exact match.
res = ts->compare_locales(locale_a, locale_b);
CHECK(res == 10);
}
} // namespace TestTranslationServer