summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/corelib/tools/qlocale.cpp83
-rw-r--r--tests/auto/corelib/tools/qlocale/tst_qlocale.cpp39
2 files changed, 100 insertions, 22 deletions
diff --git a/src/corelib/tools/qlocale.cpp b/src/corelib/tools/qlocale.cpp
index 20a984fafe..5b53b8b338 100644
--- a/src/corelib/tools/qlocale.cpp
+++ b/src/corelib/tools/qlocale.cpp
@@ -334,33 +334,17 @@ QByteArray QLocalePrivate::bcp47Name(char separator) const
return localeId.withLikelySubtagsRemoved().name(separator);
}
-const QLocaleData *QLocaleData::findLocaleData(QLocale::Language language, QLocale::Script script, QLocale::Country country)
+static const QLocaleData *findLocaleDataById(const QLocaleId &localeId)
{
- QLocaleId localeId = QLocaleId::fromIds(language, script, country);
- localeId = localeId.withLikelySubtagsAdded();
-
- uint idx = locale_index[localeId.language_id];
+ const uint idx = locale_index[localeId.language_id];
const QLocaleData *data = locale_data + idx;
- if (idx == 0) // default language has no associated country
+ if (idx == 0) // default language has no associated script or country
return data;
Q_ASSERT(data->m_language_id == localeId.language_id);
- if (localeId.script_id != QLocale::AnyScript && localeId.country_id != QLocale::AnyCountry) {
- // both script and country are explicitly specified
- do {
- if (data->m_script_id == localeId.script_id && data->m_country_id == localeId.country_id)
- return data;
- ++data;
- } while (data->m_language_id == localeId.language_id);
-
- // no match; try again with default script
- localeId.script_id = QLocale::AnyScript;
- data = locale_data + idx;
- }
-
if (localeId.script_id == QLocale::AnyScript && localeId.country_id == QLocale::AnyCountry)
return data;
@@ -369,15 +353,72 @@ const QLocaleData *QLocaleData::findLocaleData(QLocale::Language language, QLoca
if (data->m_country_id == localeId.country_id)
return data;
++data;
- } while (data->m_language_id == localeId.language_id);
+ } while (data->m_language_id && data->m_language_id == localeId.language_id);
} else if (localeId.country_id == QLocale::AnyCountry) {
do {
if (data->m_script_id == localeId.script_id)
return data;
++data;
- } while (data->m_language_id == localeId.language_id);
+ } while (data->m_language_id && data->m_language_id == localeId.language_id);
+ } else {
+ do {
+ if (data->m_script_id == localeId.script_id && data->m_country_id == localeId.country_id)
+ return data;
+ ++data;
+ } while (data->m_language_id && data->m_language_id == localeId.language_id);
+ }
+
+ return 0;
+}
+
+const QLocaleData *QLocaleData::findLocaleData(QLocale::Language language, QLocale::Script script, QLocale::Country country)
+{
+ QLocaleId localeId = QLocaleId::fromIds(language, script, country);
+ localeId = localeId.withLikelySubtagsAdded();
+
+ const uint idx = locale_index[localeId.language_id];
+
+ // Try a straight match
+ if (const QLocaleData *const data = findLocaleDataById(localeId))
+ return data;
+ QList<QLocaleId> tried;
+ tried.push_back(localeId);
+
+ // No match; try again with likely country
+ localeId = QLocaleId::fromIds(language, script, QLocale::AnyCountry);
+ localeId = localeId.withLikelySubtagsAdded();
+ if (!tried.contains(localeId)) {
+ if (const QLocaleData *const data = findLocaleDataById(localeId))
+ return data;
+ tried.push_back(localeId);
+ }
+
+ // No match; try again with any country
+ localeId = QLocaleId::fromIds(language, script, QLocale::AnyCountry);
+ if (!tried.contains(localeId)) {
+ if (const QLocaleData *const data = findLocaleDataById(localeId))
+ return data;
+ tried.push_back(localeId);
+ }
+
+ // No match; try again with likely script
+ localeId = QLocaleId::fromIds(language, QLocale::AnyScript, country);
+ localeId = localeId.withLikelySubtagsAdded();
+ if (!tried.contains(localeId)) {
+ if (const QLocaleData *const data = findLocaleDataById(localeId))
+ return data;
+ tried.push_back(localeId);
+ }
+
+ // No match; try again with any script
+ localeId = QLocaleId::fromIds(language, QLocale::AnyScript, country);
+ if (!tried.contains(localeId)) {
+ if (const QLocaleData *const data = findLocaleDataById(localeId))
+ return data;
+ tried.push_back(localeId);
}
+ // No match; return data at original index
return locale_data + idx;
}
diff --git a/tests/auto/corelib/tools/qlocale/tst_qlocale.cpp b/tests/auto/corelib/tools/qlocale/tst_qlocale.cpp
index 8d9a789507..42bfb3603d 100644
--- a/tests/auto/corelib/tools/qlocale/tst_qlocale.cpp
+++ b/tests/auto/corelib/tools/qlocale/tst_qlocale.cpp
@@ -186,12 +186,50 @@ void tst_QLocale::ctor()
QVERIFY(l.country() == default_country);
}
+#define TEST_CTOR(req_lang, req_script, req_country, exp_lang, exp_script, exp_country) \
+ { \
+ QLocale l(QLocale::req_lang, QLocale::req_script, QLocale::req_country); \
+ QCOMPARE((int)l.language(), (int)exp_lang); \
+ QCOMPARE((int)l.script(), (int)exp_script); \
+ QCOMPARE((int)l.country(), (int)exp_country); \
+ }
+
+ // Exact matches
+ TEST_CTOR(Chinese, SimplifiedHanScript, China, QLocale::Chinese, QLocale::SimplifiedHanScript, QLocale::China);
+ TEST_CTOR(Chinese, TraditionalHanScript, Taiwan, QLocale::Chinese, QLocale::TraditionalHanScript, QLocale::Taiwan);
+ TEST_CTOR(Chinese, TraditionalHanScript, HongKong, QLocale::Chinese, QLocale::TraditionalHanScript, QLocale::HongKong);
+
+ // Best match for AnyCountry
+ TEST_CTOR(Chinese, SimplifiedHanScript, AnyCountry, QLocale::Chinese, QLocale::SimplifiedHanScript, QLocale::China);
+ TEST_CTOR(Chinese, TraditionalHanScript, AnyCountry, QLocale::Chinese, QLocale::TraditionalHanScript, QLocale::Taiwan);
+
+ // Best match for AnyScript (and change country to supported one, if necessary)
+ TEST_CTOR(Chinese, AnyScript, China, QLocale::Chinese, QLocale::SimplifiedHanScript, QLocale::China);
+ TEST_CTOR(Chinese, AnyScript, Taiwan, QLocale::Chinese, QLocale::TraditionalHanScript, QLocale::Taiwan);
+ TEST_CTOR(Chinese, AnyScript, HongKong, QLocale::Chinese, QLocale::TraditionalHanScript, QLocale::HongKong);
+ TEST_CTOR(Chinese, AnyScript, UnitedStates, QLocale::Chinese, QLocale::SimplifiedHanScript, QLocale::China);
+
+ // Fully-specified not found; find best alternate country
+ TEST_CTOR(Chinese, SimplifiedHanScript, Taiwan, QLocale::Chinese, QLocale::SimplifiedHanScript, QLocale::China);
+ TEST_CTOR(Chinese, SimplifiedHanScript, UnitedStates, QLocale::Chinese, QLocale::SimplifiedHanScript, QLocale::China);
+ TEST_CTOR(Chinese, TraditionalHanScript, China, QLocale::Chinese, QLocale::TraditionalHanScript, QLocale::Taiwan);
+ TEST_CTOR(Chinese, TraditionalHanScript, UnitedStates, QLocale::Chinese, QLocale::TraditionalHanScript, QLocale::Taiwan);
+
+ // Fully-specified not found; find best alternate script
+ TEST_CTOR(Chinese, LatinScript, China, QLocale::Chinese, QLocale::SimplifiedHanScript, QLocale::China);
+ TEST_CTOR(Chinese, LatinScript, Taiwan, QLocale::Chinese, QLocale::TraditionalHanScript, QLocale::Taiwan);
+
+ // Fully-specified not found; find best alternate country and script
+ TEST_CTOR(Chinese, LatinScript, UnitedStates, QLocale::Chinese, QLocale::SimplifiedHanScript, QLocale::China);
+
+#undef TEST_CTOR
#define TEST_CTOR(req_lang, req_country, exp_lang, exp_country) \
{ \
QLocale l(QLocale::req_lang, QLocale::req_country); \
QCOMPARE((int)l.language(), (int)exp_lang); \
QCOMPARE((int)l.country(), (int)exp_country); \
}
+
{
QLocale l(QLocale::C, QLocale::AnyCountry);
QCOMPARE(l.language(), QLocale::C);
@@ -295,7 +333,6 @@ void tst_QLocale::ctor()
TEST_CTOR(Uzbek, AnyCountry, QLocale::Uzbek, QLocale::Uzbekistan)
#undef TEST_CTOR
-
#define TEST_CTOR(req_lc, exp_lang, exp_country) \
{ \
QLocale l(req_lc); \