diff options
author | Edward Welbourne <edward.welbourne@qt.io> | 2018-01-12 11:36:06 +0100 |
---|---|---|
committer | Edward Welbourne <edward.welbourne@qt.io> | 2018-05-23 12:12:24 +0000 |
commit | c416a7f25770563a265cc86e779f2e54c01a85a0 (patch) | |
tree | d561e4236bd427077aadc1af6f11345b3ad74007 | |
parent | 7aaa7debc455516cbb1b1f536e990b9154272f64 (diff) |
QLocale: only use LANGUAGE if it contradicts LC_ALL/LC_MESSAGES/LANG
If LANGUAGE specified only the language, without any script or
country, and matched the value we'd got from other environment
variables, we were throwing away their knowledge of script and
country, leading to falling back on the default script and country for
that language, which might be at odds with what other environment
variables had told us.
Changed to only use LANGUAGE if it contradicts (or extends) what we
would otherwise have used. Clarified some comments in the process.
[ChangeLog][QLocale][Unix] When using LANGUAGE would lose information
about script or country, without changing language, use the locale
implied by LC_ALL, LC_MESSAGES or LANG.
Prompted-by: Safa AlFulaij <safa1996alfulaij@gmail.com>
Change-Id: Ie433e57ae6b995abafd05c931136cc9796494895
Reviewed-by: Oswald Buddenhagen <oswald.buddenhagen@qt.io>
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
-rw-r--r-- | src/corelib/tools/qlocale_unix.cpp | 34 |
1 files changed, 31 insertions, 3 deletions
diff --git a/src/corelib/tools/qlocale_unix.cpp b/src/corelib/tools/qlocale_unix.cpp index 095001e0a3..1a9184bca9 100644 --- a/src/corelib/tools/qlocale_unix.cpp +++ b/src/corelib/tools/qlocale_unix.cpp @@ -107,8 +107,36 @@ Q_GLOBAL_STATIC(QSystemLocaleData, qSystemLocaleData) #ifndef QT_NO_SYSTEMLOCALE +static bool contradicts(const QByteArray &maybe, const QByteArray &known) +{ + if (maybe.isEmpty()) + return false; + + /* + If \a known (our current best shot at deciding which language to use) + provides more information (e.g. script, country) than \a maybe (a + candidate to replace \a known) and \a maybe agrees with \a known in what + it does provide, we keep \a known; this happens when \a maybe comes from + LANGUAGE (usually a simple language code) and LANG includes script and/or + country. A textual comparison won't do because, for example, bn (Bengali) + isn't a prefix of ben_IN, but the latter is a refinement of the former. + (Meanwhile, bn is a prefix of bnt, Bantu; and a prefix of ben is be, + Belarusian. There are many more such prefixings between two- and + three-letter codes.) + */ + QLocale::Language langm, langk; + QLocale::Script scriptm, scriptk; + QLocale::Country landm, landk; + QLocalePrivate::getLangAndCountry(maybe, langm, scriptm, landm); + QLocalePrivate::getLangAndCountry(known, langk, scriptk, landk); + return (langm != QLocale::AnyLanguage && langm != langk) + || (scriptm != QLocale::AnyScript && scriptm != scriptk) + || (landm != QLocale::AnyCountry && landm != landk); +} + QLocale QSystemLocale::fallbackUiLocale() const { + // See man 7 locale for precedence - LC_ALL beats LC_MESSAGES beats LANG: QByteArray lang = qgetenv("LC_ALL"); if (lang.isEmpty()) lang = qgetenv("LC_MESSAGES"); @@ -118,12 +146,12 @@ QLocale QSystemLocale::fallbackUiLocale() const if (lang.isEmpty() || lang == QByteArray("C") || lang == QByteArray("POSIX")) return QLocale(QString::fromLatin1(lang)); - // if the locale is not the "C" locale and LANGUAGE is not empty, return - // the first part of LANGUAGE if LANGUAGE is set and has a first part: + // ... otherwise, if the first part of LANGUAGE says more than or + // contradicts what we have, use that: QByteArray language = qgetenv("LANGUAGE"); if (!language.isEmpty()) { language = language.split(':').constFirst(); - if (!language.isEmpty()) + if (contradicts(language, lang)) return QLocale(QString::fromLatin1(language)); } |