summaryrefslogtreecommitdiffstats
path: root/src/corelib/text/qlocale_mac.mm
diff options
context:
space:
mode:
Diffstat (limited to 'src/corelib/text/qlocale_mac.mm')
-rw-r--r--src/corelib/text/qlocale_mac.mm88
1 files changed, 72 insertions, 16 deletions
diff --git a/src/corelib/text/qlocale_mac.mm b/src/corelib/text/qlocale_mac.mm
index d410e13565..65891d6a3b 100644
--- a/src/corelib/text/qlocale_mac.mm
+++ b/src/corelib/text/qlocale_mac.mm
@@ -14,6 +14,9 @@
#include <CoreFoundation/CoreFoundation.h>
#endif
+#include <QtCore/qloggingcategory.h>
+#include <QtCore/qcoreapplication.h>
+
QT_BEGIN_NAMESPACE
using namespace Qt::StringLiterals;
@@ -22,6 +25,41 @@ using namespace Qt::StringLiterals;
** Wrappers for Mac locale system functions
*/
+Q_LOGGING_CATEGORY(lcLocale, "qt.core.locale")
+
+static void printLocalizationInformation()
+{
+ if (!lcLocale().isDebugEnabled())
+ return;
+
+#if defined(Q_OS_MACOS)
+ // Trigger initialization of standard user defaults, so that Foundation picks
+ // up -AppleLanguages and -AppleLocale passed on the command line.
+ Q_UNUSED(NSUserDefaults.standardUserDefaults);
+#endif
+
+ auto singleLineDescription = [](NSArray *array) {
+ NSString *str = [array description];
+ str = [str stringByReplacingOccurrencesOfString:@"\n" withString:@""];
+ return [str stringByReplacingOccurrencesOfString:@" " withString:@""];
+ };
+
+ bool allowMixedLocalizations = [NSBundle.mainBundle.infoDictionary[@"CFBundleAllowMixedLocalizations"] boolValue];
+
+ NSBundle *foundation = [NSBundle bundleForClass:NSBundle.class];
+ qCDebug(lcLocale).nospace() << "Launched with locale \"" << NSLocale.currentLocale.localeIdentifier
+ << "\" based on user's preferred languages " << singleLineDescription(NSLocale.preferredLanguages)
+ << ", main bundle localizations " << singleLineDescription(NSBundle.mainBundle.localizations)
+ << ", and allowing mixed localizations " << allowMixedLocalizations
+ << "; resulting in main bundle preferred localizations "
+ << singleLineDescription(NSBundle.mainBundle.preferredLocalizations)
+ << " and Foundation preferred localizations "
+ << singleLineDescription(foundation.preferredLocalizations);
+ qCDebug(lcLocale) << "Reflected by Qt as system locale"
+ << QLocale::system() << "with UI languges " << QLocale::system().uiLanguages();
+}
+Q_COREAPP_STARTUP_FUNCTION(printLocalizationInformation);
+
static QString getMacLocaleName()
{
QCFType<CFLocaleRef> l = CFLocaleCopyCurrent();
@@ -118,14 +156,26 @@ static QVariant macDayName(int day, QSystemLocale::QueryType type)
static QString macZeroDigit()
{
- QCFType<CFLocaleRef> locale = CFLocaleCopyCurrent();
- QCFType<CFNumberFormatterRef> numberFormatter =
- CFNumberFormatterCreate(nullptr, locale, kCFNumberFormatterNoStyle);
- const int zeroDigit = 0;
- QCFType<CFStringRef> value
- = CFNumberFormatterCreateStringWithValue(nullptr, numberFormatter,
- kCFNumberIntType, &zeroDigit);
- return QString::fromCFString(value);
+ static QString cachedZeroDigit;
+
+ if (cachedZeroDigit.isNull()) {
+ QCFType<CFLocaleRef> locale = CFLocaleCopyCurrent();
+ QCFType<CFNumberFormatterRef> numberFormatter =
+ CFNumberFormatterCreate(nullptr, locale, kCFNumberFormatterNoStyle);
+ const int zeroDigit = 0;
+ QCFType<CFStringRef> value
+ = CFNumberFormatterCreateStringWithValue(nullptr, numberFormatter,
+ kCFNumberIntType, &zeroDigit);
+ cachedZeroDigit = QString::fromCFString(value);
+ }
+
+ static QMacNotificationObserver localeChangeObserver = QMacNotificationObserver(
+ nil, NSCurrentLocaleDidChangeNotification, [&] {
+ qCDebug(lcLocale) << "System locale changed";
+ cachedZeroDigit = QString();
+ });
+
+ return cachedZeroDigit;
}
static QString zeroPad(QString &&number, qsizetype minDigits, const QString &zero)
@@ -188,12 +238,16 @@ static QString fourDigitYear(int year, const QString &zero)
static QString macDateToStringImpl(QDate date, CFDateFormatterStyle style)
{
- QCFType<CFDateRef> myDate = date.startOfDay().toCFDate();
+ // Use noon on the given date, to avoid complications that can arise for
+ // dates before 1900 (see QTBUG-54955) using different UTC offset than
+ // QDateTime extrapolates backwards from time_t functions that only work
+ // back to 1900. (Alaska and Phillipines may still be borked, though.)
+ QCFType<CFDateRef> myDate = QDateTime(date, QTime(12, 0)).toCFDate();
QCFType<CFLocaleRef> mylocale = CFLocaleCopyCurrent();
QCFType<CFDateFormatterRef> myFormatter
= CFDateFormatterCreate(kCFAllocatorDefault, mylocale, style,
kCFDateFormatterNoStyle);
- QCFType<CFStringRef> text = CFDateFormatterCreateStringWithDate(0, myFormatter, myDate);
+ QCFType<CFStringRef> text = CFDateFormatterCreateStringWithDate(nullptr, myFormatter, myDate);
return QString::fromCFString(text);
}
@@ -201,12 +255,14 @@ static QVariant macDateToString(QDate date, bool short_format)
{
const int year = date.year();
QString fakeYear, trueYear;
- if (year < 0) {
+ if (year < 1583) {
// System API (in macOS 11.0, at least) discards sign :-(
// Simply negating the year won't do as the resulting year typically has
// a different pattern of week-days.
+ // Furthermore (see QTBUG-54955), Darwin uses the Julian calendar for
+ // dates before 1582-10-15, leading to discrepancies.
int matcher = QGregorianCalendar::yearSharingWeekDays(date);
- Q_ASSERT(matcher > 0);
+ Q_ASSERT(matcher >= 1583);
Q_ASSERT(matcher % 100 != date.month());
Q_ASSERT(matcher % 100 != date.day());
// i.e. there can't be any confusion between the two-digit year and
@@ -219,7 +275,7 @@ static QVariant macDateToString(QDate date, bool short_format)
QString text = macDateToStringImpl(date, short_format
? kCFDateFormatterShortStyle
: kCFDateFormatterLongStyle);
- if (year < 0) {
+ if (year < 1583) {
if (text.contains(fakeYear))
return std::move(text).replace(fakeYear, trueYear);
// Cope with two-digit year:
@@ -585,13 +641,13 @@ QVariant QSystemLocale::query(QueryType type, QVariant in) const
case CurrencySymbol:
return macCurrencySymbol(QLocale::CurrencySymbolFormat(in.toUInt()));
case CurrencyToString:
- return macFormatCurrency(in.value<QSystemLocale::CurrencyToStringArgument>());
+ return macFormatCurrency(in.value<CurrencyToStringArgument>());
case UILanguages: {
QStringList result;
QCFType<CFArrayRef> languages = CFLocaleCopyPreferredLanguages();
- const int cnt = CFArrayGetCount(languages);
+ const CFIndex cnt = CFArrayGetCount(languages);
result.reserve(cnt);
- for (int i = 0; i < cnt; ++i) {
+ for (CFIndex i = 0; i < cnt; ++i) {
const QString lang = QString::fromCFString(
static_cast<CFStringRef>(CFArrayGetValueAtIndex(languages, i)));
result.append(lang);