Translation: Fix logic bug finding match for regional locales

The  match test was inverted. The rest of the changes
are documentation and cleanup.

Fixes #26346 and fixes #31192.

(cherry picked from commit b33042507b)
This commit is contained in:
Rémi Verschelde 2019-08-08 10:15:55 +02:00
parent a5547ac3c7
commit b45ec12c8c
1 changed files with 32 additions and 32 deletions

View File

@ -1030,6 +1030,13 @@ StringName TranslationServer::translate(const StringName &p_message) const {
if (!enabled) if (!enabled)
return p_message; return p_message;
// Locale can be of the form 'll_CC', i.e. language code and regional code,
// e.g. 'en_US', 'en_GB', etc. It might also be simply 'll', e.g. 'en'.
// To find the relevant translation, we look for those with locale starting
// with the language code, and then if any is an exact match for the long
// form. If not found, we fall back to a near match (another locale with
// same language code).
StringName res; StringName res;
bool near_match = false; bool near_match = false;
const CharType *lptr = &locale[0]; const CharType *lptr = &locale[0];
@ -1039,13 +1046,11 @@ StringName TranslationServer::translate(const StringName &p_message) const {
const Ref<Translation> &t = E->get(); const Ref<Translation> &t = E->get();
String l = t->get_locale(); String l = t->get_locale();
if (lptr[0] != l[0] || lptr[1] != l[1]) if (lptr[0] != l[0] || lptr[1] != l[1])
continue; // locale not match continue; // Language code does not match.
//near match bool exact_match = (l == locale);
bool match = (l != locale); if (!exact_match && near_match)
continue; // Only near-match once, but keep looking for exact matches.
if (near_match && !match)
continue; //only near-match once
StringName r = t->get_message(p_message); StringName r = t->get_message(p_message);
@ -1054,43 +1059,38 @@ StringName TranslationServer::translate(const StringName &p_message) const {
res = r; res = r;
if (match) if (exact_match)
break; break;
else else
near_match = true; near_match = true;
} }
if (!res) { if (!res && fallback.length() >= 2) {
//try again with fallback // Try again with the fallback locale.
if (fallback.length() >= 2) { const CharType *fptr = &fallback[0];
near_match = false;
for (const Set<Ref<Translation> >::Element *E = translations.front(); E; E = E->next()) {
const CharType *fptr = &fallback[0]; const Ref<Translation> &t = E->get();
near_match = false; String l = t->get_locale();
for (const Set<Ref<Translation> >::Element *E = translations.front(); E; E = E->next()) { if (fptr[0] != l[0] || fptr[1] != l[1])
continue; // Language code does not match.
const Ref<Translation> &t = E->get(); bool exact_match = (l == fallback);
String l = t->get_locale(); if (!exact_match && near_match)
if (fptr[0] != l[0] || fptr[1] != l[1]) continue; // Only near-match once, but keep looking for exact matches.
continue; // locale not match
//near match StringName r = t->get_message(p_message);
bool match = (l != fallback);
if (near_match && !match) if (!r)
continue; //only near-match once continue;
StringName r = t->get_message(p_message); res = r;
if (!r) if (exact_match)
continue; break;
else
res = r; near_match = true;
if (match)
break;
else
near_match = true;
}
} }
} }