summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorEdward Welbourne <edward.welbourne@qt.io>2018-01-12 11:36:06 +0100
committerEdward Welbourne <edward.welbourne@qt.io>2018-05-23 12:12:24 +0000
commitc416a7f25770563a265cc86e779f2e54c01a85a0 (patch)
treed561e4236bd427077aadc1af6f11345b3ad74007 /src
parent7aaa7debc455516cbb1b1f536e990b9154272f64 (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>
Diffstat (limited to 'src')
-rw-r--r--src/corelib/tools/qlocale_unix.cpp34
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));
}