14#include "QtCore/private/qgregoriancalendar_p.h"
16#include <q20algorithm.h>
19#include <qt_windows.h>
22#if QT_CONFIG(cpp_winrt)
23# include <QtCore/private/qt_winrtbase_p.h>
25# include <winrt/Windows.Foundation.h>
26# include <winrt/Windows.Foundation.Collections.h>
27# include <winrt/Windows.System.UserProfile.h>
32using namespace Qt::StringLiterals;
42 const QByteArray lang = qgetenv(
"LANG");
43 if (lang.size() && (lang ==
"C" || qt_splitLocaleName(QString::fromLocal8Bit(lang)))) {
45 const auto [id, used] = qstrntoll(lang.data(), lang.size(), 0);
46 if (used > 0 && id && INT_MIN <= id && id <= INT_MAX)
47 return R {QByteArray(),
static_cast<LCID>(id)};
55 const auto [name, id] = scanLangEnv();
59 if (!name.isEmpty()) {
60 LCID id = LocaleNameToLCID(
static_cast<LPCWSTR>(
61 QString::fromUtf8(name).toStdWString().data()), 0);
66 return GetUserDefaultLCID();
71#ifndef QT_NO_SYSTEMLOCALE
73#ifndef MUI_LANGUAGE_NAME
74#define MUI_LANGUAGE_NAME 0x8
76#ifndef LOCALE_SSHORTESTDAYNAME1
77# define LOCALE_SSHORTESTDAYNAME1 0x0060
78# define LOCALE_SSHORTESTDAYNAME2 0x0061
79# define LOCALE_SSHORTESTDAYNAME3 0x0062
80# define LOCALE_SSHORTESTDAYNAME4 0x0063
81# define LOCALE_SSHORTESTDAYNAME5 0x0064
82# define LOCALE_SSHORTESTDAYNAME6 0x0065
83# define LOCALE_SSHORTESTDAYNAME7 0x0066
85#ifndef LOCALE_SNATIVELANGUAGENAME
86# define LOCALE_SNATIVELANGUAGENAME 0x00000004
88#ifndef LOCALE_SNATIVECOUNTRYNAME
89# define LOCALE_SNATIVECOUNTRYNAME 0x00000008
91#ifndef LOCALE_SSHORTTIME
92# define LOCALE_SSHORTTIME 0x00000079
97static QVariant nullIfEmpty(T &&value)
102 return std::move(value);
139 enum SubstitutionType {
148 SubstitutionType substitutionType = SUnknown;
152 int getLocaleInfo(LCTYPE type, LPWSTR data,
int size);
153 QVariant getLocaleInfo(LCTYPE type);
154 int getLocaleInfo_int(LCTYPE type);
156 int getCurrencyFormat(DWORD flags, LPCWSTR value,
const CURRENCYFMTW *format, LPWSTR data,
int size);
157 int getDateFormat(DWORD flags,
const SYSTEMTIME * date, LPCWSTR format, LPWSTR data,
int size);
158 int getTimeFormat(DWORD flags,
const SYSTEMTIME *date, LPCWSTR format, LPWSTR data,
int size);
160 SubstitutionType substitution();
161 QString substituteDigits(QString &&string);
162 QString correctDigits(QString &&string);
163 QString yearFix(
int year,
int fakeYear, QString &&formatted);
165 static QString winToQtFormat(QStringView sys_fmt);
170QSystemLocalePrivate::QSystemLocalePrivate()
171 : lcid(getDefaultWinId())
175inline int QSystemLocalePrivate::getCurrencyFormat(DWORD flags, LPCWSTR value,
const CURRENCYFMTW *format, LPWSTR data,
int size)
177 return GetCurrencyFormat(lcid, flags, value, format, data, size);
180inline int QSystemLocalePrivate::getDateFormat(DWORD flags,
const SYSTEMTIME * date, LPCWSTR format, LPWSTR data,
int size)
182 return GetDateFormat(lcid, flags, date, format, data, size);
185inline int QSystemLocalePrivate::getTimeFormat(DWORD flags,
const SYSTEMTIME *date, LPCWSTR format, LPWSTR data,
int size)
187 return GetTimeFormat(lcid, flags, date, format, data, size);
192 return GetLocaleInfo(lcid, type, data, size);
202 QVarLengthArray<
wchar_t, 64> buf(64);
204 if (!getLocaleInfo(type, buf.data(), buf.size())) {
205 const auto lastError = GetLastError();
206 if (type == LOCALE_SPOSITIVESIGN && lastError == ERROR_SUCCESS)
208 if (lastError != ERROR_INSUFFICIENT_BUFFER)
210 int cnt = getLocaleInfo(type, 0, 0);
214 if (!getLocaleInfo(type, buf.data(), buf.size()))
217 if (type == LOCALE_SPOSITIVESIGN && !buf[0])
219 return QString::fromWCharArray(buf.data());
225 int r = GetLocaleInfo(lcid, type | LOCALE_RETURN_NUMBER,
226 reinterpret_cast<
wchar_t *>(&value),
227 sizeof(value) /
sizeof(
wchar_t));
228 return r ==
sizeof(value) /
sizeof(
wchar_t) ? value : 0;
233 if (substitutionType == SUnknown) {
235 if (!getLocaleInfo(LOCALE_IDIGITSUBSTITUTION, buf, 8)) {
236 substitutionType = SNever;
237 return substitutionType;
240 substitutionType = SNever;
241 else if (buf[0] ==
'0')
242 substitutionType = SContext;
243 else if (buf[0] ==
'2')
244 substitutionType = SAlways;
247 if (!getLocaleInfo(LOCALE_SNATIVEDIGITS, digits, 11)) {
248 substitutionType = SNever;
249 return substitutionType;
251 if (buf[0] == digits[0] + 2)
252 substitutionType = SAlways;
254 substitutionType = SNever;
257 return substitutionType;
263 switch (zero.size()) {
265 ushort z = zero.at(0).unicode();
269 ushort *
const qch =
reinterpret_cast<ushort *>(string.data());
270 for (qsizetype i = 0, stop = string.size(); i < stop; ++i) {
272 if (ch >=
'0' && ch <=
'9')
273 ch = unicodeForDigit(ch -
'0', z);
279 char32_t z = QChar::surrogateToUcs4(zero.at(0), zero.at(1));
280 for (
int i = 0; i < 10; i++) {
281 char32_t digit = unicodeForDigit(i, z);
282 const QChar s[2] = { QChar::highSurrogate(digit), QChar::lowSurrogate(digit) };
283 string.replace(QString(QLatin1Char(
'0' + i)), QString(s, 2));
288 Q_ASSERT(!
"Expected zero digit to be a single UCS2 code-point or a surrogate pair");
292 return std::move(string);
297 return substitution() == SAlways ? substituteDigits(std::move(string)) : std::move(string);
302 if (zero.isEmpty()) {
304
305
306
307
308
309
311 if (getLocaleInfo(LOCALE_SNATIVEDIGITS, digits, 11)) {
314 zero = QString::fromWCharArray(digits, 1);
317 return nullIfEmpty(zero);
322 return nullIfEmpty(getLocaleInfo(LOCALE_SDECIMAL).toString());
328 wchar_t grouping[10];
330
331
332
333
334
335
336
337 int dataSize = getLocaleInfo(LOCALE_SGROUPING, grouping,
int(std::size(grouping)));
340 QString sysGroupingStr = QString::fromWCharArray(grouping, dataSize);
341 auto tokenized = sysGroupingStr.tokenize(u";");
342 int width[2] = {0, 0};
344 for (
const auto tok : tokenized) {
346 int value = tok.toInt(&ok);
347 if (!ok || !value || index >= 2)
349 width[index++] = value;
362 return QVariant::fromValue(sizes);
367 return getLocaleInfo(LOCALE_STHOUSAND);
372 return nullIfEmpty(getLocaleInfo(LOCALE_SNEGATIVESIGN).toString());
377 return nullIfEmpty(getLocaleInfo(LOCALE_SPOSITIVESIGN).toString());
383 case QLocale::ShortFormat:
384 return nullIfEmpty(winToQtFormat(getLocaleInfo(LOCALE_SSHORTDATE).toString()));
385 case QLocale::LongFormat:
386 return nullIfEmpty(winToQtFormat(getLocaleInfo(LOCALE_SLONGDATE).toString()));
387 case QLocale::NarrowFormat:
396 case QLocale::ShortFormat:
398 case QLocale::LongFormat:
399 return nullIfEmpty(winToQtFormat(getLocaleInfo(LOCALE_STIMEFORMAT).toString()));
400 case QLocale::NarrowFormat:
408 QVariant d = dateFormat(type), t = timeFormat(type);
409 if (d.typeId() == QMetaType::QString && t.typeId() == QMetaType::QString)
410 return QString(d.toString() + u' ' + t.toString());
416 if (day < 1 || day > 7)
419 static constexpr LCTYPE short_day_map[]
420 = { LOCALE_SABBREVDAYNAME1, LOCALE_SABBREVDAYNAME2,
421 LOCALE_SABBREVDAYNAME3, LOCALE_SABBREVDAYNAME4, LOCALE_SABBREVDAYNAME5,
422 LOCALE_SABBREVDAYNAME6, LOCALE_SABBREVDAYNAME7 };
424 static constexpr LCTYPE long_day_map[]
425 = { LOCALE_SDAYNAME1, LOCALE_SDAYNAME2,
426 LOCALE_SDAYNAME3, LOCALE_SDAYNAME4, LOCALE_SDAYNAME5,
427 LOCALE_SDAYNAME6, LOCALE_SDAYNAME7 };
429 static constexpr LCTYPE narrow_day_map[]
435 return nullIfEmpty(getLocaleInfo(
436 (type == QLocale::LongFormat ? long_day_map
437 : type == QLocale::NarrowFormat ? narrow_day_map
438 : short_day_map)[day - 1]).toString());
443 static constexpr LCTYPE short_month_map[]
444 = { LOCALE_SABBREVMONTHNAME1, LOCALE_SABBREVMONTHNAME2, LOCALE_SABBREVMONTHNAME3,
445 LOCALE_SABBREVMONTHNAME4, LOCALE_SABBREVMONTHNAME5, LOCALE_SABBREVMONTHNAME6,
446 LOCALE_SABBREVMONTHNAME7, LOCALE_SABBREVMONTHNAME8, LOCALE_SABBREVMONTHNAME9,
447 LOCALE_SABBREVMONTHNAME10, LOCALE_SABBREVMONTHNAME11, LOCALE_SABBREVMONTHNAME12 };
449 static constexpr LCTYPE long_month_map[]
450 = { LOCALE_SMONTHNAME1, LOCALE_SMONTHNAME2, LOCALE_SMONTHNAME3,
451 LOCALE_SMONTHNAME4, LOCALE_SMONTHNAME5, LOCALE_SMONTHNAME6,
452 LOCALE_SMONTHNAME7, LOCALE_SMONTHNAME8, LOCALE_SMONTHNAME9,
453 LOCALE_SMONTHNAME10, LOCALE_SMONTHNAME11, LOCALE_SMONTHNAME12 };
455 if (month < 1 || month > 12)
459 return nullIfEmpty(getLocaleInfo(
460 (type == QLocale::LongFormat ? long_month_map : short_month_map)[month - 1]).toString());
475 const wchar_t *
const format = type == QLocale::LongFormat ? L"ddMMMM" : L"ddMMM";
477 if (getDateFormat(flags, &st, format, buf, 255) > 2) {
479 return nullIfEmpty(correctDigits(QString::fromWCharArray(buf + 2)));
495 Q_ASSERT(fakeYear >= 1970 && fakeYear <= 2400);
496 const bool matchTwo = year >= 0 && year % 100 == fakeYear % 100;
497 auto yearUsed = fourDigitYear(fakeYear);
498 QString sign(year < 0 ? 1 : 0, u'-');
499 auto trueYear = fourDigitYear(year < 0 ? -year : year);
500 if (formatted.contains(yearUsed))
501 return std::move(formatted).replace(yearUsed, sign + trueYear);
503 auto tail = QStringView{yearUsed}.last(2);
504 Q_ASSERT(!matchTwo || tail == QString(sign + trueYear.last(2)));
505 if (formatted.contains(tail)) {
507 return std::move(formatted);
508 return std::move(formatted).replace(tail.toString(), sign + trueYear.last(2));
513 trueYear = substituteDigits(std::move(trueYear));
515 yearUsed = substituteDigits(std::move(yearUsed));
517 sign = negativeSign().toString();
519 if (formatted.contains(yearUsed))
520 return std::move(formatted).replace(yearUsed, sign + trueYear);
522 const qsizetype twoDigits = 2 * zero.size();
523 tail = QStringView{yearUsed}.last(twoDigits);
524 if (formatted.contains(tail)) {
526 return std::move(formatted);
527 return std::move(formatted).replace(tail.toString(), sign + trueYear.last(twoDigits));
530 qWarning(
"Failed to fix up year in formatted date-string using %d for %d", fakeYear, year);
531 return std::move(formatted);
537 const int year = date.year();
540 const bool fixup = year < 1601;
541 st.wYear = fixup ? QGregorianCalendar::yearSharingWeekDays(date) : year;
542 st.wMonth = date.month();
543 st.wDay = date.day();
545 Q_ASSERT(!fixup || st.wYear % 100 != st.wMonth);
546 Q_ASSERT(!fixup || st.wYear % 100 != st.wDay);
550 DWORD flags = (type == QLocale::LongFormat ? DATE_LONGDATE : DATE_SHORTDATE);
552 if (getDateFormat(flags, &st, NULL, buf, 255)) {
553 QString text = QString::fromWCharArray(buf);
555 text = yearFix(year, st.wYear, std::move(text));
556 return nullIfEmpty(correctDigits(std::move(text)));
564 st.wHour = time.hour();
565 st.wMinute = time.minute();
566 st.wSecond = time.second();
567 st.wMilliseconds = 0;
571 const QString format = type == QLocale::ShortFormat
574 auto formatStr =
reinterpret_cast<
const wchar_t *>(format.isEmpty() ?
nullptr : format.utf16());
577 if (getTimeFormat(flags, &st, formatStr, buf,
int(std::size(buf))))
578 return nullIfEmpty(correctDigits(QString::fromWCharArray(buf)));
584 QVariant d = toString(dt.date(), type), t = toString(dt.time(), type);
585 if (d.typeId() == QMetaType::QString && t.typeId() == QMetaType::QString)
586 return QString(d.toString() + u' ' + t.toString());
594 if (getLocaleInfo(LOCALE_IMEASURE, output, 2)) {
595 if (output[0] == L'1' && !output[1])
596 return QLocale::ImperialSystem;
599 return QLocale::MetricSystem;
604 return getLocaleInfo(LOCALE_SSORTLOCALE);
611 if (getLocaleInfo(LOCALE_S1159, output, 15))
612 return nullIfEmpty(QString::fromWCharArray(output));
621 if (getLocaleInfo(LOCALE_S2359, output, 15))
622 return nullIfEmpty(QString::fromWCharArray(output));
631 if (getLocaleInfo(LOCALE_IFIRSTDAYOFWEEK, output, 4))
632 return QString::fromWCharArray(output).toUInt()+1;
641 case QLocale::CurrencySymbol:
644 if (getLocaleInfo(LOCALE_SCURRENCY, buf, 13))
645 return nullIfEmpty(QString::fromWCharArray(buf));
647 case QLocale::CurrencyIsoCode:
648 if (getLocaleInfo(LOCALE_SINTLSYMBOL, buf, 9))
649 return nullIfEmpty(QString::fromWCharArray(buf));
651 case QLocale::CurrencyDisplayName: {
652 QVarLengthArray<
wchar_t, 64> buf(64);
653 if (!getLocaleInfo(LOCALE_SNATIVECURRNAME, buf.data(), buf.size())) {
654 if (GetLastError() != ERROR_INSUFFICIENT_BUFFER)
657 if (!getLocaleInfo(LOCALE_SNATIVECURRNAME, buf.data(), buf.size()))
660 return nullIfEmpty(QString::fromWCharArray(buf.data()));
671 switch (arg.value.typeId()) {
673 value = QLocaleData::c()->longLongToString(
674 arg.value.toInt(), -1, 10, -1, QLocale::OmitGroupSeparator);
676 case QMetaType::UInt:
677 value = QLocaleData::c()->unsLongLongToString(
678 arg.value.toUInt(), -1, 10, -1, QLocale::OmitGroupSeparator);
680 case QMetaType::Double:
681 value = QLocaleData::c()->doubleToString(
682 arg.value.toDouble(), -1, QLocaleData::DFDecimal, -1, QLocale::OmitGroupSeparator);
684 case QMetaType::LongLong:
685 value = QLocaleData::c()->longLongToString(
686 arg.value.toLongLong(), -1, 10, -1, QLocale::OmitGroupSeparator);
688 case QMetaType::ULongLong:
689 value = QLocaleData::c()->unsLongLongToString(
690 arg.value.toULongLong(), -1, 10, -1, QLocale::OmitGroupSeparator);
696 QVarLengthArray<
wchar_t, 64> out(64);
701 CURRENCYFMT *pformat = NULL;
702 if (!arg.symbol.isEmpty()) {
703 format.NumDigits = getLocaleInfo_int(LOCALE_ICURRDIGITS);
704 format.LeadingZero = getLocaleInfo_int(LOCALE_ILZERO);
705 decimalSep = getLocaleInfo(LOCALE_SMONDECIMALSEP).toString();
706 format.lpDecimalSep =
reinterpret_cast<
wchar_t *>(decimalSep.data());
707 thousandSep = getLocaleInfo(LOCALE_SMONTHOUSANDSEP).toString();
708 format.lpThousandSep =
reinterpret_cast<
wchar_t *>(thousandSep.data());
709 format.NegativeOrder = getLocaleInfo_int(LOCALE_INEGCURR);
710 format.PositiveOrder = getLocaleInfo_int(LOCALE_ICURRENCY);
711 format.lpCurrencySymbol = (
wchar_t *)arg.symbol.utf16();
719 QString groupingStr = getLocaleInfo(LOCALE_SMONGROUPING).toString();
720 format.Grouping = groupingStr.remove(u';').toInt();
721 if (format.Grouping % 10 == 0)
722 format.Grouping /= 10;
724 format.Grouping *= 10;
728 int ret = getCurrencyFormat(0,
reinterpret_cast<
const wchar_t *>(value.utf16()),
729 pformat, out.data(), out.size());
730 if (ret == 0 && GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
731 ret = getCurrencyFormat(0,
reinterpret_cast<
const wchar_t *>(value.utf16()),
732 pformat, out.data(), 0);
734 getCurrencyFormat(0,
reinterpret_cast<
const wchar_t *>(value.utf16()),
735 pformat, out.data(), out.size());
738 return nullIfEmpty(correctDigits(QString::fromWCharArray(out.data())));
744#if QT_CONFIG(cpp_winrt)
745 using namespace winrt::Windows::System::UserProfile;
747 auto languages = GlobalizationPreferences::Languages();
748 for (
const auto &lang : languages)
749 result << QString::fromStdString(winrt::to_string(lang));
753 if (!result.isEmpty())
757 unsigned long cnt = 0;
758 QVarLengthArray<
wchar_t, 64> buf(64);
759# if !defined(QT_BOOTSTRAPPED)
760 unsigned long size = buf.size();
763 if (GetLastError() == ERROR_INSUFFICIENT_BUFFER &&
772 const wchar_t *str = buf.constData();
773 for (; cnt > 0; --cnt) {
774 QString s = QString::fromWCharArray(str);
780 return nullIfEmpty(
std::move(result));
796 lcid = getDefaultWinId();
797 substitutionType = SUnknown;
806 while (i < sys_fmt.size()) {
807 if (sys_fmt.at(i).unicode() == u'\'') {
808 QString text = qt_readEscapedFormatString(sys_fmt, &i);
812 result += u'\'' + text + u'\'';
816 QChar c = sys_fmt.at(i);
817 qsizetype repeat = qt_repeatCount(sys_fmt.mid(i));
819 switch (c.unicode()) {
824 else if (repeat == 3)
834 result += QString(repeat, u'y');
855 result += QString(repeat, c);
865QLocale QSystemLocale::fallbackLocale()
const
867 return QLocale(QString::fromLatin1(getWinLocaleName()));
870QVariant QSystemLocale::query(QueryType type, QVariant &&in)
const
872 QSystemLocalePrivate *d = systemLocalePrivate();
877 return d->decimalPoint();
879 return d->groupingSizes();
881 return d->groupSeparator();
883 return d->negativeSign();
885 return d->positiveSign();
887 return d->dateFormat(QLocale::LongFormat);
888 case DateFormatShort:
889 return d->dateFormat(QLocale::ShortFormat);
891 return d->timeFormat(QLocale::LongFormat);
892 case TimeFormatShort:
893 return d->timeFormat(QLocale::ShortFormat);
894 case DateTimeFormatLong:
895 return d->dateTimeFormat(QLocale::LongFormat);
896 case DateTimeFormatShort:
897 return d->dateTimeFormat(QLocale::ShortFormat);
899 return d->dayName(in.toInt(), QLocale::LongFormat);
901 return d->dayName(in.toInt(), QLocale::ShortFormat);
903 return d->dayName(in.toInt(), QLocale::NarrowFormat);
904 case StandaloneDayNameLong:
905 case StandaloneDayNameShort:
906 case StandaloneDayNameNarrow:
910 return d->monthName(in.toInt(), QLocale::LongFormat);
911 case StandaloneMonthNameLong:
912 return d->standaloneMonthName(in.toInt(), QLocale::LongFormat);
914 return d->monthName(in.toInt(), QLocale::ShortFormat);
915 case StandaloneMonthNameShort:
916 return d->standaloneMonthName(in.toInt(), QLocale::ShortFormat);
917 case MonthNameNarrow:
918 case StandaloneMonthNameNarrow:
921 case DateToStringShort:
922 return d->toString(in.toDate(), QLocale::ShortFormat);
923 case DateToStringLong:
924 return d->toString(in.toDate(), QLocale::LongFormat);
925 case TimeToStringShort:
926 return d->toString(in.toTime(), QLocale::ShortFormat);
927 case TimeToStringLong:
928 return d->toString(in.toTime(), QLocale::LongFormat);
929 case DateTimeToStringShort:
930 return d->toString(in.toDateTime(), QLocale::ShortFormat);
931 case DateTimeToStringLong:
932 return d->toString(in.toDateTime(), QLocale::LongFormat);
934 return d->zeroDigit();
938 QLocaleId lid = QLocaleId::fromName(QString::fromLatin1(getWinLocaleName()));
939 if (type == LanguageId)
940 return lid.language_id;
941 if (type == ScriptId)
942 return lid.script_id ? lid.script_id : ushort(fallbackLocale().script());
943 return lid.territory_id ? lid.territory_id : ushort(fallbackLocale().territory());
945 case MeasurementSystem:
946 return d->measurementSystem();
948 return d->collation();
954 return d->firstDayOfWeek();
956 return d->currencySymbol(QLocale::CurrencySymbolFormat(in.toUInt()));
957 case CurrencyToString:
958 return d->toCurrencyString(in.value<CurrencyToStringArgument>());
960 return d->uiLanguages();
964 case NativeLanguageName:
965 return d->nativeLanguageName();
966 case NativeTerritoryName:
967 return d->nativeTerritoryName();
981struct ByWindowsCode {
1000 { 0x0409,
"en_US" },
1014 { 0x0416,
"pt_BR" },
1038 { 0x0801,
"ar_IQ" },
1039 { 0x0804,
"zh_CN" },
1040 { 0x0807,
"de_CH" },
1041 { 0x0809,
"en_GB" },
1042 { 0x080a,
"es_MX" },
1043 { 0x080c,
"fr_BE" },
1044 { 0x0810,
"it_CH" },
1046 { 0x0813,
"nl_BE" },
1051 { 0x081d,
"sv_FI" },
1052 { 0x0c01,
"ar_EG" },
1053 { 0x0c04,
"zh_HK" },
1054 { 0x0c07,
"de_AT" },
1055 { 0x0c09,
"en_AU" },
1057 { 0x0c0c,
"fr_CA" },
1059 { 0x1001,
"ar_LY" },
1060 { 0x1004,
"zh_SG" },
1061 { 0x1007,
"de_LU" },
1062 { 0x1009,
"en_CA" },
1063 { 0x100a,
"es_GT" },
1064 { 0x100c,
"fr_CH" },
1065 { 0x1401,
"ar_DZ" },
1066 { 0x1407,
"de_LI" },
1067 { 0x1409,
"en_NZ" },
1068 { 0x140a,
"es_CR" },
1069 { 0x140c,
"fr_LU" },
1070 { 0x1801,
"ar_MA" },
1071 { 0x1809,
"en_IE" },
1072 { 0x180a,
"es_PA" },
1073 { 0x1c01,
"ar_TN" },
1074 { 0x1c09,
"en_ZA" },
1075 { 0x1c0a,
"es_DO" },
1076 { 0x2001,
"ar_OM" },
1077 { 0x2009,
"en_JM" },
1078 { 0x200a,
"es_VE" },
1079 { 0x2401,
"ar_YE" },
1081 { 0x240a,
"es_CO" },
1082 { 0x2801,
"ar_SY" },
1083 { 0x2809,
"en_BZ" },
1084 { 0x280a,
"es_PE" },
1085 { 0x2c01,
"ar_JO" },
1086 { 0x2c09,
"en_TT" },
1087 { 0x2c0a,
"es_AR" },
1088 { 0x3001,
"ar_LB" },
1089 { 0x300a,
"es_EC" },
1090 { 0x3401,
"ar_KW" },
1091 { 0x340a,
"es_CL" },
1092 { 0x3801,
"ar_AE" },
1093 { 0x380a,
"es_UY" },
1094 { 0x3c01,
"ar_BH" },
1095 { 0x3c0a,
"es_PY" },
1096 { 0x4001,
"ar_QA" },
1097 { 0x400a,
"es_BO" },
1098 { 0x440a,
"es_SV" },
1099 { 0x480a,
"es_HN" },
1100 { 0x4c0a,
"es_NI" },
1121 return it->iso_name;
1130 return LOCALE_USER_DEFAULT;
1131 if (std::strlen(name) >=
sizeof(WindowsToISOListElt::iso_name))
1132 return LOCALE_USER_DEFAULT;
1137 strncpy(n, name,
sizeof(n));
1149 return LOCALE_USER_DEFAULT;
1161 if (GetLocaleInfo(id, LOCALE_ILANGUAGE, out, 255))
1162 lang_code = QString::fromWCharArray(out);
1164 if (!lang_code.isEmpty()) {
1165 const QByteArray latin1 =
std::move(lang_code).toLatin1();
1166 const auto [i, used] = qstrntoull(latin1.data(), latin1.size(), 16);
1167 if (used >= latin1.size() || (used > 0 && latin1[used] ==
'\0')) {
1178 if (!result.isEmpty())
1182 if (GetLocaleInfo(id, LOCALE_SISO639LANGNAME, out, 255))
1183 result = QString::fromWCharArray(out);
1193 if (GetLocaleInfo(id, LOCALE_SISO3166CTRYNAME, out, 255))
1194 result = QString::fromWCharArray(out);
1201 if (id == LOCALE_USER_DEFAULT) {
1202 const auto [name, lcid] = scanLangEnv();
1203 if (!name.isEmpty())
1206 return winLangCodeToIsoName(lcid);
1208 id = GetUserDefaultLCID();
1211 QString resultusage = winIso639LangName(id);
1212 QString country = winIso3116CtryName(id);
1213 if (!country.isEmpty())
1214 resultusage += u'_' + country;
1216 return std::move(resultusage).toLatin1();
1222 return QLocale(QString::fromLatin1(getWinLocaleName(id)));
1227static QString localeConvertString(
const QString &localeID,
const QString &str,
bool *ok,
1231 LCID lcid = LocaleNameToLCID(
reinterpret_cast<
const wchar_t *>(localeID.constData()), 0);
1233 const int size = LCMapStringW(lcid, flags,
reinterpret_cast<
const wchar_t *>(str.constData()),
1235 QString buf(size, Qt::Uninitialized);
1236 if (lcid == 0 || size == 0
1237 || LCMapStringW(lcid, flags,
reinterpret_cast<
const wchar_t *>(str.constData()), str.size(),
1238 reinterpret_cast<
wchar_t *>(buf.data()), buf.size()) == 0) {
1248QString QLocalePrivate::toLower(
const QString &str,
bool *ok)
const
1250 return localeConvertString(QString::fromUtf8(bcp47Name()), str, ok,
1251 LCMAP_LOWERCASE | LCMAP_LINGUISTIC_CASING);
1254QString QLocalePrivate::toUpper(
const QString &str,
bool *ok)
const
1256 return localeConvertString(QString::fromUtf8(bcp47Name()), str, ok,
1257 LCMAP_UPPERCASE | LCMAP_LINGUISTIC_CASING);
LCID qt_inIsoNametoLCID(const char *name)
static constexpr WindowsToISOListElt windows_to_iso_list[]
static QByteArray getWinLocaleName(LCID id=LOCALE_USER_DEFAULT)
static QString fourDigitYear(int year)
#define LOCALE_SSHORTESTDAYNAME2
static auto scanLangEnv()
#define LOCALE_SSHORTTIME
#define LOCALE_SSHORTESTDAYNAME4
#define LOCALE_SSHORTESTDAYNAME3
#define LOCALE_SSHORTESTDAYNAME7
#define LOCALE_SSHORTESTDAYNAME5
#define LOCALE_SNATIVELANGUAGENAME
static QString winIso3116CtryName(LCID id)
#define LOCALE_SSHORTESTDAYNAME6
#define LOCALE_SNATIVECOUNTRYNAME
static auto getDefaultWinId()
#define MUI_LANGUAGE_NAME
static const char * winLangCodeToIsoName(int code)
#define LOCALE_SSHORTESTDAYNAME1
static QString winIso639LangName(LCID id)
#define QStringLiteral(str)
QVariant dateFormat(QLocale::FormatType)
QVariant toString(QDate, QLocale::FormatType)
QVariant dayName(int, QLocale::FormatType)
QVariant firstDayOfWeek()
QVariant monthName(int, QLocale::FormatType)
QVariant currencySymbol(QLocale::CurrencySymbolFormat)
QVariant nativeLanguageName()
QVariant toString(QTime, QLocale::FormatType)
QVariant standaloneMonthName(int, QLocale::FormatType)
QVariant nativeTerritoryName()
QVariant dateTimeFormat(QLocale::FormatType)
QVariant toString(const QDateTime &, QLocale::FormatType)
QVariant measurementSystem()
QVariant groupSeparator()
QVariant timeFormat(QLocale::FormatType)
QVariant toCurrencyString(const QSystemLocale::CurrencyToStringArgument &)