diff options
Diffstat (limited to 'src/corelib/text/qlocale_mac.mm')
-rw-r--r-- | src/corelib/text/qlocale_mac.mm | 88 |
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); |