diff options
Diffstat (limited to 'src/corelib/kernel/qtranslator.cpp')
-rw-r--r-- | src/corelib/kernel/qtranslator.cpp | 55 |
1 files changed, 36 insertions, 19 deletions
diff --git a/src/corelib/kernel/qtranslator.cpp b/src/corelib/kernel/qtranslator.cpp index 9f9575f517..5c4ebfedf1 100644 --- a/src/corelib/kernel/qtranslator.cpp +++ b/src/corelib/kernel/qtranslator.cpp @@ -22,7 +22,7 @@ #include "qendian.h" #include "qresource.h" -#if defined(Q_OS_UNIX) && !defined(Q_OS_NACL) && !defined(Q_OS_INTEGRITY) +#if defined(Q_OS_UNIX) && !defined(Q_OS_INTEGRITY) # define QT_USE_MMAP # include "private/qcore_unix_p.h" // for mmap @@ -39,8 +39,11 @@ QT_BEGIN_NAMESPACE +namespace { enum Tag { Tag_End = 1, Tag_SourceText16, Tag_Translation, Tag_Context16, Tag_Obsolete1, Tag_SourceText, Tag_Context, Tag_Comment, Tag_Obsolete2 }; +} + /* $ mcookie 3cb86418caef9c95cd211cbf60a1bddd @@ -627,7 +630,7 @@ static QString find_translation(const QLocale & locale, // "prefix_en_us.qm" won't be found under the "en_US" locale. Note // that the Qt resource system is always case-sensitive, even on // Windows (in other words: this codepath is *not* UNIX-only). - QStringList languages = locale.uiLanguages(); + QStringList languages = locale.uiLanguages(QLocale::TagSeparator::Underscore); for (int i = languages.size()-1; i >= 0; --i) { QString lang = languages.at(i); QString lowerLang = lang.toLower(); @@ -635,27 +638,41 @@ static QString find_translation(const QLocale & locale, languages.insert(i + 1, lowerLang); } - for (QString localeName : std::as_const(languages)) { - localeName.replace(u'-', u'_'); - - // try the complete locale name first and progressively truncate from - // the end until a matching language tag is found (with or without suffix) + QStringList candidates; + // assume 3 segments for each entry + candidates.reserve(languages.size() * 3); + for (QStringView language : std::as_const(languages)) { + // for each language, add versions without territory and script for (;;) { - realname += localeName + suffixOrDotQM; - if (is_readable_file(realname)) - return realname; + candidates += language.toString(); + int rightmost = language.lastIndexOf(u'_'); + if (rightmost <= 0) + break; + language.truncate(rightmost); + } + } - realname.truncate(realNameBaseSize + localeName.size()); - if (is_readable_file(realname)) - return realname; + // now sort the list of candidates + std::sort(candidates.begin(), candidates.end(), [](const auto &lhs, const auto &rhs){ + const auto rhsSegments = rhs.count(u'_'); + const auto lhsSegments = lhs.count(u'_'); + // candidates with more segments come first + if (rhsSegments != lhsSegments) + return rhsSegments < lhsSegments; + // candidates with same number of segments are sorted alphanumerically + return lhs < rhs; + }); + + for (const QString &localeName : std::as_const(candidates)) { + realname += localeName + suffixOrDotQM; + if (is_readable_file(realname)) + return realname; - realname.truncate(realNameBaseSize); + realname.truncate(realNameBaseSize + localeName.size()); + if (is_readable_file(realname)) + return realname; - int rightmost = localeName.lastIndexOf(u'_'); - if (rightmost <= 0) - break; // no truncations anymore, break - localeName.truncate(rightmost); - } + realname.truncate(realNameBaseSize); } const int realNameBaseSizeFallbacks = path.size() + filename.size(); |