diff --git a/src/corelib/text/qlocale.cpp b/src/corelib/text/qlocale.cpp index deac50ced8..fd4fc1ad3d 100644 --- a/src/corelib/text/qlocale.cpp +++ b/src/corelib/text/qlocale.cpp @@ -3839,8 +3839,11 @@ inline QLocaleData::NumericData QLocaleData::numericData(QLocaleData::NumberMode result.plus = plus().viewData(single_character_data); if (mode != IntegerMode) result.decimal = decimalSeparator().viewData(single_character_data); - if (mode == DoubleScientificMode) + if (mode == DoubleScientificMode) { result.exponent = exponential().viewData(single_character_data); + // exponentCyrillic means "apply the Cyrrilic-specific exponent hack" + result.exponentCyrillic = m_script_id == QLocale::CyrillicScript; + } #ifndef QT_NO_SYSTEMLOCALE if (this == &systemLocaleData) { const auto getString = [sys = systemLocale()](QSystemLocale::QueryType query) { @@ -4017,6 +4020,15 @@ char NumericTokenizer::nextToken() return ','; } + // Cyrillic has its own E, used by Ukrainian as exponent; but others + // writing Cyrillic may well use that; and Ukrainians might well use E. + // All other Cyrillic locales (officially) use plain ASCII E. + if (m_guide.exponentCyrillic // Only true in scientific float mode. + && (tail.startsWith(u"\u0415") || tail.startsWith(u"E"))) { + ++m_index; + return 'e'; + } + return 0; } } // namespace with no name diff --git a/src/corelib/text/qlocale_p.h b/src/corelib/text/qlocale_p.h index c7c91fba5a..99b2528633 100644 --- a/src/corelib/text/qlocale_p.h +++ b/src/corelib/text/qlocale_p.h @@ -322,6 +322,7 @@ public: char32_t zeroUcs = 0; qint8 zeroLen = 0; bool isC = false; // C locale sets this and nothing else. + bool exponentCyrillic = false; // True only for floating-point parsing of Cyrillic. void setZero(QStringView zero) { // No known locale has digits that are more than one Unicode @@ -346,6 +347,8 @@ public: { if (isC) return true; + if (exponentCyrillic && exponent != u"E" && exponent != u"\u0415") + return false; return (zeroLen == 1 || zeroLen == 2) && zeroUcs > 0 && (mode == IntegerMode || !decimal.isEmpty()) // group may be empty (user config in system locale) diff --git a/tests/auto/corelib/text/qlocale/tst_qlocale.cpp b/tests/auto/corelib/text/qlocale/tst_qlocale.cpp index 3378446252..194263aacf 100644 --- a/tests/auto/corelib/text/qlocale/tst_qlocale.cpp +++ b/tests/auto/corelib/text/qlocale/tst_qlocale.cpp @@ -910,6 +910,14 @@ void tst_QLocale::toReal_data() << u"fa_IR"_s << u"\u06f4\u00d7\u200e\u2212\u06f0\u06f3"_s << false << 0.0; QTest::newRow("fa_IR 4x!3") // Only first character of exponent and sign << u"fa_IR"_s << u"\u06f4\u00d7\u200e\u06f0\u06f3"_s << false << 0.0; + + // Cyrillic has its own E; only officially used by Ukrainian as exponent, + // with other Cyrillic locales using the Latin E. QLocale allows that there + // may be some cross-over between these. + QTest::newRow("uk_UA Cyrillic E") << u"uk_UA"_s << u"4\u0415-3"_s << true << 4e-3; // Official + QTest::newRow("uk_UA Latin E") << u"uk_UA"_s << u"4E-3"_s << true << 4e-3; + QTest::newRow("ru_RU Latin E") << u"ru_RU"_s << u"4E-3"_s << true << 4e-3; // Official + QTest::newRow("ru_RU Cyrillic E") << u"ru_RU"_s << u"4\u0415-3"_s << true << 4e-3; } void tst_QLocale::stringToDouble_data()