Fix locale warnings on Darwin. https://github.com/qt/qtbase/commit/f03ccd29bd5d36a79c6b73eccc6485c1b49a109c https://github.com/qt/qtbase/commit/611777e084c503c7f3195adbdbfb10a5f74308f9 https://github.com/qt/qtbase/commit/7aac60beea47130b9e9d435579143794fa2e2edc diff --git a/src/corelib/kernel/qcoreapplication.cpp b/src/corelib/kernel/qcoreapplication.cpp index 355d1e42ccf..96efb94b0ca 100644 --- src/corelib/kernel/qcoreapplication.cpp +++ src/corelib/kernel/qcoreapplication.cpp @@ -548,22 +548,30 @@ QString qAppName() void QCoreApplicationPrivate::initLocale() { -#if defined(Q_OS_UNIX) && !defined(QT_BOOTSTRAPPED) +#if defined(QT_BOOTSTRAPPED) + // Don't try to control bootstrap library locale or encoding. +#elif defined(Q_OS_UNIX) Q_CONSTINIT static bool qt_locale_initialized = false; if (qt_locale_initialized) return; qt_locale_initialized = true; -# ifdef Q_OS_INTEGRITY + // By default the portable "C"/POSIX locale is selected and active. + // Apply the locale from the environment, via setlocale(), which will + // read LC_ALL, LC_, and LANG, in order (for each category). + const char *locale = setlocale(LC_ALL, ""); + + // Next, let's ensure that LC_CTYPE is UTF-8, since QStringConverter's + // QLocal8Bit hard-codes this, and we need to be consistent. +# if defined(Q_OS_INTEGRITY) setlocale(LC_CTYPE, "UTF-8"); +# elif defined(Q_OS_QNX) + // QNX has no nl_langinfo, so we can't check. + // FIXME: Shouldn't we still setlocale("UTF-8")? +# elif defined(Q_OS_ANDROID) && __ANDROID_API__ < __ANDROID_API_O__ + // Android 6 still lacks nl_langinfo(), so we can't check. + // FIXME: Shouldn't we still setlocale("UTF-8")? # else -# if defined(Q_OS_QNX) || (defined(Q_OS_ANDROID) && __ANDROID_API__ < __ANDROID_API_O__) - // Android 6 still lacks nl_langinfo(), as does QNX, so we just assume it's - // always UTF-8 on these platforms. - auto nl_langinfo = [](int) { return "UTF-8"; }; -# endif // QNX or Android NDK < 26, "O". - - const char *locale = setlocale(LC_ALL, ""); const char *codec = nl_langinfo(CODESET); if (Q_UNLIKELY(qstricmp(codec, "UTF-8") != 0 && qstricmp(codec, "utf8") != 0)) { QByteArray oldLocale = locale; @@ -575,8 +583,8 @@ void QCoreApplicationPrivate::initLocale() newLocale += ".UTF-8"; newLocale = setlocale(LC_CTYPE, newLocale); - // if locale doesn't exist, try some fallbacks -# ifdef Q_OS_DARWIN + // If that locale doesn't exist, try some fallbacks: +# if defined(Q_OS_DARWIN) if (newLocale.isEmpty()) newLocale = setlocale(LC_CTYPE, "UTF-8"); # endif @@ -590,7 +598,7 @@ void QCoreApplicationPrivate::initLocale() "reconfigure your locale. See the locale(1) manual for more information.", codec, oldLocale.constData(), newLocale.constData()); } -# endif // Integrity +# endif // Platform choice #endif // Unix } diff --git a/src/corelib/kernel/qcoreapplication.cpp b/src/corelib/kernel/qcoreapplication.cpp index 96efb94b0ca..d38cb742424 100644 --- src/corelib/kernel/qcoreapplication.cpp +++ src/corelib/kernel/qcoreapplication.cpp @@ -559,7 +559,7 @@ void QCoreApplicationPrivate::initLocale() // By default the portable "C"/POSIX locale is selected and active. // Apply the locale from the environment, via setlocale(), which will // read LC_ALL, LC_, and LANG, in order (for each category). - const char *locale = setlocale(LC_ALL, ""); + setlocale(LC_ALL, ""); // Next, let's ensure that LC_CTYPE is UTF-8, since QStringConverter's // QLocal8Bit hard-codes this, and we need to be consistent. @@ -572,9 +572,9 @@ void QCoreApplicationPrivate::initLocale() // Android 6 still lacks nl_langinfo(), so we can't check. // FIXME: Shouldn't we still setlocale("UTF-8")? # else - const char *codec = nl_langinfo(CODESET); - if (Q_UNLIKELY(qstricmp(codec, "UTF-8") != 0 && qstricmp(codec, "utf8") != 0)) { - QByteArray oldLocale = locale; + const char *charEncoding = nl_langinfo(CODESET); + if (Q_UNLIKELY(qstricmp(charEncoding, "UTF-8") != 0 && qstricmp(charEncoding, "utf8") != 0)) { + const QByteArray oldLocale = setlocale(LC_ALL, nullptr); QByteArray newLocale = setlocale(LC_CTYPE, nullptr); if (qsizetype dot = newLocale.indexOf('.'); dot != -1) newLocale.truncate(dot); // remove encoding, if any @@ -593,10 +593,20 @@ void QCoreApplicationPrivate::initLocale() if (newLocale.isEmpty()) newLocale = setlocale(LC_CTYPE, "C.utf8"); - qWarning("Detected system locale encoding (%s, locale \"%s\") is not UTF-8.\n" - "Qt shall use a UTF-8 locale (\"%s\") instead. If this causes problems,\n" - "reconfigure your locale. See the locale(1) manual for more information.", - codec, oldLocale.constData(), newLocale.constData()); + if (newLocale.isEmpty()) { + // Failed to set a UTF-8 locale. + qWarning("Detected locale \"%s\" with character encoding \"%s\", which is not UTF-8.\n" + "Qt depends on a UTF-8 locale, but has failed to switch to one.\n" + "If this causes problems, reconfigure your locale. See the locale(1) manual\n" + "for more information.", oldLocale.constData(), charEncoding); + } else { + // Let the user know we over-rode their configuration. + qWarning("Detected locale \"%s\" with character encoding \"%s\", which is not UTF-8.\n" + "Qt depends on a UTF-8 locale, and has switched to \"%s\" instead.\n" + "If this causes problems, reconfigure your locale. See the locale(1) manual\n" + "for more information.", + oldLocale.constData(), charEncoding, newLocale.constData()); + } } # endif // Platform choice #endif // Unix diff --git a/src/corelib/kernel/qcoreapplication.cpp b/src/corelib/kernel/qcoreapplication.cpp index d38cb742424..7f53931a3d3 100644 --- src/corelib/kernel/qcoreapplication.cpp +++ src/corelib/kernel/qcoreapplication.cpp @@ -575,7 +575,20 @@ void QCoreApplicationPrivate::initLocale() const char *charEncoding = nl_langinfo(CODESET); if (Q_UNLIKELY(qstricmp(charEncoding, "UTF-8") != 0 && qstricmp(charEncoding, "utf8") != 0)) { const QByteArray oldLocale = setlocale(LC_ALL, nullptr); - QByteArray newLocale = setlocale(LC_CTYPE, nullptr); + QByteArray newLocale; + bool warnOnOverride = true; +# if defined(Q_OS_DARWIN) + // Don't warn unless the char encoding has been changed from the + // default "C" encoding, or the user touched any of the locale + // environment variables to force the "C" char encoding. + warnOnOverride = qstrcmp(setlocale(LC_CTYPE, nullptr), "C") != 0 + || getenv("LC_ALL") || getenv("LC_CTYPE") || getenv("LANG"); + + // No need to try language or region specific CTYPEs, as they + // all point back to the same generic UTF-8 CTYPE. + newLocale = setlocale(LC_CTYPE, "UTF-8"); +# else + newLocale = setlocale(LC_CTYPE, nullptr); if (qsizetype dot = newLocale.indexOf('.'); dot != -1) newLocale.truncate(dot); // remove encoding, if any if (qsizetype at = newLocale.indexOf('@'); at != -1) @@ -584,14 +597,11 @@ void QCoreApplicationPrivate::initLocale() newLocale = setlocale(LC_CTYPE, newLocale); // If that locale doesn't exist, try some fallbacks: -# if defined(Q_OS_DARWIN) - if (newLocale.isEmpty()) - newLocale = setlocale(LC_CTYPE, "UTF-8"); -# endif if (newLocale.isEmpty()) newLocale = setlocale(LC_CTYPE, "C.UTF-8"); if (newLocale.isEmpty()) newLocale = setlocale(LC_CTYPE, "C.utf8"); +# endif if (newLocale.isEmpty()) { // Failed to set a UTF-8 locale. @@ -599,7 +609,7 @@ void QCoreApplicationPrivate::initLocale() "Qt depends on a UTF-8 locale, but has failed to switch to one.\n" "If this causes problems, reconfigure your locale. See the locale(1) manual\n" "for more information.", oldLocale.constData(), charEncoding); - } else { + } else if (warnOnOverride) { // Let the user know we over-rode their configuration. qWarning("Detected locale \"%s\" with character encoding \"%s\", which is not UTF-8.\n" "Qt depends on a UTF-8 locale, and has switched to \"%s\" instead.\n"