Browse Source

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 b33042507bbccacc0b31be4415613a124e18d9ff)
Rémi Verschelde 6 years ago
parent
commit
b45ec12c8c
1 changed files with 32 additions and 32 deletions
  1. 32 32
      core/translation.cpp

+ 32 - 32
core/translation.cpp

@@ -1030,6 +1030,13 @@ StringName TranslationServer::translate(const StringName &p_message) const {
 	if (!enabled)
 		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;
 	bool near_match = false;
 	const CharType *lptr = &locale[0];
@@ -1039,13 +1046,11 @@ StringName TranslationServer::translate(const StringName &p_message) const {
 		const Ref<Translation> &t = E->get();
 		String l = t->get_locale();
 		if (lptr[0] != l[0] || lptr[1] != l[1])
-			continue; // locale not match
-
-		//near match
-		bool match = (l != locale);
+			continue; // Language code does not match.
 
-		if (near_match && !match)
-			continue; //only near-match once
+		bool exact_match = (l == locale);
+		if (!exact_match && near_match)
+			continue; // Only near-match once, but keep looking for exact matches.
 
 		StringName r = t->get_message(p_message);
 
@@ -1054,43 +1059,38 @@ StringName TranslationServer::translate(const StringName &p_message) const {
 
 		res = r;
 
-		if (match)
+		if (exact_match)
 			break;
 		else
 			near_match = true;
 	}
 
-	if (!res) {
-		//try again with fallback
-		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()) {
+	if (!res && fallback.length() >= 2) {
+		// Try again with the fallback locale.
+		const CharType *fptr = &fallback[0];
+		near_match = false;
+		for (const Set<Ref<Translation> >::Element *E = translations.front(); E; E = E->next()) {
 
-				const Ref<Translation> &t = E->get();
-				String l = t->get_locale();
-				if (fptr[0] != l[0] || fptr[1] != l[1])
-					continue; // locale not match
+			const Ref<Translation> &t = E->get();
+			String l = t->get_locale();
+			if (fptr[0] != l[0] || fptr[1] != l[1])
+				continue; // Language code does not match.
 
-				//near match
-				bool match = (l != fallback);
+			bool exact_match = (l == fallback);
+			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);
+			if (!r)
+				continue;
 
-				if (!r)
-					continue;
+			res = r;
 
-				res = r;
-
-				if (match)
-					break;
-				else
-					near_match = true;
-			}
+			if (exact_match)
+				break;
+			else
+				near_match = true;
 		}
 	}