diff options
author | Jordi Vilalta Prat | 2010-12-01 20:00:40 +0000 |
---|---|---|
committer | Jordi Vilalta Prat | 2010-12-01 20:00:40 +0000 |
commit | a17c07bcaa5256acf5777b2d4df90e0c01d38d74 (patch) | |
tree | f1dec4691594ddf39bad902499ae9ba488e9a5c8 /common | |
parent | 1ed5b5b353b476a66992d6849245ba8e129daaaa (diff) | |
download | scummvm-rg350-a17c07bcaa5256acf5777b2d4df90e0c01d38d74.tar.gz scummvm-rg350-a17c07bcaa5256acf5777b2d4df90e0c01d38d74.tar.bz2 scummvm-rg350-a17c07bcaa5256acf5777b2d4df90e0c01d38d74.zip |
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.
svn-id: r54715
Diffstat (limited to 'common')
-rw-r--r-- | common/translation.cpp | 69 | ||||
-rw-r--r-- | common/translation.h | 10 |
2 files changed, 55 insertions, 24 deletions
diff --git a/common/translation.cpp b/common/translation.cpp index 47671b3a8d..407da2c883 100644 --- a/common/translation.cpp +++ b/common/translation.cpp @@ -51,8 +51,6 @@ bool operator<(const TLanguage &l, const TLanguage &r) { TranslationManager::TranslationManager() : _currentLang(-1) { loadTranslationsInfoDat(); - _syslang = g_system->getSystemLanguage(); - // Set the default language setLanguage(""); } @@ -60,27 +58,52 @@ TranslationManager::TranslationManager() : _currentLang(-1) { 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 { } 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 @@ void TranslationManager::loadTranslationsInfoDat() { 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 @@ void TranslationManager::loadTranslationsInfoDat() { 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 @@ void TranslationManager::loadLanguageDat(int index) { // 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); } } } diff --git a/common/translation.h b/common/translation.h index 5587d0eb92..523f2f4de7 100644 --- a/common/translation.h +++ b/common/translation.h @@ -161,6 +161,15 @@ public: 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 @@ private: */ bool checkHeader(File &in); - String _syslang; StringArray _langs; StringArray _langNames; |