27 #include "config-localization.h"
31 #ifdef HAVE_SYS_TIME_H
41 #include <QtCore/QTextCodec>
42 #include <QtCore/QFile>
43 #include <QtGui/QPrinter>
44 #include <QtCore/QFileInfo>
45 #include <QtCore/QRegExp>
46 #include <QtCore/QLocale>
47 #include <QtCore/QHash>
48 #include <QtCore/QMutexLocker>
49 #include <QtCore/QStringList>
66 class KLocaleStaticData
78 KLocaleStaticData::KLocaleStaticData()
102 return debug << cn.name << cn.loadCount;
114 m_codecForEncoding(0)
132 return m_config.
data();
144 m_config = rhs.m_config;
147 m_country = rhs.m_country;
148 m_countryDivisionCode = rhs.m_countryDivisionCode;
151 m_language = rhs.m_language;
153 m_languageList = rhs.m_languageList;
154 m_languageSensitiveDigits = rhs.m_languageSensitiveDigits;
155 m_nounDeclension = rhs.m_nounDeclension;
158 m_catalogName = rhs.m_catalogName;
159 m_catalogNames = rhs.m_catalogNames;
160 m_catalogs = rhs.m_catalogs;
161 m_numberOfSysCatalogs = rhs.m_numberOfSysCatalogs;
162 m_useTranscript = rhs.m_useTranscript;
165 m_calendarSystem = rhs.m_calendarSystem;
167 m_weekStartDay = rhs.m_weekStartDay;
168 m_workingWeekStartDay = rhs.m_workingWeekStartDay;
169 m_workingWeekEndDay = rhs.m_workingWeekEndDay;
170 m_weekDayOfPray = rhs.m_weekDayOfPray;
173 m_dateFormat = rhs.m_dateFormat;
174 m_dateFormatShort = rhs.m_dateFormatShort;
175 m_timeFormat = rhs.m_timeFormat;
176 m_dateTimeDigitSet = rhs.m_dateTimeDigitSet;
177 m_dateMonthNamePossessive = rhs.m_dateMonthNamePossessive;
178 m_dayPeriods = rhs.m_dayPeriods;
179 m_weekNumberSystem = rhs.m_weekNumberSystem;
182 m_decimalPlaces = rhs.m_decimalPlaces;
183 m_decimalSymbol = rhs.m_decimalSymbol;
184 m_thousandsSeparator = rhs.m_thousandsSeparator;
185 m_numericDigitGrouping = rhs.m_numericDigitGrouping;
186 m_positiveSign = rhs.m_positiveSign;
187 m_negativeSign = rhs.m_negativeSign;
188 m_digitSet = rhs.m_digitSet;
191 m_currencyCode = rhs.m_currencyCode;
193 m_currencyCodeList = rhs.m_currencyCodeList;
196 m_currencySymbol = rhs.m_currencySymbol;
197 m_monetaryDecimalSymbol = rhs.m_monetaryDecimalSymbol;
198 m_monetaryThousandsSeparator = rhs.m_monetaryThousandsSeparator;
199 m_monetaryDigitGrouping = rhs.m_monetaryDigitGrouping;
200 m_monetaryDecimalPlaces = rhs.m_monetaryDecimalPlaces;
201 m_positiveMonetarySignPosition = rhs.m_positiveMonetarySignPosition;
202 m_negativeMonetarySignPosition = rhs.m_negativeMonetarySignPosition;
203 m_positivePrefixCurrencySymbol = rhs.m_positivePrefixCurrencySymbol;
204 m_negativePrefixCurrencySymbol = rhs.m_negativePrefixCurrencySymbol;
205 m_monetaryDigitSet = rhs.m_monetaryDigitSet;
208 m_binaryUnitDialect = rhs.m_binaryUnitDialect;
209 m_byteSizeFmt = rhs.m_byteSizeFmt;
210 m_pageSize = rhs.m_pageSize;
211 m_measureSystem = rhs.m_measureSystem;
214 m_encoding = rhs.m_encoding;
215 m_codecForEncoding = rhs.m_codecForEncoding;
216 m_utf8FileEncoding = rhs.m_utf8FileEncoding;
231 m_catalogName = catalogName;
235 m_config = persistantConfig;
239 bool useEnvironmentVariables;
247 cg = m_config->
group(QLatin1String(
"Locale"));
248 useEnvironmentVariables =
false;
249 }
else if (tempConfig == 0 || tempConfig ==
KGlobal::config().data()) {
251 useEnvironmentVariables =
true;
253 cg = tempConfig->
group(QLatin1String(
"Locale"));
254 useEnvironmentVariables =
false;
297 KLocaleStaticData *s = staticData;
300 if (!s->maincatalog.isEmpty()) {
303 m_catalogName = s->maincatalog;
306 if (m_catalogName.isEmpty()) {
307 kDebug(173) <<
"KLocale instance created called without valid "
308 <<
"catalog! Give an argument or call setMainCatalog "
309 <<
"before init" << endl;
315 const int numberOfCatalogs = m_catalogNames.size();
316 m_catalogNames.append(
KCatalogName(QString::fromLatin1(
"libphonon")));
317 m_catalogNames.append(
KCatalogName(QString::fromLatin1(
"kio4")));
318 m_catalogNames.append(
KCatalogName(QString::fromLatin1(
"kdelibs4")));
319 m_catalogNames.append(
KCatalogName(QString::fromLatin1(
"kdeqt")));
320 m_catalogNames.append(
KCatalogName(QString::fromLatin1(
"solid_qt")));
321 m_catalogNames.append(
KCatalogName(QString::fromLatin1(
"kdecalendarsystems")));
322 m_numberOfSysCatalogs = m_catalogNames.size() - numberOfCatalogs;
330 QByteArray var(qgetenv(variable));
331 if (!var.isEmpty()) {
332 QString value = QFile::decodeName(var);
333 if (isLanguageList) {
334 list += value.split(QLatin1Char(
':'));
337 QString lang, ctry, modf, cset;
340 if (!ctry.isEmpty() && !modf.isEmpty()) {
341 list += lang + QLatin1Char(
'_') + ctry + QLatin1Char(
'@') + modf;
346 if (!modf.isEmpty()) {
347 list += lang + QLatin1Char(
'@') + modf;
349 if (!ctry.isEmpty()) {
350 list += lang + QLatin1Char(
'_') + ctry;
367 if ( putativeCountry.isEmpty() || !validCountries.contains( putativeCountry, Qt::CaseInsensitive ) ) {
370 putativeCountry = configCountry;
372 if ( putativeCountry.isEmpty() || !validCountries.contains( putativeCountry, Qt::CaseInsensitive ) ) {
377 if ( putativeCountry.isEmpty() || !validCountries.contains( putativeCountry, Qt::CaseInsensitive ) ) {
388 m_country = putativeCountry.toLower();
397 splitLocale( QLocale::system().name(), s1, systemCountry, s2, s3 );
398 return systemCountry.toLower();
402 bool useEnvironmentVariables)
414 if (!m_language.isEmpty()) {
421 if (useEnvironmentVariables) {
426 if (!configLanguages.isEmpty()) {
427 list += configLanguages.split(QLatin1Char(
':'));
430 if (useEnvironmentVariables) {
462 if (cg.
hasKey(
"FracDigits")) {
464 if (!fracDigits.isEmpty()) {
466 cg.
writeEntry(
"MonetaryDecimalPlaces", fracDigits);
473 #define readConfigEntry(key, default, save) \
474 save = entry.readEntry(key, default); \
475 save = cg.readEntry(key, save);
477 #define readConfigNumEntry(key, default, save, type) \
478 save = (type)entry.readEntry(key, int(default)); \
479 save = (type)cg.readEntry(key, int(save));
489 m_thousandsSeparator.remove(QString::fromLatin1(
"$0"));
492 m_numericDigitGrouping = digitGroupFormatToList(digitGroupFormat);
499 readConfigEntry(
"LanguageSensitiveDigits",
true, m_languageSensitiveDigits);
510 readConfigEntry(
"MonetaryDecimalSymbol",
".", m_monetaryDecimalSymbol);
511 readConfigEntry(
"MonetaryThousandsSeparator",
",", m_monetaryThousandsSeparator);
512 m_monetaryThousandsSeparator.remove(QString::fromLatin1(
"$0"));
513 readConfigEntry(
"MonetaryDigitGroupFormat",
"3", digitGroupFormat);
514 m_monetaryDigitGrouping = digitGroupFormatToList(digitGroupFormat);
516 readConfigEntry(
"PositivePrefixCurrencySymbol",
true, m_positivePrefixCurrencySymbol);
517 readConfigEntry(
"NegativePrefixCurrencySymbol",
true, m_negativePrefixCurrencySymbol);
529 readConfigEntry(
"TimeFormat",
"%H:%M:%S", m_timeFormat);
530 readConfigEntry(
"DateFormat",
"%A %d %B %Y", m_dateFormat);
531 readConfigEntry(
"DateFormatShort",
"%Y-%m-%d", m_dateFormatShort);
542 #ifndef QT_NO_PRINTER
547 readConfigEntry(
"CalendarSystem",
"gregorian", calendarType);
550 readConfigEntry(
"Transcript",
true, m_useTranscript);
556 #define read3ConfigBoolEntry(key, default, save) \
557 save = entry.readEntry(key, default); \
558 save = lang.readEntry(key, save); \
559 save = cg.readEntry(key, save);
576 m_dayPeriods.clear();
577 QString periodKey = QString::fromLatin1(
"DayPeriod1");
579 while (cg.
hasKey(periodKey)) {
581 if (period.count() == 8) {
582 m_dayPeriods.append(
KDayPeriod(period[0], period[1], period[2], period[3],
583 QTime::fromString(period[4], QString::fromLatin1(
"HH:mm:ss.zzz")),
584 QTime::fromString(period[5], QString::fromLatin1(
"HH:mm:ss.zzz")),
585 period[6].toInt(), period[7].toInt()));
588 periodKey = QString::fromLatin1(
"DayPeriod%1").arg(i);
600 if (putativeCountry.isEmpty()) {
603 if (putativeCountry.isEmpty() || !validCountries.contains(putativeCountry, Qt::CaseInsensitive)) {
607 }
else if (!validCountries.contains(putativeCountry, Qt::CaseInsensitive)) {
615 m_country = putativeCountry.toLower();
637 m_languageList.removeAll(language);
638 m_languageList.prepend(language);
676 list.append(language);
687 m_language = list.first();
689 m_languageList = list;
712 if (!newCurrencyCode.isEmpty() && newCurrencyCode != m_currency->
isoCurrencyCode() &&
714 m_currencyCode = newCurrencyCode;
721 if (lang.isEmpty()) {
730 if (m_catalogName.isEmpty()) {
731 kDebug() <<
"no appName!";
753 int f = locale.indexOf(QLatin1Char(
':'));
758 f = locale.indexOf(QLatin1Char(
'.'));
760 charset = locale.mid(f + 1);
764 f = locale.indexOf(QLatin1Char(
'@'));
766 modifier = locale.mid(f + 1);
770 f = locale.indexOf(QLatin1Char(
'_'));
772 country = locale.mid(f + 1);
791 if (m_countryDivisionCode.isEmpty()) {
794 return m_countryDivisionCode;
808 return m_currencyCode;
814 int pos = m_catalogNames.indexOf(
KCatalogName(catalog));
816 ++m_catalogNames[pos].loadCount;
822 m_catalogNames.insert(m_catalogNames.size() - m_numberOfSysCatalogs,
KCatalogName(catalog));
839 foreach(
const QString &lang, m_languageList) {
856 m_catalogs = newCatalogs;
863 int pos = m_catalogNames.indexOf(
KCatalogName(catalog));
867 if (--m_catalogNames[pos].loadCount > 0) {
870 m_catalogNames.removeAt(pos);
880 int pos = m_catalogNames.indexOf(
KCatalogName(catalog));
884 m_catalogNames.move(pos, 0);
892 if (!msgid || !msgid[0]) {
893 kDebug(173) <<
"KLocale: trying to look up \"\" in catalog. "
894 <<
"Fix the program" << endl;
896 translation->clear();
899 if (msgctxt && !msgctxt[0]) {
900 kDebug(173) <<
"KLocale: trying to use \"\" as context to message. "
901 <<
"Fix the program" << endl;
903 if (msgid_plural && !msgid_plural[0]) {
904 kDebug(173) <<
"KLocale: trying to use \"\" as plural message. "
905 <<
"Fix the program" << endl;
911 if (msgid_plural == NULL) {
912 fallback = QString::fromUtf8(msgid);
915 fallback = QString::fromUtf8(msgid);
917 fallback = QString::fromUtf8(msgid_plural);
924 *translation = fallback;
934 if (catname != NULL) {
935 catNameDecoded = QString::fromUtf8(catname);
946 if (catNameDecoded.isEmpty() || catNameDecoded == (*it).name()) {
948 if (msgctxt != NULL && msgid_plural != NULL) {
949 text = (*it).translateStrict(msgctxt, msgid, msgid_plural, n);
950 }
else if (msgid_plural != NULL) {
951 text = (*it).translateStrict(msgid, msgid_plural, n);
952 }
else if (msgctxt != NULL) {
953 text = (*it).translateStrict(msgctxt, msgid);
955 text = (*it).translateStrict(msgid);
958 if (!text.isEmpty()) {
961 *language = (*it).language();
996 if (!sourceText || !sourceText[0]) {
997 kDebug(173) <<
"KLocale: trying to look up \"\" in catalog. "
998 <<
"Fix the program" << endl;
1012 if (comment && comment[0]) {
1017 if (context && context[0]) {
1058 return QString::fromUtf8(
"٠١٢٣٤٥٦٧٨٩");
1060 return QString::fromUtf8(
"০১২৩৪৫৬৭৮৯");
1062 return QString::fromUtf8(
"०१२३४५६७८९");
1064 return QString::fromUtf8(
"۰۱۲۳۴۵۶۷۸۹");
1066 return QString::fromUtf8(
"૦૧૨૩૪૫૬૭૮૯");
1068 return QString::fromUtf8(
"੦੧੨੩੪੫੬੭੮੯");
1070 return QString::fromUtf8(
"೦೧೨೩೪೫೬೭೮೯");
1072 return QString::fromUtf8(
"០១២៣៤៥៦៧៨៩");
1074 return QString::fromUtf8(
"൦൧൨൩൪൫൬൭൮൯");
1076 return QString::fromUtf8(
"୦୧୨୩୪୫୬୭୮୯");
1078 return QString::fromUtf8(
"௦௧௨௩௪௫௬௭௮");
1080 return QString::fromUtf8(
"౦౧౨౩౪౫౬౭౯");
1082 return QString::fromUtf8(
"๐๑๒๓๔๕๖๗๘๙");
1084 return QString::fromUtf8(
"0123456789");
1093 name =
i18nc(
"digit set",
"Arabic-Indic");
1096 name =
i18nc(
"digit set",
"Bengali");
1099 name =
i18nc(
"digit set",
"Devanagari");
1102 name =
i18nc(
"digit set",
"Eastern Arabic-Indic");
1105 name =
i18nc(
"digit set",
"Gujarati");
1108 name =
i18nc(
"digit set",
"Gurmukhi");
1111 name =
i18nc(
"digit set",
"Kannada");
1114 name =
i18nc(
"digit set",
"Khmer");
1117 name =
i18nc(
"digit set",
"Malayalam");
1120 name =
i18nc(
"digit set",
"Oriya");
1123 name =
i18nc(
"digit set",
"Tamil");
1126 name =
i18nc(
"digit set",
"Telugu");
1129 name =
i18nc(
"digit set",
"Thai");
1132 name =
i18nc(
"digit set",
"Arabic");
1136 QString nameWithDigits =
i18nc(
"name of digit set with digit string, "
1137 "e.g. 'Arabic (0123456789)'",
"%1 (%2)", name, digits);
1138 return nameWithDigits;
1146 if (!ignoreContext) {
1150 KLocaleStaticData *s = staticData;
1151 if (m_languageSensitiveDigits && !s->languagesUsingDigitSet[digitSet].contains(m_language)) {
1158 foreach(
const QChar &c, str) {
1160 nstr += digitDraw[c.digitValue()];
1171 foreach(
const QChar &c, str) {
1173 nstr += QChar(
'0' + c.digitValue());
1183 return m_nounDeclension;
1188 return m_dateMonthNamePossessive;
1193 return m_weekStartDay;
1198 return m_workingWeekStartDay;
1203 return m_workingWeekEndDay;
1208 return m_weekDayOfPray;
1213 return m_decimalPlaces;
1218 return m_decimalSymbol;
1223 return m_thousandsSeparator;
1228 return m_numericDigitGrouping;
1233 return m_currencySymbol;
1238 return m_monetaryDecimalSymbol;
1243 return m_monetaryThousandsSeparator;
1248 return m_monetaryDigitGrouping;
1253 return m_positiveSign;
1258 return m_negativeSign;
1270 return m_monetaryDecimalPlaces;
1275 return m_positivePrefixCurrencySymbol;
1280 return m_negativePrefixCurrencySymbol;
1285 return m_positiveMonetarySignPosition;
1290 return m_negativeMonetarySignPosition;
1295 for (
int l = 0; l < s.length(); l++) {
1296 buffer[index++] = s.at(l);
1300 static inline void put_it_in(QChar *buffer,
int &index,
int number)
1302 buffer[index++] = number / 10 +
'0';
1303 buffer[index++] = number % 10 +
'0';
1307 QList<int> KLocalePrivate::digitGroupFormatToList(
const QString &digitGroupFormat)
const
1310 QStringList stringList = digitGroupFormat.split(QLatin1Char(
';'));
1311 foreach(
const QString &size, stringList) {
1312 groupList.append(size.toInt());
1320 if (groupList.isEmpty() || groupSeparator.isEmpty()) {
1325 int groupCount = groupList.count();
1327 int groupSize = groupList.at(groupAt);
1328 int pos = num.indexOf(decimalSeperator);
1332 pos = pos - groupSize;
1334 while (pos > 0 && groupSize > 0) {
1335 num.insert(pos, groupSeparator);
1336 if (groupAt + 1 < groupCount) {
1338 groupSize = groupList.at(groupAt);
1340 pos = pos - groupSize;
1352 if (!groupSeparator.isEmpty()) {
1353 if (!groupList.isEmpty()) {
1354 int separatorSize = groupSeparator.length();
1355 int groupCount = groupList.count();
1357 int groupSize = groupList.at(groupAt);
1358 int pos = number.indexOf(decimalSeparator);
1360 pos = number.length();
1362 pos = pos - groupSize - separatorSize;
1364 while (pos > 0 && valid && groupSize > 0) {
1365 if (num.mid(pos, separatorSize) == groupSeparator) {
1366 num.remove(pos, separatorSize);
1367 if (groupAt + 1 < groupCount) {
1369 groupSize = groupList.at(groupAt);
1371 pos = pos - groupSize - separatorSize;
1378 if (num.contains(groupSeparator)) {
1380 num = num.remove(groupSeparator);
1394 QString currencyString = symbol;
1395 if (symbol.isNull()) {
1398 if (precision < 0) {
1404 QString res = QString::number(neg ? -num : num,
'f', precision);
1422 res.prepend(QLatin1Char(
'('));
1423 res.append(QLatin1Char(
')'));
1432 currencyString.prepend(sign);
1435 currencyString.append(sign);
1441 res.prepend(QLatin1Char(
' '));
1442 res.prepend(currencyString);
1444 res.append(QLatin1Char(
' '));
1445 res.append(currencyString);
1457 if (precision < 0) {
1461 return formatNumber(QString::number(num,
'f', precision),
false, 0);
1472 for (
int i = position; i >= 0; i--) {
1473 char last_char = str[i].toLatin1();
1474 switch (last_char) {
1504 if (i == 0) str.prepend(QLatin1Char(
'1'));
1516 int decimalSymbolPos = str.indexOf(QLatin1Char(
'.'));
1518 if (decimalSymbolPos == -1) {
1519 if (precision == 0)
return;
1520 else if (precision > 0) {
1521 str.append(QLatin1Char(
'.'));
1522 decimalSymbolPos = str.length() - 1;
1526 str.reserve(str.length() + precision);
1527 for (
int i = 0; i < precision; ++i)
1528 str.append(QLatin1Char(
'0'));
1531 char last_char = str[decimalSymbolPos + precision + 1].toLatin1();
1532 switch (last_char) {
1551 decimalSymbolPos = str.indexOf(QLatin1Char(
'.'));
1552 str.truncate(decimalSymbolPos + precision + 1);
1555 if (precision == 0) {
1556 str = str.left(decimalSymbolPos);
1566 if (precision < 0) {
1571 const bool neg = (tmpString[0] == QLatin1Char(
'-'));
1572 if (neg || tmpString[0] == QLatin1Char(
'+')) {
1573 tmpString.remove(0, 1);
1579 const int expPos = tmpString.indexOf(QLatin1Char(
'e'));
1580 QString mantString = tmpString.left(expPos);
1583 expString = tmpString.mid(expPos);
1584 if (expString.length() == 1) {
1591 if (mantString.isEmpty() || !mantString[0].isDigit()) {
1592 mantString = QLatin1Char(
'0');
1596 _round(mantString, precision);
1614 return mantString + expString;
1625 #define CACHE_BYTE_FMT(ctxt_text) \
1626 translateRawFrom(0, ctxt_text, 0, 0, 0, &s); \
1627 binaryUnits.append(s);
1704 dialect = m_binaryUnitDialect;
1713 if (dialect == m_binaryUnitDialect) {
1715 if (m_byteSizeFmt.size() == 0) {
1722 dialectUnits = m_byteSizeFmt;
1728 double multiplier = 1024.0;
1731 multiplier = 1000.0;
1743 unit =
static_cast<int>(specificUnit);
1745 size /= pow(multiplier, unit);
1754 return dialectUnits[unit].arg(
formatNumber(size, precision));
1764 return m_binaryUnitDialect;
1771 m_binaryUnitDialect = newDialect;
1772 m_byteSizeFmt.clear();
1778 if (mSec >= 24*3600000) {
1779 return i18nc(
"@item:intext %1 is a real number, e.g. 1.23 days",
"%1 days",
1781 }
else if (mSec >= 3600000) {
1782 return i18nc(
"@item:intext %1 is a real number, e.g. 1.23 hours",
"%1 hours",
1784 }
else if (mSec >= 60000) {
1785 return i18nc(
"@item:intext %1 is a real number, e.g. 1.23 minutes",
"%1 minutes",
1787 }
else if (mSec >= 1000) {
1788 return i18nc(
"@item:intext %1 is a real number, e.g. 1.23 seconds",
"%1 seconds",
1791 return i18ncp(
"@item:intext",
"%1 millisecond",
"%1 milliseconds", mSec);
1796 switch (durationType) {
1798 return i18ncp(
"@item:intext",
"1 day",
"%1 days", n);
1800 return i18ncp(
"@item:intext",
"1 hour",
"%1 hours", n);
1802 return i18ncp(
"@item:intext",
"1 minute",
"%1 minutes", n);
1804 return i18ncp(
"@item:intext",
"1 second",
"%1 seconds", n);
1811 unsigned long ms = mSec;
1812 int days = ms / (24 * 3600000);
1813 ms = ms % (24 * 3600000);
1814 int hours = ms / 3600000;
1816 int minutes = ms / 60000;
1818 int seconds = qRound(ms / 1000.0);
1822 if (seconds == 60) {
1826 if (days && hours) {
1827 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",
1832 }
else if (hours && minutes) {
1833 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",
1839 }
else if (minutes && seconds) {
1840 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",
1844 }
else if (minutes) {
1858 KLocaleStaticData *s = staticData;
1859 s->maincatalog = QString::fromUtf8(catalog);
1872 str = str.trimmed();
1876 str = str.trimmed();
1877 }
else if (
negativeSign().isEmpty() && str[0].isDigit()) {
1887 EPos = str.indexOf(QLatin1Char(
'E'), 0, Qt::CaseInsensitive);
1890 exponentialPart = str.mid(EPos);
1891 str = str.left(EPos);
1892 str = str.trimmed();
1896 bool groupOk =
true;
1915 major = str.left(pos);
1920 bool digitTest =
true;
1921 foreach (
const QChar &ch, major) {
1922 if (!ch.isDigit()) {
1927 foreach (
const QChar &ch, minor) {
1928 if (!ch.isDigit()) {
1942 tot = QLatin1Char(
'-');
1944 tot += major + QLatin1Char(
'.') + minor + exponentialPart;
1946 return tot.toDouble(ok);
1953 bool currencyFound =
false;
1957 int pos = str.indexOf(symbol);
1958 if (pos == 0 || pos == (
int) str.length() - symbol.length()) {
1959 str.remove(pos, symbol.length());
1960 str = str.trimmed();
1961 currencyFound =
true;
1963 if (str.isEmpty()) {
1971 if (str[0] == QLatin1Char(
'(') && str[str.length()-1] == QLatin1Char(
')')) {
1975 str.remove(str.length() - 1, 1);
1977 str = str.trimmed();
1983 if (!negSign.isEmpty() && (str.left(negLen) == negSign || str.right(negSign.length()) == negSign)) {
1990 if (!posSign.isEmpty() && (str.left(posLen) == posSign || str.right(posSign.length()) == posSign)) {
1993 }
else if (negSign.isEmpty() && str[0].isDigit() && str[str.length() - 1].isDigit()){
1997 if (!sign.isEmpty()) {
1998 if (str.left(len) == sign) {
2001 str.remove(str.length() - len, len);
2003 str = str.trimmed();
2009 if (!currencyFound) {
2010 pos = str.indexOf(symbol);
2011 if (pos == 0 || pos == (
int) str.length() - symbol.length()) {
2012 str.remove(pos, symbol.length());
2013 str = str.trimmed();
2018 bool groupOk =
true;
2038 major = str.left(pos);
2043 bool digitTest =
true;
2044 foreach (
const QChar &ch, major) {
2045 if (!ch.isDigit()) {
2050 foreach (
const QChar &ch, minor) {
2051 if (!ch.isDigit()) {
2065 tot = QLatin1Char(
'-');
2067 tot += major + QLatin1Char(
'.') + minor;
2069 return tot.toDouble(ok);
2080 if (!str.at(pos).isDigit()) {
2084 for (; str.length() > pos && str.at(pos).isDigit(); ++pos) {
2086 result += str.at(pos).digitValue();
2110 if (time.isValid()) {
2127 int remPos = inout.indexOf(strip2char);
2131 int endPos = remPos + 2;
2132 int curPos = remPos - 1;
2133 while (curPos >= 0 && inout.at(curPos).isSpace()) {
2138 if (curPos >= 0 && inout.at(curPos).isPunct() && inout.at(curPos) != QLatin1Char(
'%')) {
2141 while (curPos >= 0 && inout.at(curPos).isSpace()) {
2145 remPos = qMax(curPos + 1, 0);
2146 inout.remove(remPos, endPos - remPos);
2154 int remPos = inout.indexOf(strip2char);
2158 int curPos = remPos + 2;
2159 while (curPos < inout.size() &&
2160 (inout.at(curPos).isSpace() ||
2161 (inout.at(curPos).isPunct() && inout.at(curPos) != QLatin1Char(
'%')))) {
2164 inout.remove(remPos, curPos - remPos);
2174 int length = inout.size();
2175 int ppos = inout.indexOf(QLatin1String(
"%p"));
2178 }
else if (ppos == 0) {
2181 while (ppos < length && (inout.at(ppos).isSpace() || inout.at(ppos).isPunct()) &&
2182 inout.at(ppos) != QLatin1Char(
'%')) {
2185 inout = inout.mid(ppos);
2192 KLocale::TimeProcessingOptions processing)
const
2194 QString str(intstr.simplified().toLower());
2200 bool useDayPeriod =
false;
2231 while (!error && (format.length() > formatpos || str.length() > strpos)) {
2232 if (!(format.length() > formatpos && str.length() > strpos)) {
2237 QChar c = format.at(formatpos++);
2240 if (!str.at(strpos).isSpace()) {
2247 if (str.at(strpos).isSpace()) {
2254 if (c != QLatin1Char(
'%')) {
2255 if (c != str.at(strpos++)) {
2262 c = format.at(formatpos++);
2263 switch (c.unicode()) {
2271 int len = dayPeriodText.length();
2272 if (str.mid(strpos, len) == dayPeriodText.toLower()) {
2273 dayPeriod = testDayPeriod;
2276 useDayPeriod =
true;
2285 useDayPeriod =
false;
2291 useDayPeriod = !isDuration;
2296 minute =
readInt(str, strpos);
2301 minute = minute % 60;
2306 second =
readInt(str, strpos);
2317 returnTime = dayPeriod.
time(hour, minute, second);
2319 returnTime = QTime(hour, minute, second);
2323 *ok = returnTime.isValid();
2369 QChar *buffer =
new QChar[rst.length() * 3 / 2 + 32];
2372 bool escape =
false;
2375 for (
int format_index = 0; format_index < rst.length(); format_index++) {
2377 if (rst.at(format_index).unicode() ==
'%') {
2380 buffer[index++] = rst.at(format_index);
2383 switch (rst.at(format_index).unicode()) {
2385 buffer[index++] = QLatin1Char(
'%');
2399 put_it_in(buffer, index, QString::number(time.hour() * 60 + time.minute()));
2401 put_it_in(buffer, index, time.minute());
2405 put_it_in(buffer, index, time.second());
2410 if (!isDuration && rst.at(format_index).unicode() ==
'l') {
2413 number = time.hour();
2416 buffer[index++] = number / 10 +
'0';
2418 buffer[index++] = number % 10 +
'0';
2426 buffer[index++] = rst.at(format_index);
2435 return ret.trimmed();
2440 if ((
timeFormat().contains(QString::fromLatin1(
"%I")) > 0) ||
2441 (
timeFormat().contains(QString::fromLatin1(
"%l")) > 0)) {
2450 if (dayPeriods.count() > 0) {
2451 foreach (
const KDayPeriod &dayPeriod, dayPeriods) {
2466 if (m_dayPeriods.isEmpty()) {
2467 m_dayPeriods.append(
KDayPeriod(QString::fromLatin1(
"am"),
2468 i18nc(
"Before Noon KLocale::LongName",
"Ante Meridiem" ),
2469 i18nc(
"Before Noon KLocale::ShortName",
"AM" ),
2470 i18nc(
"Before Noon KLocale::NarrowName",
"A" ),
2471 QTime( 0, 0, 0 ), QTime( 11, 59, 59, 999 ), 0, 12 ));
2472 m_dayPeriods.append(
KDayPeriod(QString::fromLatin1(
"pm"),
2473 i18nc(
"After Noon KLocale::LongName",
"Post Meridiem" ),
2474 i18nc(
"After Noon KLocale::ShortName",
"PM" ),
2475 i18nc(
"After Noon KLocale::NarrowName",
"P" ),
2476 QTime( 12, 0, 0 ), QTime( 23, 59, 59, 999 ), 0, 12 ));
2478 return m_dayPeriods;
2483 if (time.isValid()) {
2485 if (dayPeriod.
isValid(time)) {
2495 return m_languageList;
2500 return m_currencyCodeList;
2504 bool includeSeconds,
int daysTo,
int secsTo)
2511 if ((daysTo == 0 && secsTo > 3600) || daysTo < 0 || daysTo > 6) {
2523 dateStr =
i18n(
"Today");
2526 dateStr =
i18n(
"Yesterday");
2532 dateStr = locale->
formatDate(dateTime.date(), format);
2536 if (includeSeconds) {
2542 return i18nc(
"concatenation of dates and time",
"%1 %2", dateStr,
2548 QDateTime now = QDateTime::currentDateTime();
2549 int daysTo = dateTime.date().daysTo(now.date());
2550 int secsTo = now.secsTo(dateTime);
2555 KLocale::DateTimeFormatOptions options)
2563 int daysTo = dateTime.
date().daysTo(now.
date());
2564 int secsTo = now.
secsTo(dateTime);
2572 tz =
i18n(dateTime.
toString(QString::fromLatin1(
"%z")).toUtf8());
2582 return i18nc(
"concatenation of date/time and time zone",
"%1 %2", dt, tz);
2596 for (
int id = localDoc.count() - 1;
id >= 0; --id) {
2599 langs.replaceInStrings(QLatin1String(
"en_US"), QLatin1String(
"en"));
2600 langs.append(QLatin1String(
"en"));
2601 Q_FOREACH(
const QString &lang, langs)
2602 search.append(QString::fromLatin1(
"%1%2/%3").arg(localDoc[
id]).arg(lang).arg(fname));
2606 Q_FOREACH(
const QString &file, search) {
2607 kDebug(173) <<
"Looking for help in: " << file;
2609 QFileInfo info(file);
2610 if (info.exists() && info.isFile() && info.isReadable())
2624 m_codecForEncoding = 0;
2630 if (!codeset.isEmpty()) {
2631 QTextCodec* codec = QTextCodec::codecForName(codeset);
2636 setEncoding(QTextCodec::codecForLocale()->mibEnum());
2639 if (!m_codecForEncoding) {
2640 kWarning() <<
"Cannot resolve system encoding, defaulting to ISO 8859-1.";
2641 const int mibDefault = 4;
2645 Q_ASSERT(m_codecForEncoding);
2657 codeset = nl_langinfo(CODESET);
2659 if ((codeset ==
"ANSI_X3.4-1968") || (codeset ==
"US-ASCII")) {
2661 codeset =
"ISO-8859-1";
2671 m_utf8FileEncoding = !qgetenv(
"KDE_UTF8_FILENAMES").isEmpty();
2672 if (m_utf8FileEncoding) {
2682 return fileName.toUtf8();
2687 return QString::fromUtf8(localFileName);
2692 m_dateFormat = format.trimmed();
2697 m_dateFormatShort = format.trimmed();
2702 m_dateMonthNamePossessive = possessive;
2707 m_timeFormat = format.trimmed();
2712 if (day >= 1 && day <=
calendar()->daysInWeek(QDate())) {
2713 m_weekStartDay = day;
2719 if (day >= 1 && day <=
calendar()->daysInWeek(QDate())) {
2720 m_workingWeekStartDay = day;
2726 if (day >= 1 && day <=
calendar()->daysInWeek(QDate())) {
2727 m_workingWeekEndDay = day;
2733 if (day >= 0 && day <=
calendar()->daysInWeek(QDate())) {
2734 m_weekDayOfPray = day;
2740 return m_dateFormat;
2745 return m_dateFormatShort;
2750 return m_timeFormat;
2755 m_decimalPlaces = digits;
2760 m_decimalSymbol = symbol.trimmed();
2766 m_thousandsSeparator = separator;
2771 m_numericDigitGrouping = groupList;
2776 m_positiveSign = sign.trimmed();
2781 m_negativeSign = sign.trimmed();
2786 m_positiveMonetarySignPosition = signpos;
2791 m_negativeMonetarySignPosition = signpos;
2796 m_positivePrefixCurrencySymbol =
prefix;
2801 m_negativePrefixCurrencySymbol =
prefix;
2806 m_monetaryDecimalPlaces = digits;
2812 m_monetaryThousandsSeparator = separator;
2817 m_monetaryDigitGrouping = groupList;
2822 m_monetaryDecimalSymbol = symbol.trimmed();
2827 m_currencySymbol = symbol.trimmed();
2843 return m_measureSystem;
2848 m_measureSystem = value;
2853 static const QString en_US = QString::fromLatin1(
"en_US");
2859 return QString::fromLatin1(
"C");
2864 return QString::fromLatin1(
"USD");
2869 return m_useTranscript;
2884 if (m_utf8FileEncoding) {
2892 return m_codecForEncoding;
2897 QTextCodec * codec = QTextCodec::codecForMib(mibEnum);
2899 m_codecForEncoding = codec;
2917 foreach (
const QString &path, paths) {
2918 QString part = path.left(path.length() - 14);
2919 languages.append(part.mid(part.lastIndexOf(QLatin1Char(
'/')) + 1));
2939 for (QStringList::ConstIterator it = paths.begin(); it != paths.end(); ++it) {
2940 QString code = (*it).mid((*it).length() - 16, 2);
2941 if (code != QLatin1String(
"/C")) {
2942 countries.append(code);
2951 QString entryFile =
KStandardDirs::locate(
"locale", QString::fromLatin1(
"l10n/") + country.toLower() + QLatin1String(
"/entry.desktop"));
2952 if (!entryFile.isEmpty()) {
2962 if (calendarType == QLatin1String(
"coptic")) {
2964 }
else if (calendarType == QLatin1String(
"ethiopian")) {
2966 }
else if (calendarType == QLatin1String(
"gregorian")) {
2968 }
else if (calendarType == QLatin1String(
"gregorian-proleptic")) {
2970 }
else if (calendarType == QLatin1String(
"hebrew")) {
2972 }
else if (calendarType == QLatin1String(
"hijri")) {
2974 }
else if (calendarType == QLatin1String(
"indian-national")) {
2976 }
else if (calendarType == QLatin1String(
"jalali")) {
2978 }
else if (calendarType == QLatin1String(
"japanese")) {
2980 }
else if (calendarType == QLatin1String(
"julian")) {
2982 }
else if (calendarType == QLatin1String(
"minguo")) {
2984 }
else if (calendarType == QLatin1String(
"thai")) {
2993 switch (calendarSystem) {
2995 return QLatin1String(
"gregorian");
2997 return QLatin1String(
"coptic");
2999 return QLatin1String(
"ethiopian");
3001 return QLatin1String(
"gregorian-proleptic");
3003 return QLatin1String(
"hebrew");
3005 return QLatin1String(
"hijri");
3007 return QLatin1String(
"indian-national");
3009 return QLatin1String(
"jalali");
3011 return QLatin1String(
"japanese");
3013 return QLatin1String(
"julian");
3015 return QLatin1String(
"minguo");
3017 return QLatin1String(
"thai");
3019 return QLatin1String(
"gregorian");
3042 return m_calendarSystem;
3061 return m_weekNumberSystem;
3067 locale->d->m_catalogNames = m_catalogNames;
3079 QFileInfo fileInfo(filePath);
3080 QString locDirPath = fileInfo.path() + QLatin1String(
"/l10n");
3081 QFileInfo locDirInfo(locDirPath);
3082 if (!locDirInfo.isDir()) {
3088 QString fileName = fileInfo.fileName();
3094 QString locFilePath = locDirPath + QLatin1Char(
'/') + lang + QLatin1Char(
'/') + fileName;
3095 QFileInfo locFileInfo(locFilePath);
3096 if (locFileInfo.isFile() && locFileInfo.isReadable()) {
3126 return m_monetaryDigitSet;
3136 return m_dateTimeDigitSet;
3143 return s_kLocaleMutex();