27 #include "config-localization.h"
32 #ifdef HAVE_SYS_TIME_H
42 #include <QtCore/QTextCodec>
43 #include <QtCore/QFile>
44 #include <QtGui/QPrinter>
45 #include <QtCore/QFileInfo>
46 #include <QtCore/QRegExp>
47 #include <QtCore/QLocale>
48 #include <QtCore/QHash>
49 #include <QtCore/QMutexLocker>
50 #include <QtCore/QStringList>
67 class KLocaleStaticData
79 KLocaleStaticData::KLocaleStaticData()
103 return debug << cn.name << cn.loadCount;
115 m_codecForEncoding(0)
133 return m_config.
data();
145 m_config = rhs.m_config;
148 m_country = rhs.m_country;
149 m_countryDivisionCode = rhs.m_countryDivisionCode;
152 m_language = rhs.m_language;
154 m_languageList = rhs.m_languageList;
155 m_languageSensitiveDigits = rhs.m_languageSensitiveDigits;
156 m_nounDeclension = rhs.m_nounDeclension;
159 m_catalogName = rhs.m_catalogName;
160 m_catalogNames = rhs.m_catalogNames;
161 m_catalogs = rhs.m_catalogs;
162 m_numberOfSysCatalogs = rhs.m_numberOfSysCatalogs;
163 m_useTranscript = rhs.m_useTranscript;
166 m_calendarSystem = rhs.m_calendarSystem;
168 m_weekStartDay = rhs.m_weekStartDay;
169 m_workingWeekStartDay = rhs.m_workingWeekStartDay;
170 m_workingWeekEndDay = rhs.m_workingWeekEndDay;
171 m_weekDayOfPray = rhs.m_weekDayOfPray;
174 m_dateFormat = rhs.m_dateFormat;
175 m_dateFormatShort = rhs.m_dateFormatShort;
176 m_timeFormat = rhs.m_timeFormat;
177 m_dateTimeDigitSet = rhs.m_dateTimeDigitSet;
178 m_dateMonthNamePossessive = rhs.m_dateMonthNamePossessive;
179 m_dayPeriods = rhs.m_dayPeriods;
180 m_weekNumberSystem = rhs.m_weekNumberSystem;
183 m_decimalPlaces = rhs.m_decimalPlaces;
184 m_decimalSymbol = rhs.m_decimalSymbol;
185 m_thousandsSeparator = rhs.m_thousandsSeparator;
186 m_numericDigitGrouping = rhs.m_numericDigitGrouping;
187 m_positiveSign = rhs.m_positiveSign;
188 m_negativeSign = rhs.m_negativeSign;
189 m_digitSet = rhs.m_digitSet;
192 m_currencyCode = rhs.m_currencyCode;
194 m_currencyCodeList = rhs.m_currencyCodeList;
197 m_currencySymbol = rhs.m_currencySymbol;
198 m_monetaryDecimalSymbol = rhs.m_monetaryDecimalSymbol;
199 m_monetaryThousandsSeparator = rhs.m_monetaryThousandsSeparator;
200 m_monetaryDigitGrouping = rhs.m_monetaryDigitGrouping;
201 m_monetaryDecimalPlaces = rhs.m_monetaryDecimalPlaces;
202 m_positiveMonetarySignPosition = rhs.m_positiveMonetarySignPosition;
203 m_negativeMonetarySignPosition = rhs.m_negativeMonetarySignPosition;
204 m_positivePrefixCurrencySymbol = rhs.m_positivePrefixCurrencySymbol;
205 m_negativePrefixCurrencySymbol = rhs.m_negativePrefixCurrencySymbol;
206 m_monetaryDigitSet = rhs.m_monetaryDigitSet;
209 m_binaryUnitDialect = rhs.m_binaryUnitDialect;
210 m_byteSizeFmt = rhs.m_byteSizeFmt;
211 m_pageSize = rhs.m_pageSize;
212 m_measureSystem = rhs.m_measureSystem;
215 m_encoding = rhs.m_encoding;
216 m_codecForEncoding = rhs.m_codecForEncoding;
217 m_utf8FileEncoding = rhs.m_utf8FileEncoding;
232 m_catalogName = catalogName;
236 m_config = persistantConfig;
240 bool useEnvironmentVariables;
248 cg = m_config->
group(QLatin1String(
"Locale"));
249 useEnvironmentVariables =
false;
250 }
else if (tempConfig == 0 || tempConfig ==
KGlobal::config().data()) {
252 useEnvironmentVariables =
true;
254 cg = tempConfig->
group(QLatin1String(
"Locale"));
255 useEnvironmentVariables =
false;
298 KLocaleStaticData *s = staticData;
301 if (!s->maincatalog.isEmpty()) {
304 m_catalogName = s->maincatalog;
307 if (m_catalogName.isEmpty()) {
308 kDebug(173) <<
"KLocale instance created called without valid "
309 <<
"catalog! Give an argument or call setMainCatalog "
310 <<
"before init" << endl;
316 const int numberOfCatalogs = m_catalogNames.size();
317 m_catalogNames.append(
KCatalogName(QString::fromLatin1(
"libphonon")));
318 m_catalogNames.append(
KCatalogName(QString::fromLatin1(
"kio4")));
319 m_catalogNames.append(
KCatalogName(QString::fromLatin1(
"kdelibs4")));
320 m_catalogNames.append(
KCatalogName(QString::fromLatin1(
"kdeqt")));
321 m_catalogNames.append(
KCatalogName(QString::fromLatin1(
"solid_qt")));
322 m_catalogNames.append(
KCatalogName(QString::fromLatin1(
"kdecalendarsystems")));
323 m_numberOfSysCatalogs = m_catalogNames.size() - numberOfCatalogs;
331 QByteArray var(qgetenv(variable));
332 if (!var.isEmpty()) {
333 QString value = QFile::decodeName(var);
334 if (isLanguageList) {
335 list += value.split(QLatin1Char(
':'));
338 QString lang, ctry, modf, cset;
341 if (!ctry.isEmpty() && !modf.isEmpty()) {
342 list += lang + QLatin1Char(
'_') + ctry + QLatin1Char(
'@') + modf;
347 if (!modf.isEmpty()) {
348 list += lang + QLatin1Char(
'@') + modf;
350 if (!ctry.isEmpty()) {
351 list += lang + QLatin1Char(
'_') + ctry;
368 if ( putativeCountry.isEmpty() || !validCountries.contains( putativeCountry, Qt::CaseInsensitive ) ) {
371 putativeCountry = configCountry;
373 if ( putativeCountry.isEmpty() || !validCountries.contains( putativeCountry, Qt::CaseInsensitive ) ) {
378 if ( putativeCountry.isEmpty() || !validCountries.contains( putativeCountry, Qt::CaseInsensitive ) ) {
389 m_country = putativeCountry.toLower();
398 splitLocale( QLocale::system().name(), s1, systemCountry, s2, s3 );
399 return systemCountry.toLower();
403 bool useEnvironmentVariables)
415 if (!m_language.isEmpty()) {
422 if (useEnvironmentVariables) {
427 if (!configLanguages.isEmpty()) {
428 list += configLanguages.split(QLatin1Char(
':'));
431 if (useEnvironmentVariables) {
463 if (cg.
hasKey(
"FracDigits")) {
465 if (!fracDigits.isEmpty()) {
467 cg.
writeEntry(
"MonetaryDecimalPlaces", fracDigits);
474 #define readConfigEntry(key, default, save) \
475 save = entry.readEntry(key, default); \
476 save = cg.readEntry(key, save);
478 #define readConfigNumEntry(key, default, save, type) \
479 save = (type)entry.readEntry(key, int(default)); \
480 save = (type)cg.readEntry(key, int(save));
490 m_thousandsSeparator.remove(QString::fromLatin1(
"$0"));
493 m_numericDigitGrouping = digitGroupFormatToList(digitGroupFormat);
500 readConfigEntry(
"LanguageSensitiveDigits",
true, m_languageSensitiveDigits);
511 readConfigEntry(
"MonetaryDecimalSymbol",
".", m_monetaryDecimalSymbol);
512 readConfigEntry(
"MonetaryThousandsSeparator",
",", m_monetaryThousandsSeparator);
513 m_monetaryThousandsSeparator.remove(QString::fromLatin1(
"$0"));
514 readConfigEntry(
"MonetaryDigitGroupFormat",
"3", digitGroupFormat);
515 m_monetaryDigitGrouping = digitGroupFormatToList(digitGroupFormat);
517 readConfigEntry(
"PositivePrefixCurrencySymbol",
true, m_positivePrefixCurrencySymbol);
518 readConfigEntry(
"NegativePrefixCurrencySymbol",
true, m_negativePrefixCurrencySymbol);
530 readConfigEntry(
"TimeFormat",
"%H:%M:%S", m_timeFormat);
531 readConfigEntry(
"DateFormat",
"%A %d %B %Y", m_dateFormat);
532 readConfigEntry(
"DateFormatShort",
"%Y-%m-%d", m_dateFormatShort);
543 #ifndef QT_NO_PRINTER
548 readConfigEntry(
"CalendarSystem",
"gregorian", calendarType);
551 readConfigEntry(
"Transcript",
true, m_useTranscript);
557 #define read3ConfigBoolEntry(key, default, save) \
558 save = entry.readEntry(key, default); \
559 save = lang.readEntry(key, save); \
560 save = cg.readEntry(key, save);
577 m_dayPeriods.clear();
578 QString periodKey = QString::fromLatin1(
"DayPeriod1");
580 while (cg.
hasKey(periodKey)) {
582 if (period.count() == 8) {
583 m_dayPeriods.append(
KDayPeriod(period[0], period[1], period[2], period[3],
584 QTime::fromString(period[4], QString::fromLatin1(
"HH:mm:ss.zzz")),
585 QTime::fromString(period[5], QString::fromLatin1(
"HH:mm:ss.zzz")),
586 period[6].toInt(), period[7].toInt()));
589 periodKey = QString::fromLatin1(
"DayPeriod%1").arg(i);
601 if (putativeCountry.isEmpty()) {
604 if (putativeCountry.isEmpty() || !validCountries.contains(putativeCountry, Qt::CaseInsensitive)) {
608 }
else if (!validCountries.contains(putativeCountry, Qt::CaseInsensitive)) {
616 m_country = putativeCountry.toLower();
638 m_languageList.removeAll(language);
639 m_languageList.prepend(language);
677 list.append(language);
688 m_language = list.first();
690 m_languageList = list;
713 if (!newCurrencyCode.isEmpty() && newCurrencyCode != m_currency->
isoCurrencyCode() &&
715 m_currencyCode = newCurrencyCode;
722 if (lang.isEmpty()) {
731 if (m_catalogName.isEmpty()) {
732 kDebug() <<
"no appName!";
754 int f = locale.indexOf(QLatin1Char(
':'));
759 f = locale.indexOf(QLatin1Char(
'.'));
761 charset = locale.mid(f + 1);
765 f = locale.indexOf(QLatin1Char(
'@'));
767 modifier = locale.mid(f + 1);
771 f = locale.indexOf(QLatin1Char(
'_'));
773 country = locale.mid(f + 1);
792 if (m_countryDivisionCode.isEmpty()) {
795 return m_countryDivisionCode;
809 return m_currencyCode;
815 int pos = m_catalogNames.indexOf(
KCatalogName(catalog));
817 ++m_catalogNames[pos].loadCount;
823 m_catalogNames.insert(m_catalogNames.size() - m_numberOfSysCatalogs,
KCatalogName(catalog));
840 foreach(
const QString &lang, m_languageList) {
857 m_catalogs = newCatalogs;
864 int pos = m_catalogNames.indexOf(
KCatalogName(catalog));
868 if (--m_catalogNames[pos].loadCount > 0) {
871 m_catalogNames.removeAt(pos);
881 int pos = m_catalogNames.indexOf(
KCatalogName(catalog));
885 m_catalogNames.move(pos, 0);
893 if (!msgid || !msgid[0]) {
894 kDebug(173) <<
"KLocale: trying to look up \"\" in catalog. "
895 <<
"Fix the program" << endl;
897 translation->clear();
900 if (msgctxt && !msgctxt[0]) {
901 kDebug(173) <<
"KLocale: trying to use \"\" as context to message. "
902 <<
"Fix the program" << endl;
904 if (msgid_plural && !msgid_plural[0]) {
905 kDebug(173) <<
"KLocale: trying to use \"\" as plural message. "
906 <<
"Fix the program" << endl;
912 if (msgid_plural == NULL) {
913 fallback = QString::fromUtf8(msgid);
916 fallback = QString::fromUtf8(msgid);
918 fallback = QString::fromUtf8(msgid_plural);
925 *translation = fallback;
935 if (catname != NULL) {
936 catNameDecoded = QString::fromUtf8(catname);
947 if (catNameDecoded.isEmpty() || catNameDecoded == (*it).name()) {
949 if (msgctxt != NULL && msgid_plural != NULL) {
950 text = (*it).translateStrict(msgctxt, msgid, msgid_plural, n);
951 }
else if (msgid_plural != NULL) {
952 text = (*it).translateStrict(msgid, msgid_plural, n);
953 }
else if (msgctxt != NULL) {
954 text = (*it).translateStrict(msgctxt, msgid);
956 text = (*it).translateStrict(msgid);
959 if (!text.isEmpty()) {
962 *language = (*it).language();
997 if (!sourceText || !sourceText[0]) {
998 kDebug(173) <<
"KLocale: trying to look up \"\" in catalog. "
999 <<
"Fix the program" << endl;
1013 if (comment && comment[0]) {
1018 if (context && context[0]) {
1059 return QString::fromUtf8(
"٠١٢٣٤٥٦٧٨٩");
1061 return QString::fromUtf8(
"০১২৩৪৫৬৭৮৯");
1063 return QString::fromUtf8(
"०१२३४५६७८९");
1065 return QString::fromUtf8(
"۰۱۲۳۴۵۶۷۸۹");
1067 return QString::fromUtf8(
"૦૧૨૩૪૫૬૭૮૯");
1069 return QString::fromUtf8(
"੦੧੨੩੪੫੬੭੮੯");
1071 return QString::fromUtf8(
"೦೧೨೩೪೫೬೭೮೯");
1073 return QString::fromUtf8(
"០១២៣៤៥៦៧៨៩");
1075 return QString::fromUtf8(
"൦൧൨൩൪൫൬൭൮൯");
1077 return QString::fromUtf8(
"୦୧୨୩୪୫୬୭୮୯");
1079 return QString::fromUtf8(
"௦௧௨௩௪௫௬௭௮");
1081 return QString::fromUtf8(
"౦౧౨౩౪౫౬౭౯");
1083 return QString::fromUtf8(
"๐๑๒๓๔๕๖๗๘๙");
1085 return QString::fromUtf8(
"0123456789");
1094 name =
i18nc(
"digit set",
"Arabic-Indic");
1097 name =
i18nc(
"digit set",
"Bengali");
1100 name =
i18nc(
"digit set",
"Devanagari");
1103 name =
i18nc(
"digit set",
"Eastern Arabic-Indic");
1106 name =
i18nc(
"digit set",
"Gujarati");
1109 name =
i18nc(
"digit set",
"Gurmukhi");
1112 name =
i18nc(
"digit set",
"Kannada");
1115 name =
i18nc(
"digit set",
"Khmer");
1118 name =
i18nc(
"digit set",
"Malayalam");
1121 name =
i18nc(
"digit set",
"Oriya");
1124 name =
i18nc(
"digit set",
"Tamil");
1127 name =
i18nc(
"digit set",
"Telugu");
1130 name =
i18nc(
"digit set",
"Thai");
1133 name =
i18nc(
"digit set",
"Arabic");
1137 QString nameWithDigits =
i18nc(
"name of digit set with digit string, "
1138 "e.g. 'Arabic (0123456789)'",
"%1 (%2)", name, digits);
1139 return nameWithDigits;
1147 if (!ignoreContext) {
1151 KLocaleStaticData *s = staticData;
1152 if (m_languageSensitiveDigits && !s->languagesUsingDigitSet[digitSet].contains(m_language)) {
1159 foreach(
const QChar &c, str) {
1161 nstr += digitDraw[c.digitValue()];
1172 foreach(
const QChar &c, str) {
1174 nstr += QChar(
'0' + c.digitValue());
1184 return m_nounDeclension;
1189 return m_dateMonthNamePossessive;
1194 return m_weekStartDay;
1199 return m_workingWeekStartDay;
1204 return m_workingWeekEndDay;
1209 return m_weekDayOfPray;
1214 return m_decimalPlaces;
1219 return m_decimalSymbol;
1224 return m_thousandsSeparator;
1229 return m_numericDigitGrouping;
1234 return m_currencySymbol;
1239 return m_monetaryDecimalSymbol;
1244 return m_monetaryThousandsSeparator;
1249 return m_monetaryDigitGrouping;
1254 return m_positiveSign;
1259 return m_negativeSign;
1271 return m_monetaryDecimalPlaces;
1276 return m_positivePrefixCurrencySymbol;
1281 return m_negativePrefixCurrencySymbol;
1286 return m_positiveMonetarySignPosition;
1291 return m_negativeMonetarySignPosition;
1296 for (
int l = 0; l < s.length(); l++) {
1297 buffer[index++] = s.at(l);
1301 static inline void put_it_in(QChar *buffer,
int &index,
int number)
1303 buffer[index++] = number / 10 +
'0';
1304 buffer[index++] = number % 10 +
'0';
1308 QList<int> KLocalePrivate::digitGroupFormatToList(
const QString &digitGroupFormat)
const
1311 QStringList stringList = digitGroupFormat.split(QLatin1Char(
';'));
1312 foreach(
const QString &size, stringList) {
1313 groupList.append(size.toInt());
1321 if (groupList.isEmpty() || groupSeparator.isEmpty()) {
1326 int groupCount = groupList.count();
1328 int groupSize = groupList.at(groupAt);
1329 int pos = num.indexOf(decimalSeperator);
1333 pos = pos - groupSize;
1335 while (pos > 0 && groupSize > 0) {
1336 num.insert(pos, groupSeparator);
1337 if (groupAt + 1 < groupCount) {
1339 groupSize = groupList.at(groupAt);
1341 pos = pos - groupSize;
1353 if (!groupSeparator.isEmpty()) {
1354 if (!groupList.isEmpty()) {
1355 int separatorSize = groupSeparator.length();
1356 int groupCount = groupList.count();
1358 int groupSize = groupList.at(groupAt);
1359 int pos = number.indexOf(decimalSeparator);
1361 pos = number.length();
1363 pos = pos - groupSize - separatorSize;
1365 while (pos > 0 && valid && groupSize > 0) {
1366 if (num.mid(pos, separatorSize) == groupSeparator) {
1367 num.remove(pos, separatorSize);
1368 if (groupAt + 1 < groupCount) {
1370 groupSize = groupList.at(groupAt);
1372 pos = pos - groupSize - separatorSize;
1379 if (num.contains(groupSeparator)) {
1381 num = num.remove(groupSeparator);
1395 QString currencyString = symbol;
1396 if (symbol.isNull()) {
1399 if (precision < 0) {
1405 QString res = QString::number(neg ? -num : num,
'f', precision);
1423 res.prepend(QLatin1Char(
'('));
1424 res.append(QLatin1Char(
')'));
1433 currencyString.prepend(sign);
1436 currencyString.append(sign);
1442 res.prepend(QLatin1Char(
' '));
1443 res.prepend(currencyString);
1445 res.append(QLatin1Char(
' '));
1446 res.append(currencyString);
1458 if (precision < 0) {
1462 return formatNumber(QString::number(num,
'f', precision),
false, 0);
1473 for (
int i = position; i >= 0; i--) {
1474 char last_char = str[i].toLatin1();
1475 switch (last_char) {
1505 if (i == 0) str.prepend(QLatin1Char(
'1'));
1517 int decimalSymbolPos = str.indexOf(QLatin1Char(
'.'));
1519 if (decimalSymbolPos == -1) {
1520 if (precision == 0)
return;
1521 else if (precision > 0) {
1522 str.append(QLatin1Char(
'.'));
1523 decimalSymbolPos = str.length() - 1;
1527 str.reserve(str.length() + precision);
1528 for (
int i = 0; i < precision; ++i)
1529 str.append(QLatin1Char(
'0'));
1532 char last_char = str[decimalSymbolPos + precision + 1].toLatin1();
1533 switch (last_char) {
1552 decimalSymbolPos = str.indexOf(QLatin1Char(
'.'));
1553 str.truncate(decimalSymbolPos + precision + 1);
1556 if (precision == 0) {
1557 str = str.left(decimalSymbolPos);
1567 if (precision < 0) {
1572 const bool neg = (tmpString[0] == QLatin1Char(
'-'));
1573 if (neg || tmpString[0] == QLatin1Char(
'+')) {
1574 tmpString.remove(0, 1);
1580 const int expPos = tmpString.indexOf(QLatin1Char(
'e'));
1581 QString mantString = tmpString.left(expPos);
1584 expString = tmpString.mid(expPos);
1585 if (expString.length() == 1) {
1592 if (mantString.isEmpty() || !mantString[0].isDigit()) {
1593 mantString = QLatin1Char(
'0');
1597 _round(mantString, precision);
1615 return mantString + expString;
1626 #define CACHE_BYTE_FMT(ctxt_text) \
1627 translateRawFrom(0, ctxt_text, 0, 0, 0, &s); \
1628 binaryUnits.append(s);
1705 dialect = m_binaryUnitDialect;
1714 if (dialect == m_binaryUnitDialect) {
1716 if (m_byteSizeFmt.size() == 0) {
1723 dialectUnits = m_byteSizeFmt;
1729 double multiplier = 1024.0;
1732 multiplier = 1000.0;
1744 unit =
static_cast<int>(specificUnit);
1746 size /= pow(multiplier, unit);
1755 return dialectUnits[unit].arg(
formatNumber(size, precision));
1765 return m_binaryUnitDialect;
1772 m_binaryUnitDialect = newDialect;
1773 m_byteSizeFmt.clear();
1779 if (mSec >= 24*3600000) {
1780 return i18nc(
"@item:intext %1 is a real number, e.g. 1.23 days",
"%1 days",
1782 }
else if (mSec >= 3600000) {
1783 return i18nc(
"@item:intext %1 is a real number, e.g. 1.23 hours",
"%1 hours",
1785 }
else if (mSec >= 60000) {
1786 return i18nc(
"@item:intext %1 is a real number, e.g. 1.23 minutes",
"%1 minutes",
1788 }
else if (mSec >= 1000) {
1789 return i18nc(
"@item:intext %1 is a real number, e.g. 1.23 seconds",
"%1 seconds",
1792 return i18ncp(
"@item:intext",
"%1 millisecond",
"%1 milliseconds", mSec);
1797 switch (durationType) {
1799 return i18ncp(
"@item:intext",
"1 day",
"%1 days", n);
1801 return i18ncp(
"@item:intext",
"1 hour",
"%1 hours", n);
1803 return i18ncp(
"@item:intext",
"1 minute",
"%1 minutes", n);
1805 return i18ncp(
"@item:intext",
"1 second",
"%1 seconds", n);
1812 unsigned long ms = mSec;
1813 int days = ms / (24 * 3600000);
1814 ms = ms % (24 * 3600000);
1815 int hours = ms / 3600000;
1817 int minutes = ms / 60000;
1819 int seconds = qRound(ms / 1000.0);
1823 if (seconds == 60) {
1827 if (days && hours) {
1828 return i18nc(
"@item:intext days and hours. This uses the previous item:intext messages. If this does not fit the grammar of your language please contact the i18n team to solve the problem",
1833 }
else if (hours && minutes) {
1834 return i18nc(
"@item:intext hours and minutes. This uses the previous item:intext messages. If this does not fit the grammar of your language please contact the i18n team to solve the problem",
1840 }
else if (minutes && seconds) {
1841 return i18nc(
"@item:intext minutes and seconds. This uses the previous item:intext messages. If this does not fit the grammar of your language please contact the i18n team to solve the problem",
1845 }
else if (minutes) {
1859 KLocaleStaticData *s = staticData;
1860 s->maincatalog = QString::fromUtf8(catalog);
1873 str = str.trimmed();
1877 str = str.trimmed();
1878 }
else if (
negativeSign().isEmpty() && str[0].isDigit()) {
1888 EPos = str.indexOf(QLatin1Char(
'E'), 0, Qt::CaseInsensitive);
1891 exponentialPart = str.mid(EPos);
1892 str = str.left(EPos);
1893 str = str.trimmed();
1897 bool groupOk =
true;
1916 major = str.left(pos);
1921 bool digitTest =
true;
1922 foreach (
const QChar &ch, major) {
1923 if (!ch.isDigit()) {
1928 foreach (
const QChar &ch, minor) {
1929 if (!ch.isDigit()) {
1943 tot = QLatin1Char(
'-');
1945 tot += major + QLatin1Char(
'.') + minor + exponentialPart;
1947 return tot.toDouble(ok);
1954 bool currencyFound =
false;
1958 int pos = str.indexOf(symbol);
1959 if (pos == 0 || pos == (
int) str.length() - symbol.length()) {
1960 str.remove(pos, symbol.length());
1961 str = str.trimmed();
1962 currencyFound =
true;
1964 if (str.isEmpty()) {
1972 if (str[0] == QLatin1Char(
'(') && str[str.length()-1] == QLatin1Char(
')')) {
1976 str.remove(str.length() - 1, 1);
1978 str = str.trimmed();
1984 if (!negSign.isEmpty() && (str.left(negLen) == negSign || str.right(negSign.length()) == negSign)) {
1991 if (!posSign.isEmpty() && (str.left(posLen) == posSign || str.right(posSign.length()) == posSign)) {
1994 }
else if (negSign.isEmpty() && str[0].isDigit() && str[str.length() - 1].isDigit()){
1998 if (!sign.isEmpty()) {
1999 if (str.left(len) == sign) {
2002 str.remove(str.length() - len, len);
2004 str = str.trimmed();
2010 if (!currencyFound) {
2011 pos = str.indexOf(symbol);
2012 if (pos == 0 || pos == (
int) str.length() - symbol.length()) {
2013 str.remove(pos, symbol.length());
2014 str = str.trimmed();
2019 bool groupOk =
true;
2039 major = str.left(pos);
2044 bool digitTest =
true;
2045 foreach (
const QChar &ch, major) {
2046 if (!ch.isDigit()) {
2051 foreach (
const QChar &ch, minor) {
2052 if (!ch.isDigit()) {
2066 tot = QLatin1Char(
'-');
2068 tot += major + QLatin1Char(
'.') + minor;
2070 return tot.toDouble(ok);
2081 if (!str.at(pos).isDigit()) {
2085 for (; str.length() > pos && str.at(pos).isDigit(); ++pos) {
2087 result += str.at(pos).digitValue();
2111 if (time.isValid()) {
2128 int remPos = inout.indexOf(strip2char);
2132 int endPos = remPos + 2;
2133 int curPos = remPos - 1;
2134 while (curPos >= 0 && inout.at(curPos).isSpace()) {
2139 if (curPos >= 0 && inout.at(curPos).isPunct() && inout.at(curPos) != QLatin1Char(
'%')) {
2142 while (curPos >= 0 && inout.at(curPos).isSpace()) {
2146 remPos = qMax(curPos + 1, 0);
2147 inout.remove(remPos, endPos - remPos);
2155 int remPos = inout.indexOf(strip2char);
2159 int curPos = remPos + 2;
2160 while (curPos < inout.size() &&
2161 (inout.at(curPos).isSpace() ||
2162 (inout.at(curPos).isPunct() && inout.at(curPos) != QLatin1Char(
'%')))) {
2165 inout.remove(remPos, curPos - remPos);
2175 int length = inout.size();
2176 int ppos = inout.indexOf(QLatin1String(
"%p"));
2179 }
else if (ppos == 0) {
2182 while (ppos < length && (inout.at(ppos).isSpace() || inout.at(ppos).isPunct()) &&
2183 inout.at(ppos) != QLatin1Char(
'%')) {
2186 inout = inout.mid(ppos);
2193 KLocale::TimeProcessingOptions processing)
const
2195 QString str(intstr.simplified().toLower());
2201 bool useDayPeriod =
false;
2232 while (!error && (format.length() > formatpos || str.length() > strpos)) {
2233 if (!(format.length() > formatpos && str.length() > strpos)) {
2238 QChar c = format.at(formatpos++);
2241 if (!str.at(strpos).isSpace()) {
2248 if (str.at(strpos).isSpace()) {
2255 if (c != QLatin1Char(
'%')) {
2256 if (c != str.at(strpos++)) {
2263 c = format.at(formatpos++);
2264 switch (c.unicode()) {
2272 int len = dayPeriodText.length();
2273 if (str.mid(strpos, len) == dayPeriodText.toLower()) {
2274 dayPeriod = testDayPeriod;
2277 useDayPeriod =
true;
2286 useDayPeriod =
false;
2292 useDayPeriod = !isDuration;
2297 minute =
readInt(str, strpos);
2302 minute = minute % 60;
2307 second =
readInt(str, strpos);
2318 returnTime = dayPeriod.
time(hour, minute, second);
2320 returnTime = QTime(hour, minute, second);
2324 *ok = returnTime.isValid();
2370 QChar *buffer =
new QChar[rst.length() * 3 / 2 + 32];
2373 bool escape =
false;
2376 for (
int format_index = 0; format_index < rst.length(); format_index++) {
2378 if (rst.at(format_index).unicode() ==
'%') {
2381 buffer[index++] = rst.at(format_index);
2384 switch (rst.at(format_index).unicode()) {
2386 buffer[index++] = QLatin1Char(
'%');
2400 put_it_in(buffer, index, QString::number(time.hour() * 60 + time.minute()));
2402 put_it_in(buffer, index, time.minute());
2406 put_it_in(buffer, index, time.second());
2411 if (!isDuration && rst.at(format_index).unicode() ==
'l') {
2414 number = time.hour();
2417 buffer[index++] = number / 10 +
'0';
2419 buffer[index++] = number % 10 +
'0';
2427 buffer[index++] = rst.at(format_index);
2436 return ret.trimmed();
2441 if ((
timeFormat().contains(QString::fromLatin1(
"%I")) > 0) ||
2442 (
timeFormat().contains(QString::fromLatin1(
"%l")) > 0)) {
2451 if (dayPeriods.count() > 0) {
2452 foreach (
const KDayPeriod &dayPeriod, dayPeriods) {
2467 if (m_dayPeriods.isEmpty()) {
2468 m_dayPeriods.append(
KDayPeriod(QString::fromLatin1(
"am"),
2469 i18nc(
"Before Noon KLocale::LongName",
"Ante Meridiem" ),
2470 i18nc(
"Before Noon KLocale::ShortName",
"AM" ),
2471 i18nc(
"Before Noon KLocale::NarrowName",
"A" ),
2472 QTime( 0, 0, 0 ), QTime( 11, 59, 59, 999 ), 0, 12 ));
2473 m_dayPeriods.append(
KDayPeriod(QString::fromLatin1(
"pm"),
2474 i18nc(
"After Noon KLocale::LongName",
"Post Meridiem" ),
2475 i18nc(
"After Noon KLocale::ShortName",
"PM" ),
2476 i18nc(
"After Noon KLocale::NarrowName",
"P" ),
2477 QTime( 12, 0, 0 ), QTime( 23, 59, 59, 999 ), 0, 12 ));
2479 return m_dayPeriods;
2484 if (time.isValid()) {
2486 if (dayPeriod.
isValid(time)) {
2496 return m_languageList;
2501 return m_currencyCodeList;
2505 bool includeSeconds,
int daysTo,
int secsTo)
2512 if ((daysTo == 0 && secsTo > 3600) || daysTo < 0 || daysTo > 6) {
2524 dateStr =
i18n(
"Today");
2527 dateStr =
i18n(
"Yesterday");
2533 dateStr = locale->
formatDate(dateTime.date(), format);
2537 if (includeSeconds) {
2543 return i18nc(
"concatenation of dates and time",
"%1 %2", dateStr,
2549 QDateTime now = QDateTime::currentDateTime();
2550 int daysTo = dateTime.date().daysTo(now.date());
2551 int secsTo = now.secsTo(dateTime);
2556 KLocale::DateTimeFormatOptions options)
2564 int daysTo = dateTime.
date().daysTo(now.
date());
2565 int secsTo = now.
secsTo(dateTime);
2573 tz =
i18n(dateTime.
toString(QString::fromLatin1(
"%z")).toUtf8());
2583 return i18nc(
"concatenation of date/time and time zone",
"%1 %2", dt, tz);
2597 for (
int id = localDoc.count() - 1;
id >= 0; --id) {
2600 langs.replaceInStrings(QLatin1String(
"en_US"), QLatin1String(
"en"));
2601 langs.append(QLatin1String(
"en"));
2602 Q_FOREACH(
const QString &lang, langs)
2603 search.append(QString::fromLatin1(
"%1%2/%3").arg(localDoc[
id]).arg(lang).arg(fname));
2607 Q_FOREACH(
const QString &file, search) {
2608 kDebug(173) <<
"Looking for help in: " << file;
2610 QFileInfo info(file);
2611 if (info.exists() && info.isFile() && info.isReadable())
2625 m_codecForEncoding = 0;
2631 if (!codeset.isEmpty()) {
2632 QTextCodec* codec = QTextCodec::codecForName(codeset);
2637 setEncoding(QTextCodec::codecForLocale()->mibEnum());
2640 if (!m_codecForEncoding) {
2641 kWarning() <<
"Cannot resolve system encoding, defaulting to ISO 8859-1.";
2642 const int mibDefault = 4;
2646 Q_ASSERT(m_codecForEncoding);
2658 codeset = nl_langinfo(CODESET);
2660 if ((codeset ==
"ANSI_X3.4-1968") || (codeset ==
"US-ASCII")) {
2662 codeset =
"ISO-8859-1";
2672 m_utf8FileEncoding = !qgetenv(
"KDE_UTF8_FILENAMES").isEmpty();
2673 if (m_utf8FileEncoding) {
2677 const QByteArray ctype = setlocale(LC_CTYPE, 0);
2678 int indexOfDot = ctype.indexOf(
'.');
2679 if (indexOfDot != -1) {
2680 if (!qstrnicmp(ctype.data() + indexOfDot + 1,
"UTF-8", 5)) {
2683 m_utf8FileEncoding =
true;
2687 QByteArray lang = qgetenv(
"LC_ALL");
2688 if (lang.isEmpty() || lang ==
"C") {
2689 lang = qgetenv(
"LC_CTYPE");
2691 if (lang.isEmpty() || lang ==
"C") {
2692 lang = qgetenv(
"LANG");
2694 indexOfDot = lang.indexOf(
'.');
2695 if (indexOfDot != -1) {
2696 if (!qstrnicmp(lang.data() + indexOfDot + 1,
"UTF-8", 5)) {
2699 m_utf8FileEncoding =
true;
2709 return (ucs4 & 0xfffe) == 0xfffe || (ucs4 - 0xfdd0U) < 16;
2714 if (fileName.isNull())
return QByteArray();
2715 int len = fileName.length();
2716 const QChar *uc = fileName.constData();
2718 uchar replacement =
'?';
2720 int surrogate_high = -1;
2724 uchar* cursor = (uchar*)rstr.data();
2725 const QChar *ch = uc;
2728 const QChar *end = ch + len;
2730 uint u = ch->unicode();
2731 if (surrogate_high >= 0) {
2732 if (ch->isLowSurrogate()) {
2733 u = QChar::surrogateToUcs4(surrogate_high, u);
2734 surrogate_high = -1;
2737 *cursor = replacement;
2740 surrogate_high = -1;
2743 }
else if (ch->isLowSurrogate()) {
2745 *cursor = replacement;
2749 }
else if (ch->isHighSurrogate()) {
2755 if (u >= 0x10FE00 && u <= 0x10FE7F) {
2756 *cursor++ = (uchar)(u - 0x10FE00 + 128) ;
2758 else if (u < 0x80) {
2759 *cursor++ = (uchar)u;
2762 *cursor++ = 0xc0 | ((uchar) (u >> 6));
2766 *cursor++ = replacement;
2773 *cursor++ = 0xf0 | ((uchar) (u >> 18));
2774 *cursor++ = 0x80 | (((uchar) (u >> 12)) & 0x3f);
2776 *cursor++ = 0xe0 | (((uchar) (u >> 12)) & 0x3f);
2778 *cursor++ = 0x80 | (((uchar) (u >> 6)) & 0x3f);
2780 *cursor++ = 0x80 | ((uchar) (u&0x3f));
2785 rstr.resize(cursor - (
const uchar*)rstr.constData());
2791 const char *chars = localFileName;
2792 int len = qstrlen(chars);
2797 QString result(2 * (len + 1), Qt::Uninitialized);
2798 ushort *qch = (ushort *)result.unicode();
2801 for (
int i = 0; i < len; ++i) {
2804 if ((ch&0xc0) == 0x80) {
2805 uc = (uc << 6) | (ch & 0x3f);
2811 Q_ASSERT((qch - (ushort*)result.unicode()) + 2 < result.length());
2812 *qch++ = QChar::highSurrogate(uc);
2813 *qch++ = QChar::lowSurrogate(uc);
2814 }
else if ((uc < min_uc) || (uc >= 0xd800 && uc <= 0xdfff) || nonCharacter || uc >= 0x110000) {
2826 *qch++ = ushort(ch);
2827 }
else if ((ch & 0xe0) == 0xc0) {
2831 }
else if ((ch & 0xf0) == 0xe0) {
2835 }
else if ((ch&0xf8) == 0xf0) {
2848 result.truncate(qch - (ushort *)result.unicode());
2853 qch = (ushort *)result.unicode();
2854 for (
int i = 0; i < len; ++i) {
2857 *qch++ = ushort(ch);
2859 uint uc = ch - 128 + 0x10FE00;
2860 *qch++ = QChar::highSurrogate(uc);
2861 *qch++ = QChar::lowSurrogate(uc);
2864 result.truncate(qch - (ushort *)result.unicode());
2870 m_dateFormat = format.trimmed();
2875 m_dateFormatShort = format.trimmed();
2880 m_dateMonthNamePossessive = possessive;
2885 m_timeFormat = format.trimmed();
2890 if (day >= 1 && day <=
calendar()->daysInWeek(QDate())) {
2891 m_weekStartDay = day;
2897 if (day >= 1 && day <=
calendar()->daysInWeek(QDate())) {
2898 m_workingWeekStartDay = day;
2904 if (day >= 1 && day <=
calendar()->daysInWeek(QDate())) {
2905 m_workingWeekEndDay = day;
2911 if (day >= 0 && day <=
calendar()->daysInWeek(QDate())) {
2912 m_weekDayOfPray = day;
2918 return m_dateFormat;
2923 return m_dateFormatShort;
2928 return m_timeFormat;
2933 m_decimalPlaces = digits;
2938 m_decimalSymbol = symbol.trimmed();
2944 m_thousandsSeparator = separator;
2949 m_numericDigitGrouping = groupList;
2954 m_positiveSign = sign.trimmed();
2959 m_negativeSign = sign.trimmed();
2964 m_positiveMonetarySignPosition = signpos;
2969 m_negativeMonetarySignPosition = signpos;
2974 m_positivePrefixCurrencySymbol =
prefix;
2979 m_negativePrefixCurrencySymbol =
prefix;
2984 m_monetaryDecimalPlaces = digits;
2990 m_monetaryThousandsSeparator = separator;
2995 m_monetaryDigitGrouping = groupList;
3000 m_monetaryDecimalSymbol = symbol.trimmed();
3005 m_currencySymbol = symbol.trimmed();
3021 return m_measureSystem;
3026 m_measureSystem = value;
3031 static const QString en_US = QString::fromLatin1(
"en_US");
3037 return QString::fromLatin1(
"C");
3042 return QString::fromLatin1(
"USD");
3047 return m_useTranscript;
3062 if (m_utf8FileEncoding) {
3070 return m_codecForEncoding;
3075 QTextCodec * codec = QTextCodec::codecForMib(mibEnum);
3077 m_codecForEncoding = codec;
3095 foreach (
const QString &path, paths) {
3096 QString part = path.left(path.length() - 14);
3097 languages.append(part.mid(part.lastIndexOf(QLatin1Char(
'/')) + 1));
3117 for (QStringList::ConstIterator it = paths.begin(); it != paths.end(); ++it) {
3118 QString code = (*it).mid((*it).length() - 16, 2);
3119 if (code != QLatin1String(
"/C")) {
3120 countries.append(code);
3129 QString entryFile =
KStandardDirs::locate(
"locale", QString::fromLatin1(
"l10n/") + country.toLower() + QLatin1String(
"/entry.desktop"));
3130 if (!entryFile.isEmpty()) {
3140 if (calendarType == QLatin1String(
"coptic")) {
3142 }
else if (calendarType == QLatin1String(
"ethiopian")) {
3144 }
else if (calendarType == QLatin1String(
"gregorian")) {
3146 }
else if (calendarType == QLatin1String(
"gregorian-proleptic")) {
3148 }
else if (calendarType == QLatin1String(
"hebrew")) {
3150 }
else if (calendarType == QLatin1String(
"hijri")) {
3152 }
else if (calendarType == QLatin1String(
"indian-national")) {
3154 }
else if (calendarType == QLatin1String(
"jalali")) {
3156 }
else if (calendarType == QLatin1String(
"japanese")) {
3158 }
else if (calendarType == QLatin1String(
"julian")) {
3160 }
else if (calendarType == QLatin1String(
"minguo")) {
3162 }
else if (calendarType == QLatin1String(
"thai")) {
3171 switch (calendarSystem) {
3173 return QLatin1String(
"gregorian");
3175 return QLatin1String(
"coptic");
3177 return QLatin1String(
"ethiopian");
3179 return QLatin1String(
"gregorian-proleptic");
3181 return QLatin1String(
"hebrew");
3183 return QLatin1String(
"hijri");
3185 return QLatin1String(
"indian-national");
3187 return QLatin1String(
"jalali");
3189 return QLatin1String(
"japanese");
3191 return QLatin1String(
"julian");
3193 return QLatin1String(
"minguo");
3195 return QLatin1String(
"thai");
3197 return QLatin1String(
"gregorian");
3220 return m_calendarSystem;
3239 return m_weekNumberSystem;
3245 locale->d->m_catalogNames = m_catalogNames;
3257 QFileInfo fileInfo(filePath);
3258 QString locDirPath = fileInfo.path() + QLatin1String(
"/l10n");
3259 QFileInfo locDirInfo(locDirPath);
3260 if (!locDirInfo.isDir()) {
3266 QString fileName = fileInfo.fileName();
3272 QString locFilePath = locDirPath + QLatin1Char(
'/') + lang + QLatin1Char(
'/') + fileName;
3273 QFileInfo locFileInfo(locFilePath);
3274 if (locFileInfo.isFile() && locFileInfo.isReadable()) {
3304 return m_monetaryDigitSet;
3314 return m_dateTimeDigitSet;
3321 return s_kLocaleMutex();