QTranslator: rewrite loadLocale test, include failing cases
Add test coverage for the bug reported in QTBUG-124898 with QEXPECT_FAIL to document the failure in our truncation logic in QTranslator. The attempted fix in 9a11273b745a30cebb5cd648c89eb224e9704492 then introduced QTBUG-129434, as we ignored the order of languages reported by the system locale. Add a test case for that, and use a QSystemLocale subclass inspired by the QLocale unit test to override the system locale with a specific one that supports multiple languages for this test. Pick-to: 6.5 Task-number: QTBUG-124898 Task-number: QTBUG-129434 Change-Id: Iaae80d29e267fd3a2d14df0e73db27ba4c58b31a Reviewed-by: Thiago Macieira <thiago.macieira@intel.com> Reviewed-by: Edward Welbourne <edward.welbourne@qt.io> (cherry picked from commit 1f2ab46745af12e4776695c1b1a2523ac170368e) Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
This commit is contained in:
parent
c9d31c70d8
commit
34a41d83d8
@ -18,6 +18,8 @@ endif()
|
|||||||
qt_internal_add_test(tst_qtranslator
|
qt_internal_add_test(tst_qtranslator
|
||||||
SOURCES
|
SOURCES
|
||||||
tst_qtranslator.cpp
|
tst_qtranslator.cpp
|
||||||
|
LIBRARIES
|
||||||
|
Qt::CorePrivate
|
||||||
)
|
)
|
||||||
|
|
||||||
# Resources:
|
# Resources:
|
||||||
|
@ -9,10 +9,55 @@
|
|||||||
#include <qfile.h>
|
#include <qfile.h>
|
||||||
#include <qtemporarydir.h>
|
#include <qtemporarydir.h>
|
||||||
|
|
||||||
|
#include <QtCore/private/qlocale_p.h>
|
||||||
|
|
||||||
#ifdef Q_OS_ANDROID
|
#ifdef Q_OS_ANDROID
|
||||||
#include <QDirIterator>
|
#include <QDirIterator>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if !defined(QT_NO_SYSTEMLOCALE) && defined(QT_BUILD_INTERNAL)
|
||||||
|
// from tst_qlocale.cpp; override the system locale with one that supports multiple
|
||||||
|
// languages
|
||||||
|
class MySystemLocale : public QSystemLocale
|
||||||
|
{
|
||||||
|
Q_DISABLE_COPY_MOVE(MySystemLocale)
|
||||||
|
public:
|
||||||
|
MySystemLocale(const QStringList &languages)
|
||||||
|
: m_languages(languages), m_locale(languages.first())
|
||||||
|
, m_id(QLocaleId::fromName(languages.first()))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
QVariant query(QueryType type, QVariant &&/*in*/) const override
|
||||||
|
{
|
||||||
|
switch (type) {
|
||||||
|
case UILanguages:
|
||||||
|
return QVariant(m_languages);
|
||||||
|
case LanguageId:
|
||||||
|
return m_id.language_id;
|
||||||
|
case TerritoryId:
|
||||||
|
return m_id.territory_id;
|
||||||
|
case ScriptId:
|
||||||
|
return m_id.script_id;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return QVariant();
|
||||||
|
}
|
||||||
|
|
||||||
|
QLocale fallbackLocale() const override
|
||||||
|
{
|
||||||
|
return m_locale;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
QStringList m_languages;
|
||||||
|
const QLocale m_locale;
|
||||||
|
const QLocaleId m_id;
|
||||||
|
};
|
||||||
|
#endif // !defined(QT_NO_SYSTEMLOCALE) && defined(QT_BUILD_INTERNAL)
|
||||||
|
|
||||||
class tst_QTranslator : public QObject
|
class tst_QTranslator : public QObject
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
@ -27,6 +72,7 @@ private slots:
|
|||||||
|
|
||||||
void load_data();
|
void load_data();
|
||||||
void load();
|
void load();
|
||||||
|
void loadLocale_data();
|
||||||
void loadLocale();
|
void loadLocale();
|
||||||
void threadLoad();
|
void threadLoad();
|
||||||
void testLanguageChange();
|
void testLanguageChange();
|
||||||
@ -116,12 +162,40 @@ void tst_QTranslator::load()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void tst_QTranslator::loadLocale_data()
|
||||||
|
{
|
||||||
|
QTest::addColumn<QLocale>("wantedLocale");
|
||||||
|
QTest::addColumn<QStringList>("languages");
|
||||||
|
|
||||||
|
// variation of translation files for the same language
|
||||||
|
QTest::addRow("US English")
|
||||||
|
<< QLocale("en-US")
|
||||||
|
<< QStringList{"en-US", "en"};
|
||||||
|
QTest::addRow("Australia")
|
||||||
|
<< QLocale("en-AU")
|
||||||
|
<< QStringList{"en-Latn-AU", "en-AU", "en"};
|
||||||
|
|
||||||
|
// This produces a QLocale::uiLanguages list of
|
||||||
|
// {"en-NO", "en-Latn-NO", "nb-NO", "nb-Latn-NO", "nb",
|
||||||
|
// "de-DE", "de-Latn-DE", "de", "zh-Hant-NO"}
|
||||||
|
QTest::addRow("System, mixed languages")
|
||||||
|
<< QLocale::system()
|
||||||
|
<< QStringList{"en-NO", "nb-NO", "de-DE", "zh-Hant-NO"};
|
||||||
|
}
|
||||||
|
|
||||||
void tst_QTranslator::loadLocale()
|
void tst_QTranslator::loadLocale()
|
||||||
{
|
{
|
||||||
QLocale locale;
|
QFETCH(const QLocale, wantedLocale);
|
||||||
auto localeName = locale.uiLanguages(QLocale::TagSeparator::Underscore).value(0);
|
QFETCH(const QStringList, languages);
|
||||||
if (localeName.isEmpty())
|
|
||||||
QSKIP("This test requires at least one available UI language.");
|
#if !defined(QT_NO_SYSTEMLOCALE) && defined(QT_BUILD_INTERNAL)
|
||||||
|
std::unique_ptr<MySystemLocale> systemLocaleOverride;
|
||||||
|
if (wantedLocale == QLocale::system())
|
||||||
|
systemLocaleOverride.reset(new MySystemLocale(languages));
|
||||||
|
#else
|
||||||
|
if (wantedLocale == QLocale::system())
|
||||||
|
QSKIP("Test only applicable in developer builds with system locale");
|
||||||
|
#endif
|
||||||
|
|
||||||
QByteArray ba;
|
QByteArray ba;
|
||||||
{
|
{
|
||||||
@ -134,36 +208,20 @@ void tst_QTranslator::loadLocale()
|
|||||||
QTemporaryDir dir;
|
QTemporaryDir dir;
|
||||||
QVERIFY(dir.isValid());
|
QVERIFY(dir.isValid());
|
||||||
|
|
||||||
auto path = dir.path();
|
const auto path = dir.path();
|
||||||
QFile file(path + "/dummy");
|
QFile file(path + "/dummy");
|
||||||
QVERIFY2(file.open(QFile::WriteOnly), qPrintable(file.errorString()));
|
QVERIFY2(file.open(QFile::WriteOnly), qPrintable(file.errorString()));
|
||||||
QCOMPARE(file.write(ba), ba.size());
|
QCOMPARE(file.write(ba), ba.size());
|
||||||
file.close();
|
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;
|
QStringList files;
|
||||||
while (true) {
|
for (auto language : languages) {
|
||||||
files.append(path + "/foo-" + localeName + ".qm");
|
language.replace('-', '_');
|
||||||
|
const QString filename = path + "/foo-" + language;
|
||||||
|
files.append(filename + ".qm");
|
||||||
QVERIFY2(file.copy(files.last()), qPrintable(file.errorString()));
|
QVERIFY2(file.copy(files.last()), qPrintable(file.errorString()));
|
||||||
|
files.append(filename);
|
||||||
files.append(path + "/foo-" + localeName);
|
|
||||||
QVERIFY2(file.copy(files.last()), qPrintable(file.errorString()));
|
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");
|
files.append(path + "/foo.qm");
|
||||||
@ -175,9 +233,37 @@ void tst_QTranslator::loadLocale()
|
|||||||
files.append(path + "/foo");
|
files.append(path + "/foo");
|
||||||
QVERIFY2(file.rename(files.last()), qPrintable(file.errorString()));
|
QVERIFY2(file.rename(files.last()), qPrintable(file.errorString()));
|
||||||
|
|
||||||
|
// Verify that all files exist. They are removed at the latest when
|
||||||
|
// the temporary directory is destroyed.
|
||||||
|
for (const auto &filePath : files)
|
||||||
|
QVERIFY(QFile::exists(filePath));
|
||||||
|
|
||||||
|
const QRegularExpression localeExpr("foo-(.*)(\\.qm|$)");
|
||||||
QTranslator tor;
|
QTranslator tor;
|
||||||
|
// Load the translation for the wanted locale
|
||||||
|
QVERIFY(tor.load(wantedLocale, "foo", "-", path, ".qm"));
|
||||||
|
// The loaded translation file should be for the preferred language.
|
||||||
|
const QFileInfo fileInfo(tor.filePath());
|
||||||
|
const auto matches = localeExpr.match(fileInfo.fileName());
|
||||||
|
QVERIFY(matches.hasMatch());
|
||||||
|
QVERIFY(matches.hasCaptured(1));
|
||||||
|
const QLocale matchedLocale(matches.captured(1));
|
||||||
|
QCOMPARE(matchedLocale.language(), wantedLocale.language());
|
||||||
|
|
||||||
|
// Remove one file at a time, and verify that QTranslator falls back to the
|
||||||
|
// more general alternatives, or to languages with lower priority.
|
||||||
for (const auto &filePath : files) {
|
for (const auto &filePath : files) {
|
||||||
QVERIFY(tor.load(locale, "foo", "-", path, ".qm"));
|
QVERIFY(tor.load(wantedLocale, "foo", "-", path, ".qm"));
|
||||||
|
// we search 'en_Latn_US/AU', 'en_Latn', and 'en', but never 'en_US/AU'
|
||||||
|
if (filePath.endsWith("en_US") || filePath.endsWith("en_US.qm")) {
|
||||||
|
QEXPECT_FAIL("US English",
|
||||||
|
"QTBUG-124898 - we search 'en_Latn_US', 'en_Latn', and 'en', but never 'en_US",
|
||||||
|
Continue);
|
||||||
|
} else if (filePath.endsWith("en_AU") || filePath.endsWith("en_AU.qm")) {
|
||||||
|
QEXPECT_FAIL("Australia",
|
||||||
|
"QTBUG-124898 - we search 'en_Latn_AU', 'en_Latn', and 'en', but never 'en_AU",
|
||||||
|
Continue);
|
||||||
|
}
|
||||||
QCOMPARE(tor.filePath(), filePath);
|
QCOMPARE(tor.filePath(), filePath);
|
||||||
QVERIFY2(file.remove(filePath), qPrintable(file.errorString()));
|
QVERIFY2(file.remove(filePath), qPrintable(file.errorString()));
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user