Correct initialization of justAfter in QLocale::uiLanguages()

It's used to determine whether a non-equivalent prefix of a locale
gets added at the end of the block of equivalent locales, or at the
very end of the list. Thus it should be initialized for each prefix as
it is processed, not before the name is trimmed to its first prefix.

Added the test-case that caught this.
Amends commit cbf49f735e3cca85922a85d6548666816686db78

This should work as-is in 6.9 but may be hard to back-port to 6.8.
None the less, I shall try for the latter, too.

Pick-to: 6.8
Task-number: QTBUG-131894
Change-Id: I75ab27153133d2608cf57f0bc998c1e3d0d1432c
Reviewed-by: Mate Barany <mate.barany@qt.io>
Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io>
(cherry picked from commit 0278a80d6876f38bb37f1d504e6b24a3512efb7a)
Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
This commit is contained in:
Edward Welbourne 2025-04-24 14:55:46 +02:00 committed by Qt Cherry-pick Bot
parent 9e1cfb6ad9
commit b5b172e34f
2 changed files with 25 additions and 11 deletions

View File

@ -5209,23 +5209,24 @@ QStringList QLocale::uiLanguages(TagSeparator separator) const
qsizetype stopAt = uiLanguages.size();
QString prefix = entry;
qsizetype at = 0;
/* By default we append but if no later entry has this as a prefix and
the locale it implies would use the same script as entry, put it
after the block of consecutive equivalents of which entry is a part
instead. Thus [en-NL, nl-NL, en-GB] will append en but [en-NL, en-GB,
nl-NL] will put it before nl-NL, for example. We require a script
match so we don't pick translations that the user cannot read,
despite knowing the language. (Ideally that would be a constraint the
caller can opt into / out of. See QTBUG-112765.)
*/
bool justAfter
= QLocaleId::fromName(prefix).withLikelySubtagsAdded().script_id == max.script_id;
while ((at = prefix.lastIndexOf(cut)) > 0) {
prefix = prefix.first(at);
// Don't test with hasSeen() as we might defer adding to later, when
// we'll need known to see the later entry's offering of this prefix
// as a new entry.
bool found = known.contains(prefix);
/* By default we append but if no later entry has this as a prefix
and the locale it implies would use the same script as entry, put
it after the block of consecutive equivalents of which entry is a
part instead. Thus [en-NL, nl-NL, en-GB] will append en but
[en-NL, en-GB, nl-NL] will put it before nl-NL, for example. We
require a script match so we don't pick translations that the
user cannot read, despite knowing the language. (Ideally that
would be a constraint the caller can opt into / out of. See
QTBUG-112765.)
*/
bool justAfter
= (QLocaleId::fromName(prefix).withLikelySubtagsAdded().script_id == max.script_id);
for (qsizetype j = afterTruncs; !found && j < stopAt; ++j) {
QString later = uiLanguages.at(j);
if (!later.startsWith(prefix)) {

View File

@ -4175,6 +4175,8 @@ public:
return QVariant(QStringList{u"en-CA"_s, u"fr-CA"_s, u"de-AT"_s,
u"en-GB"_s, u"fr-FR"_s});
}
if (m_name == u"pa-Arab-GB") // Pakistani Punjabi in Britain
return QVariant(QStringList{u"pa-PK"_s, u"en-GB"_s});
if (m_name == u"no") // QTBUG-131127
return QVariant(QStringList{u"no"_s, u"en-US"_s, u"nb"_s});
if (m_name == u"no-US") // Empty query result:
@ -4300,6 +4302,17 @@ void tst_QLocale::mySystemLocale_data()
QTest::addRow("C-Hans-CN")
<< u"C-Hans-CN"_s << QLocale::C << QStringList{u"C-Hans-CN"_s, u"C"_s};
QTest::addRow("pa-Arab-GB")
<< u"pa-Arab-GB"_s << QLocale::Punjabi
<< QStringList{u"pa-Arab-GB"_s, u"pa-Arab-PK"_s, u"pa-PK"_s, u"pa-Arab"_s,
u"en-Latn-GB"_s, u"en-GB"_s,
// Truncations:
u"en-Latn"_s, u"en"_s,
// Last because its implied script, Guru, doesn't match the Arab
// implied by the entry that it's derived from, pa-PK - in contrast
// to en-Latn and en.
u"pa"_s};
QTest::newRow("en-Dsrt-GB")
<< u"en-Dsrt-GB"_s << QLocale::English
<< QStringList{u"en-Dsrt-GB"_s, u"en-Dsrt"_s,