Skip to content

Commit

Permalink
Revert "QTranslator: fix loading order when loading from locale"
Browse files Browse the repository at this point in the history
This reverts commit 9a11273.

Reason for revert: The fix tried to find a sensible order if
the same language is listed multiple times in QLocale::uiLanguages().
Anyhow, it breaks for lists where entirely different languages are listed. This needs more thought.

Fixes: QTBUG-129434
Pick-to: 6.8 6.7 6.5
Change-Id: I8c074cbf1ddc2ddf223ec09aef38dfc1ef7fc85f
Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io>
(cherry picked from commit f3fc7b2)
Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
  • Loading branch information
kkoehne authored and Qt Cherry-pick Bot committed Oct 1, 2024
1 parent 268006e commit a30c1bc
Show file tree
Hide file tree
Showing 2 changed files with 43 additions and 55 deletions.
46 changes: 15 additions & 31 deletions src/corelib/kernel/qtranslator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -638,41 +638,25 @@ static QString find_translation(const QLocale & locale,
languages.insert(i + 1, lowerLang);
}

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 (QString localeName : std::as_const(languages)) {
// try the complete locale name first and progressively truncate from
// the end until a matching language tag is found (with or without suffix)
for (;;) {
candidates += language.toString();
int rightmost = language.lastIndexOf(u'_');
if (rightmost <= 0)
break;
language.truncate(rightmost);
}
}
realname += localeName + suffixOrDotQM;
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 + localeName.size());
if (is_readable_file(realname))
return realname;

realname.truncate(realNameBaseSize + localeName.size());
if (is_readable_file(realname))
return realname;
realname.truncate(realNameBaseSize);

realname.truncate(realNameBaseSize);
int rightmost = localeName.lastIndexOf(u'_');
if (rightmost <= 0)
break; // no truncations anymore, break
localeName.truncate(rightmost);
}
}

const int realNameBaseSizeFallbacks = path.size() + filename.size();
Expand Down
52 changes: 28 additions & 24 deletions tests/auto/corelib/kernel/qtranslator/tst_qtranslator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@ private slots:

void load_data();
void load();
void loadLocale_data();
void loadLocale();
void threadLoad();
void testLanguageChange();
Expand Down Expand Up @@ -117,23 +116,12 @@ void tst_QTranslator::load()
}
}

void tst_QTranslator::loadLocale_data()
{
QTest::addColumn<QString>("localeName");
QTest::addColumn<QStringList>("fileNames");

QTest::addRow("US English")
<< "en_US"
<< QStringList{"en_US.qm", "en_US", "en.qm", "en"};
QTest::addRow("Australia")
<< "en_AU"
<< QStringList{"en_Latn_AU.qm", "en_AU.qm", "en.qm"};
}

void tst_QTranslator::loadLocale()
{
QFETCH(const QString, localeName);
QFETCH(const QStringList, fileNames);
QLocale locale;
auto localeName = locale.uiLanguages(QLocale::TagSeparator::Underscore).value(0);
if (localeName.isEmpty())
QSKIP("This test requires at least one available UI language.");

QByteArray ba;
{
Expand All @@ -146,16 +134,36 @@ void tst_QTranslator::loadLocale()
QTemporaryDir dir;
QVERIFY(dir.isValid());

const auto path = dir.path();
auto path = dir.path();
QFile file(path + "/dummy");
QVERIFY2(file.open(QFile::WriteOnly), qPrintable(file.errorString()));
QCOMPARE(file.write(ba), ba.size());
file.close();

/*
Test the following order:
/tmp/tmpDir/foo-en_US.qm
/tmp/tmpDir/foo-en_US
/tmp/tmpDir/foo-en.qm
/tmp/tmpDir/foo-en
/tmp/tmpDir/foo.qm
/tmp/tmpDir/foo-
/tmp/tmpDir/foo
*/

QStringList files;
for (const auto &fileName : fileNames) {
files.append(path + "/foo-" + fileName);
while (true) {
files.append(path + "/foo-" + localeName + ".qm");
QVERIFY2(file.copy(files.last()), qPrintable(file.errorString()));

files.append(path + "/foo-" + localeName);
QVERIFY2(file.copy(files.last()), qPrintable(file.errorString()));

int rightmost = localeName.lastIndexOf(QLatin1Char('_'));
if (rightmost <= 0)
break;
localeName.truncate(rightmost);
}

files.append(path + "/foo.qm");
Expand All @@ -167,14 +175,10 @@ void tst_QTranslator::loadLocale()
files.append(path + "/foo");
QVERIFY2(file.rename(files.last()), qPrintable(file.errorString()));

QLocale locale(localeName);
QTranslator tor;
for (const auto &filePath : files) {
QVERIFY(tor.load(locale, "foo", "-", path, ".qm"));
// As the file system might be case insensitive, we can't guarantee that
// the casing of the file name is preserved. The order of loading
// en_AU vs en_au if both exist is undefined anyway.
QCOMPARE(tor.filePath().toLower(), filePath.toLower());
QCOMPARE(tor.filePath(), filePath);
QVERIFY2(file.remove(filePath), qPrintable(file.errorString()));
}
}
Expand Down

0 comments on commit a30c1bc

Please sign in to comment.