Return more specific entries before less in QLocale::uiLanguages()

The documentation overtly listed entries in this order but the code
gave less specific entries before more specific (and the tests
verified the same). This is now reversed.

[ChangeLog][QtCore][QLocale] uiLanguages() now prefers more specific
locale names over less specific ones, matching its own documentation,
except where the system backend supplies them in some other order.
This means a translation with the expected script and/or territory as
well as language will be used in preference to a generic one for just
the language, rather than only as a fall-back when the more generic
one is missing.

Fixes: QTBUG-102796
Change-Id: I3c7b3627afb51246df5a6ad0230e23b60af78071
Reviewed-by: Mårten Nordheim <marten.nordheim@qt.io>
This commit is contained in:
Edward Welbourne 2022-04-22 14:43:26 +02:00
parent bf96f0eea0
commit 7a7f2547f3
2 changed files with 29 additions and 24 deletions

View File

@ -4424,10 +4424,10 @@ QString QLocale::formattedDataSize(qint64 bytes, int precision, DataSizeFormats
The return value represents locale names that the user expects to see the
UI translation in.
Most like you do not need to use this function directly, but just pass the
Most likely you do not need to use this function directly, but just pass the
QLocale object to the QTranslator::load() function.
The first item in the list is the most preferred one.
Earlier items in the list are to be preferred over later ones.
\sa QTranslator, bcp47Name()
*/
@ -4435,8 +4435,11 @@ QStringList QLocale::uiLanguages() const
{
QStringList uiLanguages;
QList<QLocale> locales;
#ifndef QT_NO_SYSTEMLOCALE
if (d->m_data == &systemLocaleData) {
#ifdef QT_NO_SYSTEMLOCALE
constexpr bool isSystem = false;
#else
const bool isSystem = d->m_data == &systemLocaleData;
if (isSystem) {
uiLanguages = systemLocale()->query(QSystemLocale::UILanguages).toStringList();
// ... but we need to include likely-adjusted forms of each of those, too:
for (const auto &entry : std::as_const(uiLanguages))
@ -4455,7 +4458,7 @@ QStringList QLocale::uiLanguages() const
int j;
QByteArray prior;
if (i < uiLanguages.size()) {
if (isSystem && i < uiLanguages.size()) {
// Adding likely-adjusted forms to system locale's list.
// Name the locale is derived from:
prior = uiLanguages.at(i).toLatin1();
@ -4466,7 +4469,7 @@ QStringList QLocale::uiLanguages() const
uiLanguages.append(locale.name());
continue;
} else {
// Plain locale, not system locale; just append.
// Plain locale or empty system uiLanguages; just append.
const QString name = locale.bcp47Name();
uiLanguages.append(name);
prior = name.toLatin1();
@ -4477,9 +4480,11 @@ QStringList QLocale::uiLanguages() const
const QLocaleId min = max.withLikelySubtagsRemoved();
id.script_id = 0; // For re-use as script-less variant.
// Include version with all likely sub-tags (last) if distinct from the rest:
if (max != min && max != id && max.name() != prior)
uiLanguages.insert(j, QString::fromLatin1(max.name()));
// Include minimal version (last) unless it's what our locale is derived from:
if (min.name() != prior)
uiLanguages.insert(j, QString::fromLatin1(min.name()));
else if (!isSystem)
--j; // bcp47Name() matches min(): put more specific forms *before* it.
// Include scriptless version if likely-equivalent and distinct:
if (data->m_script_id && id != min && id.name() != prior
@ -4487,9 +4492,9 @@ QStringList QLocale::uiLanguages() const
uiLanguages.insert(j, QString::fromLatin1(id.name()));
}
// Include minimal version (first) unless it's what our locale is derived from:
if (min.name() != prior)
uiLanguages.insert(j, QString::fromLatin1(min.name()));
// Include version with all likely sub-tags (first) if distinct from the rest:
if (max != min && max != id && max.name() != prior)
uiLanguages.insert(j, QString::fromLatin1(max.name()));
}
return uiLanguages;
}

View File

@ -2937,31 +2937,31 @@ void tst_QLocale::uiLanguages_data()
QTest::newRow("en_US")
<< QLocale("en_US")
<< QStringList{QString("en"), QString("en-US"), QString("en-Latn-US")};
<< QStringList{QString("en-Latn-US"), QString("en-US"), QString("en")};
QTest::newRow("en_Latn_US")
<< QLocale("en_Latn_US") // Specifying the default script makes no difference
<< QStringList{QString("en"), QString("en-US"), QString("en-Latn-US")};
<< QStringList{QString("en-Latn-US"), QString("en-US"), QString("en")};
QTest::newRow("en_GB")
<< QLocale("en_GB")
<< QStringList{QString("en-GB"), QString("en-Latn-GB")};
<< QStringList{QString("en-Latn-GB"), QString("en-GB")};
QTest::newRow("en_Dsrt_US")
<< QLocale("en_Dsrt_US")
<< QStringList{QString("en-Dsrt"), QString("en-Dsrt-US")};
<< QStringList{QString("en-Dsrt-US"), QString("en-Dsrt")};
QTest::newRow("ru_RU")
<< QLocale("ru_RU")
<< QStringList{QString("ru"), QString("ru-RU"), QString("ru-Cyrl-RU")};
<< QStringList{QString("ru-Cyrl-RU"), QString("ru-RU"), QString("ru")};
QTest::newRow("zh_Hant")
<< QLocale("zh_Hant")
<< QStringList{QString("zh-TW"), QString("zh-Hant-TW")};
<< QStringList{QString("zh-Hant-TW"), QString("zh-TW")};
QTest::newRow("zh_Hans_CN")
<< QLocale(QLocale::Chinese, QLocale::SimplifiedHanScript, QLocale::China)
<< QStringList{QString("zh"), QString("zh-CN"), QString("zh-Hans-CN")};
<< QStringList{QString("zh-Hans-CN"), QString("zh-CN"), QString("zh")};
}
void tst_QLocale::uiLanguages()
@ -3281,19 +3281,19 @@ void tst_QLocale::systemLocale_data()
QTest::addRow("catalan")
<< QString("ca") << QLocale::Catalan
<< QStringList{QStringLiteral("ca"), QStringLiteral("ca-ES"), QStringLiteral("ca-Latn-ES")};
<< QStringList{QStringLiteral("ca"), QStringLiteral("ca-Latn-ES"), QStringLiteral("ca-ES")};
QTest::addRow("ukrainian")
<< QString("uk") << QLocale::Ukrainian
<< QStringList{QStringLiteral("uk"), QStringLiteral("uk-UA"), QStringLiteral("uk-Cyrl-UA")};
<< QStringList{QStringLiteral("uk"), QStringLiteral("uk-Cyrl-UA"), QStringLiteral("uk-UA")};
QTest::addRow("german")
<< QString("de") << QLocale::German
<< QStringList{QStringLiteral("de"), QStringLiteral("de-DE"), QStringLiteral("de-Latn-DE")};
<< QStringList{QStringLiteral("de"), QStringLiteral("de-Latn-DE"), QStringLiteral("de-DE")};
QTest::addRow("chinese-min")
<< QString("zh") << QLocale::Chinese
<< QStringList{QStringLiteral("zh"), QStringLiteral("zh-CN"), QStringLiteral("zh-Hans-CN")};
<< QStringList{QStringLiteral("zh"), QStringLiteral("zh-Hans-CN"), QStringLiteral("zh-CN")};
QTest::addRow("chinese-full")
<< QString("zh-Hans-CN") << QLocale::Chinese
<< QStringList{QStringLiteral("zh-Hans-CN"), QStringLiteral("zh"), QStringLiteral("zh-CN")};
<< QStringList{QStringLiteral("zh-Hans-CN"), QStringLiteral("zh-CN"), QStringLiteral("zh")};
}
void tst_QLocale::systemLocale()