From cbb4c59c38cca77133ea1b7a65004ee10bb021dc Mon Sep 17 00:00:00 2001 From: Edward Welbourne Date: Mon, 22 Mar 2021 15:13:43 +0100 Subject: Make QLocale documentation more honest Documented the fall-back process by which QLocale selects an actual locale based on what it is asked for. The prior documentation was wrong. In the process, removed some out-of-date claims about QString's toInt() and toDouble() caring about the default locale; and caught a few more cases (in \internal docs) of country -> territory. Fixes: QTBUG-90962 Change-Id: I5e7cfa66443c9335a71fb2048c3f2ebf7af64573 Reviewed-by: Thiago Macieira --- .../doc/snippets/code/src_corelib_text_qlocale.cpp | 4 - src/corelib/text/qlocale.cpp | 98 ++++++++++------------ src/corelib/text/qlocale.qdoc | 61 ++++++++------ 3 files changed, 76 insertions(+), 87 deletions(-) diff --git a/src/corelib/doc/snippets/code/src_corelib_text_qlocale.cpp b/src/corelib/doc/snippets/code/src_corelib_text_qlocale.cpp index bfd847569b..58a7502346 100644 --- a/src/corelib/doc/snippets/code/src_corelib_text_qlocale.cpp +++ b/src/corelib/doc/snippets/code/src_corelib_text_qlocale.cpp @@ -59,10 +59,6 @@ int i = egyptian.toInt(s2); //! [1] -QLocale::setDefault(QLocale(QLocale::Hebrew, QLocale::Israel)); -QLocale hebrew; // Constructs a default QLocale -QString s1 = hebrew.toString(15714.3, 'e'); - bool ok; double d; diff --git a/src/corelib/text/qlocale.cpp b/src/corelib/text/qlocale.cpp index 763703b53d..783d09a8b1 100644 --- a/src/corelib/text/qlocale.cpp +++ b/src/corelib/text/qlocale.cpp @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2020 The Qt Company Ltd. +** Copyright (C) 2021 The Qt Company Ltd. ** Copyright (C) 2019 Intel Corporation. ** Contact: https://www.qt.io/licensing/ ** @@ -503,7 +503,7 @@ static QStringView findTag(QStringView name) static bool validTag(QStringView tag) { - // Returns false if any character in tag is not an ASCII letter or digit + // Is tag is a non-empty sequence of ASCII letters and/or digits ? for (QChar uc : tag) { const char16_t ch = uc.unicode(); if (!((ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z') || (ch >= '0' && ch <= '9'))) @@ -825,7 +825,7 @@ static QLocalePrivate *findLocalePrivate(QLocale::Language language, QLocale::Sc QLocale::NumberOptions numberOptions = QLocale::DefaultNumberOptions; - // If not found, should default to system + // If not found, should use default locale: if (data->m_language_id == QLocale::C) { if (defaultLocalePrivate.exists()) numberOptions = defaultLocalePrivate->data()->m_numberOptions; @@ -938,33 +938,28 @@ QLocale::QLocale(QLocalePrivate &dd) /*! Constructs a QLocale object with the specified \a name, which has the format - "language[_script][_country][.codeset][@modifier]" or "C", where: + "language[_script][_territory][.codeset][@modifier]" or "C", where: \list - \li language is a lowercase, two-letter, ISO 639 language code (also some - three-letter codes), - \li script is a titlecase, four-letter, ISO 15924 script code, - \li country is an uppercase, two-letter, ISO 3166 country code - (also "419" as defined by United Nations), - \li and codeset and modifier are ignored. + \li language is a lowercase, two-letter, ISO 639 language code (some + three-letter codes are also recognized), + \li script is a capitalized, four-letter, ISO 15924 script code, + \li territory is an uppercase, two-letter, ISO 3166 territory code + (some numeric codes are also recognized), and + \li codeset and modifier are ignored. \endlist The separator can be either underscore \c{'_'} (U+005F, "low line") or a - dash \c{'-'} (U+002D, "hyphen-minus"). + dash \c{'-'} (U+002D, "hyphen-minus"). If the string violates the locale + format, or no suitable data can be found for the specified keys, the "C" + locale is used instead. If QLocale has no data for the specified combination + of language, script and territory, the it uses most suitable match it can + find instead. - If the string violates the locale format, or language is not - a valid ISO 639 code, the "C" locale is used instead. If country - is not present, or is not a valid ISO 3166 code, the most - appropriate country is chosen for the specified language. + This constructor is much slower than QLocale(Language, Script, Territory) or + QLocale(Language, Territory). - The language, script and country codes are converted to their respective - \c Language, \c Script and \c Country enums. After this conversion is - performed, the constructor behaves exactly like QLocale(Country, Script, - Language). - - This constructor is much slower than QLocale(Country, Script, Language). - - \sa bcp47Name() + \sa bcp47Name(), {Matching combinations of language, script and territory} */ QLocale::QLocale(const QString &name) @@ -973,9 +968,10 @@ QLocale::QLocale(const QString &name) } /*! - Constructs a QLocale object initialized with the default locale. If - no default locale was set using setDefault(), this locale will - be the same as the one returned by system(). + Constructs a QLocale object initialized with the default locale. + + If no default locale was set using setDefault(), this locale will be the + same as the one returned by system(). \sa setDefault() */ @@ -983,27 +979,20 @@ QLocale::QLocale(const QString &name) QLocale::QLocale() : d(*defaultLocalePrivate) { - // Make sure system data is up to date + // Make sure system data is up to date: systemData(); } /*! - Constructs a QLocale object with the specified \a language and \a - territory. - - \list - \li If the language/territory pair is found in the database, it is used. - \li If the language is found but the territory is not, or if the territory - is \c AnyTerritory, the language is used with the most - appropriate available territory (for example, Germany for German), - \li If neither the language nor the territory are found, QLocale - defaults to the default locale (see setDefault()). - \endlist + Constructs a QLocale object for the specified \a language and \a territory. - The language and territory that are actually used can be queried - using language() and territory(). + If there is more than one script in use for this combination, a likely + script will be selected. If QLocale has no data for the specified \a + language, the default locale is used. If QLocale has no data for the + specified combination of \a language and \a territory, an alternative + territory may be used instead. - \sa setDefault(), language(), territory() + \sa setDefault(), {Matching combinations of language, script and territory} */ QLocale::QLocale(Language language, Territory territory) @@ -1012,25 +1001,22 @@ QLocale::QLocale(Language language, Territory territory) } /*! - Constructs a QLocale object with the specified \a language, \a script and - \a territory. + \since 4.8 + + Constructs a QLocale object for the specified \a language, \a script and \a + territory. + + If QLocale does not have data for the given combination, it will find data + for as good a match as it can. It falls back on the default locale if \list - \li If the language/script/territory is found in the database, it is used. - \li If both \a script is AnyScript and \a territory is AnyTerritory, the - language is used with the most appropriate available script and territory - (for example, Germany for German), - \li If either \a script is AnyScript or \a territory is AnyTerritory, the - language is used with the first locale that matches the given \a script - and \a territory. - \li If neither the language nor the territory are found, QLocale - defaults to the default locale (see setDefault()). + \li \a language is \c AnyLanguage and no language can be inferred from \a + script and \a territory + \li QLocale has no data for the language, either given as \a language or + inferred as above. \endlist - The language, script and territory that are actually used can be queried - using language(), script() and territory(). - - \sa setDefault(), language(), script(), territory() + \sa setDefault(), {Matching combinations of language, script and territory} */ QLocale::QLocale(Language language, Script script, Territory territory) diff --git a/src/corelib/text/qlocale.qdoc b/src/corelib/text/qlocale.qdoc index e8246f7990..df26a9c129 100644 --- a/src/corelib/text/qlocale.qdoc +++ b/src/corelib/text/qlocale.qdoc @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2019 The Qt Company Ltd. +** Copyright (C) 2021 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the documentation of the Qt Toolkit. @@ -36,10 +36,9 @@ \ingroup string-processing \ingroup shared - - QLocale is initialized with a language/territory pair in its - constructor and offers number-to-string and string-to-number - conversion functions similar to those in QString. + QLocale is constructed for a specified language, optional script and + territory. It offers various facilities for formatting data as text, + localized appropriately, and for reading data out of localized text. Example: @@ -54,9 +53,6 @@ \list \li If a QLocale object is constructed with the default constructor, it will use the default locale's settings. - \li QString::toInt(), QString::toDouble(), etc., interpret the - string according to the default locale. If this fails, it - falls back on the "C" locale. \li QString::arg() uses the default locale to format a number when its position specifier in the format string contains an 'L', e.g. "%L1". @@ -66,36 +62,47 @@ \snippet code/src_corelib_text_qlocale.cpp 1 - When a language/territory pair is specified in the constructor, one - of three things can happen: - - \list - \li If the language/territory pair is found in the database, it is used. - \li If the language is found but the territory is not, or if the territory - is \c AnyTerritory, the language is used with the most - appropriate available territory (for example, Germany for German), - \li If neither the language nor the territory are found, QLocale - defaults to the default locale (see setDefault()). - \endlist - - Use language() and territory() to determine the actual language and - territory values used. - An alternative method for constructing a QLocale object is by specifying the locale name. \snippet code/src_corelib_text_qlocale.cpp 2 - This constructor converts the locale name to a language/territory - pair; it does not use the system locale database. + This constructor reads the language, script and/or territory from the given + name, accepting either uderscore or dash as separator (and ignoring any + trailing \c{.codeset} or \c{@variant} suffix). \note For the current keyboard input locale take a look at QInputMethod::locale(). QLocale's data is based on Common Locale Data Repository v38. - \sa QString::arg(), QString::toInt(), QString::toDouble(), - QInputMethod::locale() + \section1 Matching combinations of language, script and territory + + QLocale has data, derived from CLDR, for many combinations of language, + script and territory, but not all. If it is constructed with all three of + these key values specified (treating \c AnyLanguage, \c AnyScript or \c + AnyTerritory as unspecified) and QLocale has data for the given combination, + this data is used. Otherwise, QLocale does its best to find a sensible + combination of language, script and territory, for which it does have data, + that matches those that were specified. + + The CLDR provides tables of likely combinations, which are used to fill in + any unspecified key or keys; if QLocale has data for the result of such a + likely combination, that is used. If no language is specified, and none can + be determined from script and territory, or if QLocale has no data for the + language, the "C" locale (when reading the keys from a string) or default + locale (otherwise) is used. + + When QLocale has no data for the keys specified, with likely keys filled in + where unspecified, but does have data for the resulting language, a + fall-back is sought, based on ignoring either territory, script or both (in + that order). This results in a QLocale which may not match what was asked + for, but provides localization that's as suitable as the available data + permits, for the keys specified. + + Use language(), script() and territory() to determine the actual keys used. + + \sa QString::arg(), QInputMethod::locale() */ /*! -- cgit v1.2.3