[Scummvm-cvs-logs] SF.net SVN: scummvm:[54715] scummvm/trunk/common

jvprat at users.sourceforge.net jvprat at users.sourceforge.net
Wed Dec 1 21:00:40 CET 2010


Revision: 54715
          http://scummvm.svn.sourceforge.net/scummvm/?rev=54715&view=rev
Author:   jvprat
Date:     2010-12-01 20:00:40 +0000 (Wed, 01 Dec 2010)

Log Message:
-----------
I18N: Improve the fallback language auto-detection.

- Broaden the range of language tags that could be accepted as fallback in
  auto-detection. For example, for a system with locale 'pt_PT', all of
  these would be accepted as valid fallbacks: 'pt_PT_*', 'pt', 'pt_*'
- Make language codes matching case-insensitive as specified in RFC 4647.
- Add support language code blocks longer than 2 characters.

Modified Paths:
--------------
    scummvm/trunk/common/translation.cpp
    scummvm/trunk/common/translation.h

Modified: scummvm/trunk/common/translation.cpp
===================================================================
--- scummvm/trunk/common/translation.cpp	2010-12-01 19:57:23 UTC (rev 54714)
+++ scummvm/trunk/common/translation.cpp	2010-12-01 20:00:40 UTC (rev 54715)
@@ -51,8 +51,6 @@
 TranslationManager::TranslationManager() : _currentLang(-1) {
 	loadTranslationsInfoDat();
 
-	_syslang = g_system->getSystemLanguage();
-
 	// Set the default language
 	setLanguage("");
 }
@@ -60,27 +58,52 @@
 TranslationManager::~TranslationManager() {
 }
 
+int32 TranslationManager::findMatchingLanguage(const String &lang) {
+	uint langLength = lang.size();
+	uint numLangs = _langs.size();
+
+	// Try to match languages of the same length or longer ones
+	// that can be cut at the length of the given one.
+	for (uint i = 0; i < numLangs; ++i) {
+		uint iLength = _langs[i].size();
+		if (iLength >= langLength) {
+			// Found a candidate; compare the full string by default.
+			String cmpLang = _langs[i];
+
+			if ((iLength > langLength) && (_langs[i][langLength] == '_')) {
+				// It has a separation mark at the length of the
+				// requested language, so we can cut it.
+				cmpLang = String(_langs[i].c_str(), langLength);
+			}
+			if (lang.equalsIgnoreCase(cmpLang))
+				return i;
+		}
+	}
+
+	// Couldn't find a matching language.
+	return -1;
+}
+
 void TranslationManager::setLanguage(const String &lang) {
-	// Get lang index
+	// Get lang index.
 	int langIndex = -1;
 	String langStr(lang);
 	if (langStr.empty())
-		langStr = _syslang;
+		langStr = g_system->getSystemLanguage();
 
-	// Searching for a valid language
-	for (unsigned int i = 0; i < _langs.size() && langIndex == -1; ++i) {
-		if (langStr == _langs[i])
-			langIndex = i;
-	}
+	// Search for the given language or a variant of it.
+	langIndex = findMatchingLanguage(langStr);
 
-	// Try partial match
-	for (unsigned int i = 0; i < _langs.size() && langIndex == -1; ++i) {
-		if (strncmp(langStr.c_str(), _langs[i].c_str(), 2) == 0)
-			langIndex = i;
+	// Try to find a partial match taking away parts of the original language.
+	const char *lastSep;
+	String langCut(langStr);
+	while ((langIndex == -1) && (lastSep = strrchr(langCut.c_str(), '_'))) {
+		langCut = String(langCut.c_str(), lastSep);
+		langIndex = findMatchingLanguage(langCut);
 	}
 
-	// Load messages for that lang
-	// Call it even if the index is -1 to unload previously loaded translations
+	// Load messages for that language.
+	// Call it even if the index is -1 to unload previously loaded translations.
 	if (langIndex != _currentLang) {
 		loadLanguageDat(langIndex);
 		_currentLang = langIndex;
@@ -92,11 +115,11 @@
 }
 
 const char *TranslationManager::getTranslation(const char *message, const char *context) const {
-	// if no language is set or message is empty, return msgid as is
+	// If no language is set or message is empty, return msgid as is
 	if (_currentTranslationMessages.empty() || *message == '\0')
 		return message;
 
-	// binary-search for the msgid
+	// Binary-search for the msgid
 	int leftIndex = 0;
 	int rightIndex = _currentTranslationMessages.size() - 1;
 
@@ -271,10 +294,10 @@
 	for (int i = 0; i < nbTranslations; ++i) {
 		len = in.readUint16BE();
 		in.read(buf, len);
-		_langs[i] = String(buf, len-1);
+		_langs[i] = String(buf, len - 1);
 		len = in.readUint16BE();
 		in.read(buf, len);
-		_langNames[i] = String(buf, len-1);
+		_langNames[i] = String(buf, len - 1);
 	}
 
 	// Read messages
@@ -283,7 +306,7 @@
 	for (int i = 0; i < numMessages; ++i) {
 		len = in.readUint16BE();
 		in.read(buf, len);
-		_messageIds[i] = String(buf, len-1);
+		_messageIds[i] = String(buf, len - 1);
 	}
 }
 
@@ -331,18 +354,18 @@
 	// Read charset
 	len = in.readUint16BE();
 	in.read(buf, len);
-	_currentCharset = String(buf, len-1);
+	_currentCharset = String(buf, len - 1);
 
 	// Read messages
 	for (int i = 0; i < nbMessages; ++i) {
 		_currentTranslationMessages[i].msgid = in.readUint16BE();
 		len = in.readUint16BE();
 		in.read(buf, len);
-		_currentTranslationMessages[i].msgstr = String(buf, len-1);
+		_currentTranslationMessages[i].msgstr = String(buf, len - 1);
 		len = in.readUint16BE();
 		if (len > 0) {
 			in.read(buf, len);
-			_currentTranslationMessages[i].msgctxt = String(buf, len-1);
+			_currentTranslationMessages[i].msgctxt = String(buf, len - 1);
 		}
 	}
 }

Modified: scummvm/trunk/common/translation.h
===================================================================
--- scummvm/trunk/common/translation.h	2010-12-01 19:57:23 UTC (rev 54714)
+++ scummvm/trunk/common/translation.h	2010-12-01 20:00:40 UTC (rev 54715)
@@ -161,6 +161,15 @@
 
 private:
 	/**
+	 * Tries to find the given language or a derivate of it.
+	 *
+	 * @param lang Language string
+	 * @return id of the language or -1 in case no matching language could
+	 *         be found.
+	 */
+	int32 findMatchingLanguage(const String &lang);
+
+	/**
 	 * Find the translations.dat file. It looks first using the SearchMan and
 	 * then if needed using the Themepath. If found it opens the given File
 	 * to read the translations.dat file.
@@ -190,7 +199,6 @@
 	 */
 	bool checkHeader(File &in);
 
-	String _syslang;
 	StringArray _langs;
 	StringArray _langNames;
 


This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.




More information about the Scummvm-git-logs mailing list