diff options
author | Ivan Solovev <ivan.solovev@qt.io> | 2022-04-05 10:53:06 +0200 |
---|---|---|
committer | Ivan Solovev <ivan.solovev@qt.io> | 2022-04-10 21:30:23 +0200 |
commit | a2704c342121d0118e27655e228ddae7fb36b6cd (patch) | |
tree | cb01b599fc3778691bf92d6690a2f5c18b31cc97 | |
parent | 4cb27786be86694e56150291170c338ab2450c13 (diff) |
Android: use BCP 47 tag to create a correct Locale for QTimeZone::displayName()
Before the patch we tried to create a java Locale object by passing the
human-readable language, territory and variant strings. However, the
Locale constructor accepts ISO-defined codes.
Fix it by using a factory method Locale.forLanguageTag() [0] that
constructs a Java Locale object based on BCP 47 tag.
[0]: https://developer.android.com/reference/java/util/Locale#forLanguageTag(java.lang.String)
Fixes: QTBUG-101460
Change-Id: If414c66cf0e5b7e8299ffc3a6038b6f9eb79d5ec
Reviewed-by: Edward Welbourne <edward.welbourne@qt.io>
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
Reviewed-by: Assam Boudjelthia <assam.boudjelthia@qt.io>
(cherry picked from commit 44f3fe1cf4e2319e012207eba3afe7adfe09cad6)
-rw-r--r-- | src/corelib/time/qtimezoneprivate_android.cpp | 15 | ||||
-rw-r--r-- | tests/auto/corelib/time/qtimezone/tst_qtimezone.cpp | 51 |
2 files changed, 55 insertions, 11 deletions
diff --git a/src/corelib/time/qtimezoneprivate_android.cpp b/src/corelib/time/qtimezoneprivate_android.cpp index 9ba6f58072..3829ff3bb5 100644 --- a/src/corelib/time/qtimezoneprivate_android.cpp +++ b/src/corelib/time/qtimezoneprivate_android.cpp @@ -88,17 +88,10 @@ QAndroidTimeZonePrivate::~QAndroidTimeZonePrivate() static QString getDisplayName(QJniObject zone, jint style, jboolean dst, const QLocale &locale) { - QJniObject jlanguage - = QJniObject::fromString(QLocale::languageToString(locale.language())); - QJniObject jterritory - = QJniObject::fromString(QLocale::territoryToString(locale.territory())); - QJniObject - jvariant = QJniObject::fromString(QLocale::scriptToString(locale.script())); - QJniObject jlocale("java.util.Locale", - "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V", - jlanguage.object<jstring>(), - jterritory.object<jstring>(), - jvariant.object<jstring>()); + QJniObject jbcpTag = QJniObject::fromString(locale.bcp47Name()); + QJniObject jlocale = QJniObject::callStaticObjectMethod( + "java/util/Locale", "forLanguageTag", "(Ljava/lang/String;)Ljava/util/Locale;", + jbcpTag.object<jstring>()); return zone.callObjectMethod("getDisplayName", "(ZILjava/util/Locale;)Ljava/lang/String;", diff --git a/tests/auto/corelib/time/qtimezone/tst_qtimezone.cpp b/tests/auto/corelib/time/qtimezone/tst_qtimezone.cpp index 12370f9e14..c4a7c3cf33 100644 --- a/tests/auto/corelib/time/qtimezone/tst_qtimezone.cpp +++ b/tests/auto/corelib/time/qtimezone/tst_qtimezone.cpp @@ -75,6 +75,8 @@ private Q_SLOTS: void macTest(); void darwinTypes(); void winTest(); + void localeSpecificDisplayName_data(); + void localeSpecificDisplayName(); private: void printTimeZone(const QTimeZone &tz); @@ -1450,6 +1452,55 @@ void tst_QTimeZone::winTest() #endif // QT_BUILD_INTERNAL && USING_WIN_TZ } +void tst_QTimeZone::localeSpecificDisplayName_data() +{ +#ifdef USING_WIN_TZ + QSKIP("MS backend does not use locale parameter"); +#endif + QTest::addColumn<QByteArray>("zoneName"); + QTest::addColumn<QLocale>("locale"); + QTest::addColumn<QTimeZone::TimeType>("timeType"); + QTest::addColumn<QString>("expectedName"); + + QStringList names; + QLocale locale; + // Pick a non-system locale; German or French + if (QLocale::system().language() != QLocale::German) { + locale = QLocale(QLocale::German); + names << QString("Mitteleurop\u00e4ische Normalzeit") + << QString("Mitteleurop\u00e4ische Sommerzeit"); + } else { + locale = QLocale(QLocale::French); + names << QString("heure normale d\u2019Europe centrale") + << QString("heure d\u2019\u00E9t\u00E9 d\u2019Europe centrale"); + } + + qsizetype index = 0; + QTest::newRow("Berlin, standard time") + << QByteArray("Europe/Berlin") << locale << QTimeZone::StandardTime + << names.at(index++); + + QTest::newRow("Berlin, summer time") + << QByteArray("Europe/Berlin") << locale << QTimeZone::DaylightTime + << names.at(index++); +} + +void tst_QTimeZone::localeSpecificDisplayName() +{ + // This test checks that QTimeZone::displayName() correctly uses the + // specified locale, NOT the system locale (see QTBUG-101460). + QFETCH(QByteArray, zoneName); + QFETCH(QLocale, locale); + QFETCH(QTimeZone::TimeType, timeType); + QFETCH(QString, expectedName); + + QTimeZone zone(zoneName); + QVERIFY(zone.isValid()); + + const QString localeName = zone.displayName(timeType, QTimeZone::LongName, locale); + QCOMPARE(localeName, expectedName); +} + #ifdef QT_BUILD_INTERNAL // Test each private produces the same basic results for CET void tst_QTimeZone::testCetPrivate(const QTimeZonePrivate &tzp) |