summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/corelib/text/qlocale.cpp36
-rw-r--r--src/corelib/text/qlocale_mac.mm16
-rw-r--r--src/corelib/text/qlocale_p.h4
-rw-r--r--tests/auto/corelib/text/qlocale/tst_qlocale.cpp30
-rwxr-xr-xutil/locale_database/cldr2qlocalexml.py1
5 files changed, 59 insertions, 28 deletions
diff --git a/src/corelib/text/qlocale.cpp b/src/corelib/text/qlocale.cpp
index 26db674a99..11e788c200 100644
--- a/src/corelib/text/qlocale.cpp
+++ b/src/corelib/text/qlocale.cpp
@@ -660,6 +660,11 @@ static QLocalePrivate *c_private()
return &c_locale;
}
+static const QLocaleData *systemData();
+static QLocale::NumberOptions system_number_options = QLocale::DefaultNumberOptions;
+Q_GLOBAL_STATIC_WITH_ARGS(QExplicitlySharedDataPointer<QLocalePrivate>, systemLocalePrivate,
+ (QLocalePrivate::create(systemData(), system_number_options)))
+
#ifndef QT_NO_SYSTEMLOCALE
/******************************************************************************
** Default system locale behavior
@@ -711,6 +716,7 @@ static void updateSystemPrivate()
{
// This function is NOT thread-safe!
// It *should not* be called by anything but systemData()
+ // It *is* called before {system,default}LocalePrivate exist.
const QSystemLocale *sys_locale = systemLocale();
// tell the object that the system locale has changed.
@@ -718,11 +724,14 @@ static void updateSystemPrivate()
// Populate global with fallback as basis:
globalLocaleData = *sys_locale->fallbackUiLocaleData();
+ system_number_options = QLocale::DefaultNumberOptions;
QVariant res = sys_locale->query(QSystemLocale::LanguageId, QVariant());
if (!res.isNull()) {
globalLocaleData.m_language_id = res.toInt();
globalLocaleData.m_script_id = QLocale::AnyScript; // default for compatibility
+ if (globalLocaleData.m_language_id == QLocale::C)
+ system_number_options = QLocale::OmitGroupSeparator;
}
res = sys_locale->query(QSystemLocale::CountryId, QVariant());
if (!res.isNull()) {
@@ -737,9 +746,26 @@ static void updateSystemPrivate()
if (!res.isNull() && !res.toString().isEmpty())
globalLocaleData.m_decimal = res.toString().at(0).unicode();
+ // System may supply empty group separator to say we should omit grouping;
+ // and it makes no sense to use the same separator for decimal and grouping
+ // (which might happen by system supplying, as decimal, what CLDR has given
+ // us for grouping; or the other way round). Assume, at least, that each of
+ // system and CLDR has decimal != group, all the same.
res = sys_locale->query(QSystemLocale::GroupSeparator, QVariant());
- if (!res.isNull() && !res.toString().isEmpty())
- globalLocaleData.m_group = res.toString().at(0).unicode();
+ if (res.isNull()) {
+ // The case where system over-rides decimal but not group, and its
+ // decimal clashes with CLDR's group.
+ if (globalLocaleData.m_group == globalLocaleData.m_decimal)
+ system_number_options |= QLocale::OmitGroupSeparator;
+ } else if (res.toString().isEmpty()) {
+ system_number_options |= QLocale::OmitGroupSeparator;
+ } else {
+ const ushort group = res.toString().at(0).unicode();
+ if (group != globalLocaleData.m_decimal)
+ globalLocaleData.m_group = group;
+ else if (group == globalLocaleData.m_group)
+ qWarning("System-supplied decimal and grouping character are both 0x%hx", group);
+ }
res = sys_locale->query(QSystemLocale::ZeroDigit, QVariant());
if (!res.isNull() && !res.toString().isEmpty())
@@ -752,6 +778,10 @@ static void updateSystemPrivate()
res = sys_locale->query(QSystemLocale::PositiveSign, QVariant());
if (!res.isNull() && !res.toString().isEmpty())
globalLocaleData.m_plus = res.toString().at(0).unicode();
+
+ if (systemLocalePrivate.exists())
+ systemLocalePrivate->data()->m_numberOptions = system_number_options;
+ // else: system_number_options will be passed to create() when constructing.
}
#endif // !QT_NO_SYSTEMLOCALE
@@ -834,8 +864,6 @@ static const int locale_data_size = sizeof(locale_data)/sizeof(QLocaleData) - 1;
Q_GLOBAL_STATIC_WITH_ARGS(QSharedDataPointer<QLocalePrivate>, defaultLocalePrivate,
(QLocalePrivate::create(defaultData())))
-Q_GLOBAL_STATIC_WITH_ARGS(QExplicitlySharedDataPointer<QLocalePrivate>, systemLocalePrivate,
- (QLocalePrivate::create(systemData())))
static QLocalePrivate *localePrivateByName(const QString &name)
{
diff --git a/src/corelib/text/qlocale_mac.mm b/src/corelib/text/qlocale_mac.mm
index 7bdae662c7..5381f0f975 100644
--- a/src/corelib/text/qlocale_mac.mm
+++ b/src/corelib/text/qlocale_mac.mm
@@ -283,10 +283,12 @@ static QString getMacTimeFormat(CFDateFormatterStyle style)
return macToQtFormat(QString::fromCFString(CFDateFormatterGetFormat(formatter)));
}
-static QString getCFLocaleValue(CFStringRef key)
+static QVariant getCFLocaleValue(CFStringRef key)
{
QCFType<CFLocaleRef> locale = CFLocaleCopyCurrent();
CFTypeRef value = CFLocaleGetValue(locale, key);
+ if (!value)
+ return QVariant();
return QString::fromCFString(CFStringRef(static_cast<CFTypeRef>(value)));
}
@@ -411,14 +413,10 @@ QVariant QSystemLocale::query(QueryType type, QVariant in) const
switch(type) {
// case Name:
// return getMacLocaleName();
- case DecimalPoint: {
- QString value = getCFLocaleValue(kCFLocaleDecimalSeparator);
- return value.isEmpty() ? QVariant() : value;
- }
- case GroupSeparator: {
- QString value = getCFLocaleValue(kCFLocaleGroupingSeparator);
- return value.isEmpty() ? QVariant() : value;
- }
+ case DecimalPoint:
+ return getCFLocaleValue(kCFLocaleDecimalSeparator);
+ case GroupSeparator:
+ return getCFLocaleValue(kCFLocaleGroupingSeparator);
case DateFormatLong:
case DateFormatShort:
return getMacDateFormat(type == DateFormatShort
diff --git a/src/corelib/text/qlocale_p.h b/src/corelib/text/qlocale_p.h
index bb24009523..7e26e86fdf 100644
--- a/src/corelib/text/qlocale_p.h
+++ b/src/corelib/text/qlocale_p.h
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2019 The Qt Company Ltd.
+** Copyright (C) 2020 The Qt Company Ltd.
** Copyright (C) 2016 Intel Corporation.
** Contact: https://www.qt.io/licensing/
**
@@ -87,7 +87,7 @@ public:
LanguageId, // uint
CountryId, // uint
DecimalPoint, // QString
- GroupSeparator, // QString
+ GroupSeparator, // QString (empty QString means: don't group digits)
ZeroDigit, // QString
NegativeSign, // QString
DateFormatLong, // QString
diff --git a/tests/auto/corelib/text/qlocale/tst_qlocale.cpp b/tests/auto/corelib/text/qlocale/tst_qlocale.cpp
index 8f434acb29..60ed22488f 100644
--- a/tests/auto/corelib/text/qlocale/tst_qlocale.cpp
+++ b/tests/auto/corelib/text/qlocale/tst_qlocale.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2019 The Qt Company Ltd.
+** Copyright (C) 2020 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the test suite of the Qt Toolkit.
@@ -1869,14 +1869,16 @@ void tst_QLocale::toDateTime()
// Format number string according to system locale settings.
// Expected in format is US "1,234.56".
-QString systemLocaleFormatNumber(const QString &numberString)
+QString systemLocaleFormatNumber(QString &&numberString)
{
QLocale locale = QLocale::system();
- QString numberStringCopy = numberString;
- return numberStringCopy.replace(QChar(','), QChar('G'))
- .replace(QChar('.'), QChar('D'))
- .replace(QChar('G'), locale.groupSeparator())
- .replace(QChar('D'), locale.decimalPoint());
+ QString numberStringMunged =
+ numberString.replace(QChar(','), QChar('G')).replace(QChar('.'), QChar('D'));
+ if (locale.numberOptions() & QLocale::OmitGroupSeparator)
+ numberStringMunged.remove(QLatin1Char('G'));
+ else
+ numberStringMunged.replace(QChar('G'), locale.groupSeparator());
+ return numberStringMunged.replace(QChar('D'), locale.decimalPoint());
}
void tst_QLocale::macDefaultLocale()
@@ -1899,12 +1901,14 @@ void tst_QLocale::macDefaultLocale()
// independently of the locale. Verify that they have one of the
// allowed values and are not the same.
QVERIFY(locale.decimalPoint() == QChar('.') || locale.decimalPoint() == QChar(','));
- QVERIFY(locale.groupSeparator() == QChar(',')
- || locale.groupSeparator() == QChar('.')
- || locale.groupSeparator() == QChar('\xA0') // no-breaking space
- || locale.groupSeparator() == QChar('\'')
- || locale.groupSeparator() == QChar());
- QVERIFY(locale.decimalPoint() != locale.groupSeparator());
+ if (!(locale.numberOptions() & QLocale::OmitGroupSeparator)) {
+ QVERIFY(locale.groupSeparator() == QChar(',')
+ || locale.groupSeparator() == QChar('.')
+ || locale.groupSeparator() == QChar('\xA0') // no-breaking space
+ || locale.groupSeparator() == QChar('\'')
+ || locale.groupSeparator() == QChar());
+ QVERIFY(locale.decimalPoint() != locale.groupSeparator());
+ }
// make sure we are using the system to parse them
QCOMPARE(locale.toString(1234.56), systemLocaleFormatNumber(QString("1,234.56")));
diff --git a/util/locale_database/cldr2qlocalexml.py b/util/locale_database/cldr2qlocalexml.py
index 072ea9e4ed..a1df872e01 100755
--- a/util/locale_database/cldr2qlocalexml.py
+++ b/util/locale_database/cldr2qlocalexml.py
@@ -305,6 +305,7 @@ def _generateLocaleInfo(path, language_code, script_code, country_code, variant_
result['decimal'] = get_number_in_system(path, "numbers/symbols/decimal", numbering_system)
result['group'] = get_number_in_system(path, "numbers/symbols/group", numbering_system)
+ assert result['decimal'] != result['group']
result['list'] = get_number_in_system(path, "numbers/symbols/list", numbering_system)
result['percent'] = get_number_in_system(path, "numbers/symbols/percentSign", numbering_system)
try: