00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include "klocale.h"
00025 #include "klocale_p.h"
00026
00027 #include <config.h>
00028
00029 #ifdef HAVE_SYS_TIME_H
00030 #include <sys/time.h>
00031 #endif
00032 #ifdef HAVE_TIME_H
00033 #include <time.h>
00034 #endif
00035 #ifdef HAVE_LANGINFO_H
00036 #include <langinfo.h>
00037 #endif
00038
00039 #include <QtCore/QTextCodec>
00040 #include <QtCore/QFile>
00041 #include <QtGui/QPrinter>
00042 #include <QtCore/QFileInfo>
00043 #include <QtCore/QRegExp>
00044 #include <QtCore/QLocale>
00045 #include <QtCore/QHash>
00046 #include <QtCore/QMutexLocker>
00047
00048 #include "kcatalog_p.h"
00049 #include "kglobal.h"
00050 #include "kstandarddirs.h"
00051 #include "kconfig.h"
00052 #include "kcomponentdata.h"
00053 #include "kdebug.h"
00054 #include "kdatetime.h"
00055 #include "kcalendarsystem.h"
00056 #include "klocalizedstring.h"
00057 #include "ktranslit_p.h"
00058 #include "kconfiggroup.h"
00059 #include "kcatalogname_p.h"
00060 #include "common_helpers_p.h"
00061
00062 #ifdef Q_WS_WIN
00063 #include <windows.h>
00064 #endif
00065
00066 class KLocaleStaticData
00067 {
00068 public:
00069
00070 KLocaleStaticData ();
00071
00072 QString maincatalog;
00073
00074
00075 QHash<KLocale::DigitSet, QStringList> languagesUsingDigitSet;
00076 };
00077
00078 KLocaleStaticData::KLocaleStaticData ()
00079 {
00080
00081
00082 #define SET_LANGS_FOR_DS(ds, langs) do { \
00083 languagesUsingDigitSet[KLocale::ds] = QStringList(); \
00084 languagesUsingDigitSet[KLocale::ds] << langs; \
00085 } while (0)
00086 SET_LANGS_FOR_DS(ArabicIndicDigits, "ar" << "ps");
00087 SET_LANGS_FOR_DS(EasternArabicIndicDigits, "fa" << "ur");
00088 SET_LANGS_FOR_DS(DevenagariDigits, "hi" << "ne");
00089 }
00090
00091 K_GLOBAL_STATIC(KLocaleStaticData, staticData)
00092
00093
00094 QDebug operator<<(QDebug debug, const KCatalogName &cn)
00095 {
00096 return debug << cn.name << cn.loadCount;
00097 }
00098
00099 class KLocalePrivate
00100 {
00101 public:
00102 KLocalePrivate(const QString& catalog, KConfig *config, const QString &language_ = QString(), const QString &country_ = QString());
00106 void initMainCatalogs();
00107
00116 void initLanguageList(KConfig *config, bool useEnv);
00117
00121 void initEncoding();
00122
00127 void initFileNameEncoding();
00128
00132 static QByteArray encodeFileNameUTF8( const QString & fileName );
00133
00137 static QString decodeFileNameUTF8( const QByteArray & localFileName );
00138
00142 void initFormat(KConfig *config);
00143
00147 bool setLanguage(const QString & _language, KConfig *config);
00148
00152 bool setLanguage(const QStringList & languages);
00153
00157 bool setEncoding(int mibEnum);
00158
00162 void translate_priv(const char *msgctxt,
00163 const char *msgid,
00164 const char *msgid_plural = 0,
00165 unsigned long n = 0,
00166 QString *language = 0,
00167 QString *translation = 0) const;
00168
00172 bool useDefaultLanguage() const;
00173
00180 void updateCatalogs( );
00181
00187 bool isApplicationTranslatedInto( const QString & language);
00188
00192 static QString formatDateTime(const KLocale *locale, const QDateTime &dateTime,
00193 KLocale::DateFormat, bool includeSeconds, int daysToNow);
00197 static QString fancyDate(const KLocale *locale, const QDate &date, int daysToNow);
00198
00199 enum DurationType {
00200 DaysDurationType = 0,
00201 HoursDurationType,
00202 MinutesDurationType,
00203 SecondsDurationType
00204 };
00208 static QString formatSingleDuration( DurationType durationType, int n );
00209
00210
00211 QString decimalSymbol;
00212 QString thousandsSeparator;
00213 QString currencySymbol;
00214 QString monetaryDecimalSymbol;
00215 QString monetaryThousandsSeparator;
00216 QString positiveSign;
00217 QString negativeSign;
00218 KLocale::DigitSet digitSet;
00219 int fracDigits;
00220 KLocale::SignPosition positiveMonetarySignPosition;
00221 KLocale::SignPosition negativeMonetarySignPosition;
00222 bool positivePrefixCurrencySymbol : 1;
00223 bool negativePrefixCurrencySymbol : 1;
00224 KLocale::DigitSet monetaryDigitSet;
00225
00226
00227 QString timeFormat;
00228 QString dateFormat;
00229 QString dateFormatShort;
00230 int weekStartDay;
00231 int workingWeekStartDay;
00232 int workingWeekEndDay;
00233 int weekDayOfPray;
00234 KLocale::DigitSet dateTimeDigitSet;
00235
00236
00237 bool languageSensitiveDigits;
00238
00239
00240 QString language;
00241 QString country;
00242
00243
00244 QStringList languageList;
00245
00246 QList<KCatalogName> catalogNames;
00247 QList<KCatalog> catalogs;
00248 int numberOfSysCatalogs;
00249 bool useTranscript;
00250
00251
00252 QString encoding;
00253 QTextCodec * codecForEncoding;
00254
00255 int pageSize;
00256 KLocale::MeasureSystem measureSystem;
00257 KConfig * languages;
00258
00259 QString calendarType;
00260 KCalendarSystem * calendar;
00261 QString catalogName;
00262 bool nounDeclension:1;
00263 bool dateMonthNamePossessive:1;
00264 bool utf8FileEncoding:1;
00265 #ifdef Q_WS_WIN
00266 char win32SystemEncoding[3+7];
00267 #endif
00268
00269
00270 enum ByteSizeFmt {
00271 TiB, GiB, MiB, KiB, B
00272 };
00273 QList<QString> byteSizeFmt;
00274 };
00275
00276 KLocalePrivate::KLocalePrivate(const QString& catalog, KConfig *config, const QString &language_, const QString &country_)
00277 : language(language_),
00278 country(country_),
00279 useTranscript(false),
00280 codecForEncoding(0),
00281 languages(0), calendar(0),
00282 catalogName(catalog)
00283 {
00284 initEncoding();
00285 initFileNameEncoding();
00286
00287 if (config) {
00288 initLanguageList(config, false);
00289 }
00290 else {
00291 config = KGlobal::config().data();
00292 initLanguageList(config, true);
00293 }
00294
00295 initMainCatalogs();
00296
00297 initFormat(config);
00298 }
00299
00300 KLocale::KLocale( const QString & catalog, KSharedConfig::Ptr config )
00301 : d(new KLocalePrivate(catalog, config.data()))
00302 {
00303 }
00304
00305 KLocale::KLocale(const QString& catalog, const QString &language, const QString &country, KConfig *config)
00306 : d(new KLocalePrivate(catalog, config, language, country))
00307 {
00308 }
00309
00310 void KLocalePrivate::initMainCatalogs()
00311 {
00312 KLocaleStaticData *s = staticData;
00313 QMutexLocker lock(kLocaleMutex());
00314
00315 if (!s->maincatalog.isEmpty()) {
00316
00317 catalogName = s->maincatalog;
00318 }
00319
00320 if (catalogName.isEmpty()) {
00321 kDebug(173) << "KLocale instance created called without valid "
00322 << "catalog! Give an argument or call setMainCatalog "
00323 << "before init" << endl;
00324 }
00325 else {
00326
00327 catalogNames.append(KCatalogName(catalogName));
00328
00329
00330 numberOfSysCatalogs = 4;
00331 catalogNames.append(KCatalogName("libphonon"));
00332 catalogNames.append(KCatalogName("kio4"));
00333 catalogNames.append(KCatalogName("kdelibs4"));
00334 catalogNames.append(KCatalogName("kdeqt"));
00335
00336 updateCatalogs();
00337 }
00338 }
00339
00340 static inline void getLanguagesFromVariable(QStringList& list, const char* variable)
00341 {
00342 QByteArray var( qgetenv(variable) );
00343 if (!var.isEmpty())
00344 list += QFile::decodeName(var).split(':');
00345 }
00346
00347 void KLocalePrivate::initLanguageList(KConfig *config, bool useEnv)
00348 {
00349 KConfigGroup cg(config, "Locale");
00350
00351
00352
00353 if (country.isEmpty())
00354 country = cg.readEntry("Country");
00355 if (country.isEmpty())
00356 country = KLocale::defaultCountry();
00357
00358
00359
00360
00361
00362
00363
00364 QStringList list;
00365
00366 if (!language.isEmpty())
00367 list.append(language);
00368
00369
00370 if (useEnv)
00371 getLanguagesFromVariable(list, "KDE_LANG");
00372
00373
00374 QString languages(cg.readEntry("Language", QString()));
00375 if (!languages.isEmpty())
00376 list += languages.split(':');
00377
00378
00379 QStringList rawList;
00380 if (useEnv) {
00381
00382
00383
00384
00385 getLanguagesFromVariable(list, "LANGUAGE");
00386
00387
00388
00389 getLanguagesFromVariable(rawList, "LC_ALL");
00390 getLanguagesFromVariable(rawList, "LC_MESSAGES");
00391 getLanguagesFromVariable(rawList, "LANG");
00392 }
00393 #ifdef Q_WS_WIN // how about Mac?
00394 rawList += QLocale::system().name();
00395 #endif
00396
00397 #ifndef Q_WS_WIN
00398 if (useEnv)
00399 #endif
00400 {
00401
00402 foreach (const QString &ln, rawList) {
00403 QString lang, ctry, modf, cset;
00404 KLocale::splitLocale(ln, lang, ctry, modf, cset);
00405
00406 if (!ctry.isEmpty() && !modf.isEmpty()) {
00407 list += lang + '_' + ctry + '@' + modf;
00408 }
00409
00410
00411
00412 if (!modf.isEmpty()) {
00413 list += lang + '@' + modf;
00414 }
00415 if (!ctry.isEmpty()) {
00416 list += lang + '_' + ctry;
00417 }
00418 list += lang;
00419 }
00420 }
00421
00422
00423 setLanguage(list);
00424 }
00425
00426 void KLocalePrivate::initFormat(KConfig *config)
00427 {
00428 Q_ASSERT(config);
00429
00430
00431
00432 config->setLocale(language);
00433
00434 KConfigGroup cg(config, "Locale");
00435
00436 KConfig entryFile(KStandardDirs::locate("locale",
00437 QString::fromLatin1("l10n/%1/entry.desktop")
00438 .arg(country)));
00439 entryFile.setLocale(language);
00440 KConfigGroup entry(&entryFile, "KCM Locale");
00441
00442
00443 #define readConfigEntry(key, default, save) \
00444 save = entry.readEntry(key, default); \
00445 save = cg.readEntry(key, save);
00446
00447 #define readConfigNumEntry(key, default, save, type) \
00448 save = (type)entry.readEntry(key, int(default)); \
00449 save = (type)cg.readEntry(key, int(save));
00450
00451 readConfigEntry("DecimalSymbol", ".", decimalSymbol);
00452 readConfigEntry("ThousandsSeparator", ",", thousandsSeparator);
00453 thousandsSeparator.remove( QString::fromLatin1("$0") );
00454
00455
00456 readConfigEntry("PositiveSign", "", positiveSign);
00457 readConfigEntry("NegativeSign", "-", negativeSign);
00458
00459 readConfigNumEntry("DigitSet", KLocale::ArabicDigits,
00460 digitSet, KLocale::DigitSet);
00461
00462 readConfigEntry("LanguageSensitiveDigits", true,
00463 languageSensitiveDigits);
00464
00465
00466 readConfigEntry("CurrencySymbol", "$", currencySymbol);
00467 readConfigEntry("MonetaryDecimalSymbol", ".", monetaryDecimalSymbol);
00468 readConfigEntry("MonetaryThousandsSeparator", ",",
00469 monetaryThousandsSeparator);
00470 monetaryThousandsSeparator.remove(QString::fromLatin1("$0"));
00471
00472 readConfigNumEntry("FracDigits", 2, fracDigits, int);
00473 readConfigEntry("PositivePrefixCurrencySymbol", true,
00474 positivePrefixCurrencySymbol);
00475 readConfigEntry("NegativePrefixCurrencySymbol", true,
00476 negativePrefixCurrencySymbol);
00477 readConfigNumEntry("PositiveMonetarySignPosition", KLocale::BeforeQuantityMoney,
00478 positiveMonetarySignPosition, KLocale::SignPosition);
00479 readConfigNumEntry("NegativeMonetarySignPosition", KLocale::ParensAround,
00480 negativeMonetarySignPosition, KLocale::SignPosition);
00481
00482 readConfigNumEntry("MonetaryDigitSet", KLocale::ArabicDigits,
00483 monetaryDigitSet, KLocale::DigitSet);
00484
00485
00486 readConfigEntry("TimeFormat", "%H:%M:%S", timeFormat);
00487 readConfigEntry("DateFormat", "%A %d %B %Y", dateFormat);
00488 readConfigEntry("DateFormatShort", "%Y-%m-%d", dateFormatShort);
00489 readConfigNumEntry("WeekStartDay", 1, weekStartDay, int);
00490 readConfigNumEntry("WorkingWeekStartDay", 1, workingWeekStartDay, int);
00491 readConfigNumEntry("WorkingWeekEndDay", 5, workingWeekEndDay, int);
00492 readConfigNumEntry("WeekDayOfPray", 7, weekDayOfPray, int);
00493 readConfigNumEntry("DateTimeDigitSet", KLocale::ArabicDigits,
00494 dateTimeDigitSet, KLocale::DigitSet);
00495
00496
00497 readConfigNumEntry("PageSize", QPrinter::A4, pageSize,
00498 QPrinter::PageSize);
00499 readConfigNumEntry("MeasureSystem", KLocale::Metric,
00500 measureSystem, KLocale::MeasureSystem);
00501 readConfigEntry("CalendarSystem", "gregorian", calendarType);
00502 delete calendar;
00503 calendar = 0;
00504
00505 readConfigEntry("Transcript", true, useTranscript);
00506
00507
00508
00509 KConfig langCfg(KStandardDirs::locate("locale",
00510 QString::fromLatin1("%1/entry.desktop")
00511 .arg(language)));
00512 KConfigGroup lang(&langCfg,"KCM Locale");
00513 #define read3ConfigBoolEntry(key, default, save) \
00514 save = entry.readEntry(key, default); \
00515 save = lang.readEntry(key, save); \
00516 save = cg.readEntry(key, save);
00517
00518 read3ConfigBoolEntry("NounDeclension", false, nounDeclension);
00519 read3ConfigBoolEntry("DateMonthNamePossessive", false,
00520 dateMonthNamePossessive);
00521 }
00522
00523 bool KLocale::setCountry(const QString & aCountry, KConfig *config)
00524 {
00525
00526 if ( aCountry.isEmpty() )
00527 return false;
00528
00529 d->country = aCountry;
00530
00531 d->initFormat(config);
00532
00533 return true;
00534 }
00535
00536 bool KLocale::setLanguage(const QString & language, KConfig *config)
00537 {
00538 return d->setLanguage(language, config);
00539 }
00540
00541 bool KLocalePrivate::setLanguage(const QString & _language, KConfig *config)
00542 {
00543 QMutexLocker lock(kLocaleMutex());
00544 languageList.removeAll( _language );
00545 languageList.prepend( _language );
00546
00547 language = _language;
00548
00549
00550
00551 updateCatalogs();
00552
00553 initFormat(config);
00554
00555 return true;
00556 }
00557
00558 bool KLocale::setLanguage(const QStringList & languages)
00559 {
00560 return d->setLanguage(languages);
00561 }
00562
00563 bool KLocalePrivate::setLanguage(const QStringList & languages)
00564 {
00565 QMutexLocker lock(kLocaleMutex());
00566
00567
00568
00569
00570
00571
00572
00573
00574
00575
00576 QStringList list;
00577 foreach (const QString &language, languages) {
00578 if (!language.isEmpty() && !list.contains(language) && isApplicationTranslatedInto(language)) {
00579 list.append(language);
00580 }
00581 }
00582
00583 if ( !list.contains( KLocale::defaultLanguage() ) ) {
00584
00585
00586
00587 list.append( KLocale::defaultLanguage() );
00588 }
00589
00590 language = list.first();
00591
00592 languageList = list;
00593
00594
00595
00596 updateCatalogs();
00597
00598 return true;
00599 }
00600
00601 bool KLocale::isApplicationTranslatedInto( const QString & lang)
00602 {
00603 return d->isApplicationTranslatedInto( lang );
00604 }
00605
00606 bool KLocalePrivate::isApplicationTranslatedInto( const QString & lang)
00607 {
00608 if ( lang.isEmpty() ) {
00609 return false;
00610 }
00611
00612 if ( lang == KLocale::defaultLanguage() ) {
00613
00614 return true;
00615 }
00616
00617 if (catalogName.isEmpty()) {
00618 kDebug() << "no appName!";
00619 return false;
00620 }
00621
00622
00623 QStringList possibles;
00624 possibles += lang;
00625 possibles += KTranslit::fallbackList(lang);
00626 foreach (const QString &lang, possibles) {
00627 if ( ! KCatalog::catalogLocaleDir( catalogName, lang ).isEmpty() ) {
00628 return true;
00629 }
00630 }
00631 return false;
00632 }
00633
00634 void KLocale::splitLocale(const QString &aLocale,
00635 QString &language,
00636 QString &country,
00637 QString &modifier,
00638 QString &charset)
00639 {
00640 QString locale = aLocale;
00641
00642 language.clear();
00643 country.clear();
00644 modifier.clear();
00645 charset.clear();
00646
00647
00648
00649 int f = locale.indexOf(':');
00650 if (f >= 0) {
00651 locale.truncate(f);
00652 }
00653
00654 f = locale.indexOf('.');
00655 if (f >= 0) {
00656 charset = locale.mid(f + 1);
00657 locale.truncate(f);
00658 }
00659
00660 f = locale.indexOf('@');
00661 if (f >= 0) {
00662 modifier = locale.mid(f + 1);
00663 locale.truncate(f);
00664 }
00665
00666 f = locale.indexOf('_');
00667 if (f >= 0) {
00668 country = locale.mid(f + 1);
00669 locale.truncate(f);
00670 }
00671
00672 language = locale;
00673 }
00674
00675 QString KLocale::language() const
00676 {
00677 return d->language;
00678 }
00679
00680 QString KLocale::country() const
00681 {
00682 return d->country;
00683 }
00684
00685 void KLocale::insertCatalog( const QString & catalog )
00686 {
00687 QMutexLocker lock(kLocaleMutex());
00688 int pos = d->catalogNames.indexOf(KCatalogName(catalog));
00689 if (pos != -1) {
00690 ++d->catalogNames[pos].loadCount;
00691 return;
00692 }
00693
00694
00695
00696 d->catalogNames.insert(d->catalogNames.size() - d->numberOfSysCatalogs,
00697 KCatalogName(catalog));
00698 d->updateCatalogs();
00699 }
00700
00701 void KLocalePrivate::updateCatalogs( )
00702 {
00703
00704
00705
00706
00707 QList<KCatalog> newCatalogs;
00708
00709
00710 QStringList languageListFB;
00711 foreach (const QString &lang, languageList) {
00712 languageListFB += lang;
00713 languageListFB += KTranslit::fallbackList(lang);
00714 }
00715
00716
00717
00718
00719
00720 foreach ( const QString &lang, languageListFB ) {
00721 foreach ( const KCatalogName &name, catalogNames ) {
00722
00723 if ( ! KCatalog::catalogLocaleDir( name.name, lang ).isEmpty() )
00724 {
00725 newCatalogs.append( KCatalog( name.name, lang ) );
00726
00727 }
00728 }
00729 }
00730
00731
00732 catalogs = newCatalogs;
00733 KLocalizedString::notifyCatalogsUpdated(languageListFB, catalogNames);
00734 }
00735
00736 void KLocale::removeCatalog(const QString &catalog)
00737 {
00738 QMutexLocker lock(kLocaleMutex());
00739 int pos = d->catalogNames.indexOf(KCatalogName(catalog));
00740 if (pos == -1)
00741 return;
00742 if (--d->catalogNames[pos].loadCount > 0)
00743 return;
00744 d->catalogNames.removeAt(pos);
00745 if (KGlobal::hasMainComponent())
00746 d->updateCatalogs();
00747 }
00748
00749 void KLocale::setActiveCatalog(const QString &catalog)
00750 {
00751 QMutexLocker lock(kLocaleMutex());
00752 int pos = d->catalogNames.indexOf(KCatalogName(catalog));
00753 if (pos == -1)
00754 return;
00755 d->catalogNames.move(pos, 0);
00756 d->updateCatalogs();
00757 }
00758
00759 KLocale::~KLocale()
00760 {
00761 delete d->calendar;
00762 delete d->languages;
00763 delete d;
00764 }
00765
00766 void KLocalePrivate::translate_priv(const char *msgctxt,
00767 const char *msgid,
00768 const char *msgid_plural,
00769 unsigned long n,
00770 QString *language,
00771 QString *translation) const
00772 {
00773 if ( !msgid || !msgid[0] ) {
00774 kDebug(173) << "KLocale: trying to look up \"\" in catalog. "
00775 << "Fix the program" << endl;
00776 language->clear();
00777 translation->clear();
00778 return;
00779 }
00780 if ( msgctxt && !msgctxt[0] ) {
00781 kDebug(173) << "KLocale: trying to use \"\" as context to message. "
00782 << "Fix the program" << endl;
00783 }
00784 if ( msgid_plural && !msgid_plural[0] ) {
00785 kDebug(173) << "KLocale: trying to use \"\" as plural message. "
00786 << "Fix the program" << endl;
00787 }
00788
00789 QMutexLocker locker(kLocaleMutex());
00790
00791 QString fallback;
00792 if ( msgid_plural == NULL )
00793 fallback = QString::fromUtf8( msgid );
00794 else {
00795 if ( n == 1 )
00796 fallback = QString::fromUtf8( msgid );
00797 else
00798 fallback = QString::fromUtf8( msgid_plural );
00799 }
00800 if ( language )
00801 *language = KLocale::defaultLanguage();
00802 if ( translation )
00803 *translation = fallback;
00804
00805
00806 if ( useDefaultLanguage() )
00807 return;
00808
00809 QList<KCatalog> catalogList = catalogs;
00810 for ( QList<KCatalog>::ConstIterator it = catalogList.constBegin();
00811 it != catalogList.constEnd();
00812 ++it )
00813 {
00814
00815
00816
00817 if ( (*it).language() == KLocale::defaultLanguage() )
00818 return;
00819
00820 QString text;
00821 if ( msgctxt != NULL && msgid_plural != NULL )
00822 text = (*it).translateStrict( msgctxt, msgid, msgid_plural, n );
00823 else if ( msgid_plural != NULL )
00824 text = (*it).translateStrict( msgid, msgid_plural, n );
00825 else if ( msgctxt != NULL )
00826 text = (*it).translateStrict( msgctxt, msgid );
00827 else
00828 text = (*it).translateStrict( msgid );
00829
00830 if ( !text.isEmpty() ) {
00831
00832 if ( language )
00833 *language = (*it).language();
00834 if ( translation )
00835 *translation = text;
00836 return;
00837 }
00838 }
00839 }
00840
00841 void KLocale::translateRaw(const char* msg,
00842 QString *lang, QString *trans) const
00843 {
00844 d->translate_priv(0, msg, 0, 0, lang, trans);
00845 }
00846
00847 void KLocale::translateRaw(const char *ctxt, const char *msg,
00848 QString *lang, QString *trans) const
00849 {
00850 d->translate_priv(ctxt, msg, 0, 0, lang, trans);
00851 }
00852
00853 void KLocale::translateRaw(const char *singular, const char *plural, unsigned long n,
00854 QString *lang, QString *trans) const
00855 {
00856 d->translate_priv(0, singular, plural, n, lang, trans);
00857 }
00858
00859 void KLocale::translateRaw(const char *ctxt, const char *singular, const char *plural,
00860 unsigned long n,
00861 QString *lang, QString *trans) const
00862 {
00863 d->translate_priv(ctxt, singular, plural, n, lang, trans);
00864 }
00865
00866 QString KLocale::translateQt(const char *context, const char *sourceText,
00867 const char *comment) const
00868 {
00869
00870
00871
00872
00873
00874
00875
00876
00877
00878
00879
00880
00881
00882
00883
00884
00885
00886
00887
00888
00889
00890
00891 if (!sourceText || !sourceText[0]) {
00892 kDebug(173) << "KLocale: trying to look up \"\" in catalog. "
00893 << "Fix the program" << endl;
00894 return QString();
00895 }
00896
00897 if (d->useDefaultLanguage()) {
00898 return QString();
00899 }
00900
00901 QString translation;
00902 QString language;
00903
00904
00905
00906
00907 if (comment && comment[0]) {
00908
00909 d->translate_priv(comment, sourceText, 0, 0, &language, &translation);
00910 }
00911 else {
00912
00913 if (context && context[0]) {
00914 d->translate_priv(context, sourceText, 0, 0, &language, &translation);
00915 }
00916 if (language.isEmpty() || language == defaultLanguage()) {
00917 d->translate_priv(0, sourceText, 0, 0, &language, &translation);
00918 }
00919 }
00920
00921 if (language != defaultLanguage()) {
00922 return translation;
00923 }
00924
00925
00926 return QString();
00927 }
00928
00929 QList<KLocale::DigitSet> KLocale::allDigitSetsList () const
00930 {
00931 QList<DigitSet> digitSets;
00932 digitSets.append(ArabicDigits);
00933 digitSets.append(ArabicIndicDigits);
00934 digitSets.append(EasternArabicIndicDigits);
00935 digitSets.append(DevenagariDigits);
00936 return digitSets;
00937 }
00938
00939 static QString digitSetString (KLocale::DigitSet digitSet)
00940 {
00941 switch (digitSet) {
00942 case KLocale::ArabicIndicDigits:
00943 return QString::fromUtf8("٠١٢٣٤٥٦٧٨٩");
00944 case KLocale::EasternArabicIndicDigits:
00945 return QString::fromUtf8("Û°Û±Û²Û³Û´ÛµÛ¶Û·Û¸Û¹");
00946 case KLocale::DevenagariDigits:
00947 return QString::fromUtf8("०१२३४५६à¥à¥®à¥¯");
00948 default:
00949 return QString::fromUtf8("0123456789");
00950 }
00951 }
00952
00953 QString KLocale::digitSetToName (DigitSet digitSet, bool withDigits) const
00954 {
00955 QString name;
00956 switch (digitSet) {
00957 case KLocale::ArabicIndicDigits:
00958 name = i18nc("digit set", "Arabic-Indic");
00959 break;
00960 case KLocale::EasternArabicIndicDigits:
00961 name = i18nc("digit set", "Eastern Arabic-Indic");
00962 break;
00963 case KLocale::DevenagariDigits:
00964 name = i18nc("digit set", "Devenagari");
00965 break;
00966 default:
00967 name = i18nc("digit set", "Arabic");
00968 }
00969 if (withDigits) {
00970 QString digits = digitSetString(digitSet);
00971 QString nameWithDigits = i18nc("name of digit set with digit string, "
00972 "e.g. 'Arabic (0123456789)'",
00973 "%1 (%2)", name, digits);
00974 return nameWithDigits;
00975 } else {
00976 return name;
00977 }
00978 }
00979
00980 QString KLocale::convertDigits (const QString &str, DigitSet digitSet,
00981 bool ignoreContext) const
00982 {
00983 if (!ignoreContext) {
00984
00985
00986
00987 KLocaleStaticData *s = staticData;
00988 if ( d->languageSensitiveDigits
00989 && !s->languagesUsingDigitSet[digitSet].contains(d->language))
00990 {
00991 digitSet = KLocale::ArabicDigits;
00992 }
00993 }
00994
00995 QString nstr;
00996 QString digitDraw = digitSetString(digitSet);
00997 foreach (const QChar &c, str) {
00998 if (c.isDigit()) {
00999 nstr += digitDraw[c.digitValue()];
01000 } else {
01001 nstr += c;
01002 }
01003 }
01004 return nstr;
01005 }
01006
01007 static QString toArabicDigits(const QString &str)
01008 {
01009 QString nstr;
01010 foreach (const QChar &c, str) {
01011 if (c.isDigit()) {
01012 nstr += QChar('0' + c.digitValue());
01013 } else {
01014 nstr += c;
01015 }
01016 }
01017 return nstr;
01018 }
01019
01020 bool KLocale::nounDeclension() const
01021 {
01022 return d->nounDeclension;
01023 }
01024
01025 bool KLocale::dateMonthNamePossessive() const
01026 {
01027 return d->dateMonthNamePossessive;
01028 }
01029
01030 int KLocale::weekStartDay() const
01031 {
01032 return d->weekStartDay;
01033 }
01034
01035 int KLocale::workingWeekStartDay() const
01036 {
01037 return d->workingWeekStartDay;
01038 }
01039
01040 int KLocale::workingWeekEndDay() const
01041 {
01042 return d->workingWeekEndDay;
01043 }
01044
01045 int KLocale::weekDayOfPray() const
01046 {
01047 return d->weekDayOfPray;
01048 }
01049
01050
01051 QString KLocale::decimalSymbol() const
01052 {
01053 return d->decimalSymbol;
01054 }
01055
01056 QString KLocale::thousandsSeparator() const
01057 {
01058 return d->thousandsSeparator;
01059 }
01060
01061 QString KLocale::currencySymbol() const
01062 {
01063 return d->currencySymbol;
01064 }
01065
01066 QString KLocale::monetaryDecimalSymbol() const
01067 {
01068 return d->monetaryDecimalSymbol;
01069 }
01070
01071 QString KLocale::monetaryThousandsSeparator() const
01072 {
01073 return d->monetaryThousandsSeparator;
01074 }
01075
01076 QString KLocale::positiveSign() const
01077 {
01078 return d->positiveSign;
01079 }
01080
01081 QString KLocale::negativeSign() const
01082 {
01083 return d->negativeSign;
01084 }
01085
01086 int KLocale::fracDigits() const
01087 {
01088 return d->fracDigits;
01089 }
01090
01091 bool KLocale::positivePrefixCurrencySymbol() const
01092 {
01093 return d->positivePrefixCurrencySymbol;
01094 }
01095
01096 bool KLocale::negativePrefixCurrencySymbol() const
01097 {
01098 return d->negativePrefixCurrencySymbol;
01099 }
01100
01101 KLocale::SignPosition KLocale::positiveMonetarySignPosition() const
01102 {
01103 return d->positiveMonetarySignPosition;
01104 }
01105
01106 KLocale::SignPosition KLocale::negativeMonetarySignPosition() const
01107 {
01108 return d->negativeMonetarySignPosition;
01109 }
01110
01111 static inline void put_it_in( QChar *buffer, int& index, const QString &s )
01112 {
01113 for ( int l = 0; l < s.length(); l++ )
01114 buffer[index++] = s.at( l );
01115 }
01116
01117 static inline void put_it_in( QChar *buffer, int& index, int number )
01118 {
01119 buffer[index++] = number / 10 + '0';
01120 buffer[index++] = number % 10 + '0';
01121 }
01122
01123
01124 static void _insertSeparator(QString &str, const QString &separator,
01125 const QString &decimalSymbol)
01126 {
01127
01128 const int decimalSymbolPos = str.indexOf(decimalSymbol);
01129 const int start = decimalSymbolPos == -1 ? str.length() : decimalSymbolPos;
01130 for (int pos = start - 3; pos > 0; pos -= 3)
01131 str.insert(pos, separator);
01132 }
01133
01134 QString KLocale::formatMoney(double num,
01135 const QString & symbol,
01136 int precision) const
01137 {
01138
01139 QString currency = symbol.isNull()
01140 ? currencySymbol()
01141 : symbol;
01142 if (precision < 0) precision = fracDigits();
01143
01144
01145 bool neg = num < 0;
01146 QString res = QString::number(neg?-num:num, 'f', precision);
01147
01148
01149 res.replace(QChar('.'), monetaryDecimalSymbol());
01150
01151
01152 _insertSeparator(res, monetaryThousandsSeparator(), monetaryDecimalSymbol());
01153
01154
01155 int signpos = neg
01156 ? negativeMonetarySignPosition()
01157 : positiveMonetarySignPosition();
01158 QString sign = neg
01159 ? negativeSign()
01160 : positiveSign();
01161
01162 switch (signpos)
01163 {
01164 case ParensAround:
01165 res.prepend(QLatin1Char('('));
01166 res.append (QLatin1Char(')'));
01167 break;
01168 case BeforeQuantityMoney:
01169 res.prepend(sign);
01170 break;
01171 case AfterQuantityMoney:
01172 res.append(sign);
01173 break;
01174 case BeforeMoney:
01175 currency.prepend(sign);
01176 break;
01177 case AfterMoney:
01178 currency.append(sign);
01179 break;
01180 }
01181
01182 if (neg?negativePrefixCurrencySymbol():
01183 positivePrefixCurrencySymbol())
01184 {
01185 res.prepend(QLatin1Char(' '));
01186 res.prepend(currency);
01187 } else {
01188 res.append (QLatin1Char(' '));
01189 res.append (currency);
01190 }
01191
01192
01193 res = convertDigits(res, d->monetaryDigitSet);
01194
01195 return res;
01196 }
01197
01198
01199 QString KLocale::formatNumber(double num, int precision) const
01200 {
01201 if (precision == -1) precision = 2;
01202
01203 return formatNumber(QString::number(num, 'f', precision), false, 0);
01204 }
01205
01206 QString KLocale::formatLong(long num) const
01207 {
01208 return formatNumber((double)num, 0);
01209 }
01210
01211
01212
01213 static void _inc_by_one(QString &str, int position)
01214 {
01215 for (int i = position; i >= 0; i--)
01216 {
01217 char last_char = str[i].toLatin1();
01218 switch(last_char)
01219 {
01220 case '0':
01221 str[i] = '1';
01222 break;
01223 case '1':
01224 str[i] = '2';
01225 break;
01226 case '2':
01227 str[i] = '3';
01228 break;
01229 case '3':
01230 str[i] = '4';
01231 break;
01232 case '4':
01233 str[i] = '5';
01234 break;
01235 case '5':
01236 str[i] = '6';
01237 break;
01238 case '6':
01239 str[i] = '7';
01240 break;
01241 case '7':
01242 str[i] = '8';
01243 break;
01244 case '8':
01245 str[i] = '9';
01246 break;
01247 case '9':
01248 str[i] = '0';
01249 if (i == 0) str.prepend('1');
01250 continue;
01251 case '.':
01252 continue;
01253 }
01254 break;
01255 }
01256 }
01257
01258
01259 static void _round(QString &str, int precision)
01260 {
01261 int decimalSymbolPos = str.indexOf('.');
01262
01263 if (decimalSymbolPos == -1) {
01264 if (precision == 0) return;
01265 else if (precision > 0)
01266 {
01267 str.append('.');
01268 decimalSymbolPos = str.length() - 1;
01269 }
01270 }
01271
01272 str.reserve(str.length() + precision);
01273 for (int i = 0; i < precision; ++i)
01274 str.append('0');
01275
01276
01277 char last_char = str[decimalSymbolPos + precision + 1].toLatin1();
01278 switch (last_char)
01279 {
01280 case '0':
01281 case '1':
01282 case '2':
01283 case '3':
01284 case '4':
01285
01286 break;
01287 case '5':
01288 case '6':
01289 case '7':
01290 case '8':
01291 case '9':
01292 _inc_by_one(str, decimalSymbolPos + precision);
01293 break;
01294 default:
01295 break;
01296 }
01297
01298 decimalSymbolPos = str.indexOf('.');
01299 str.truncate(decimalSymbolPos + precision + 1);
01300
01301
01302 if (precision == 0) str = str.left(decimalSymbolPos);
01303
01304 str.squeeze();
01305 }
01306
01307 QString KLocale::formatNumber(const QString &numStr, bool round,
01308 int precision) const
01309 {
01310 QString tmpString = numStr;
01311 if (round && precision < 0)
01312 return numStr;
01313
01314
01315 const bool neg = (tmpString[0] == '-');
01316 if (neg || tmpString[0] == '+') tmpString.remove(0, 1);
01317
01318
01319
01320
01321 const int expPos = tmpString.indexOf('e');
01322 QString mantString = tmpString.left(expPos);
01323 QString expString;
01324 if (expPos > -1) {
01325 expString = tmpString.mid(expPos);
01326 if (expString.length() == 1)
01327 expString.clear();
01328 }
01329
01330
01331
01332 if (mantString.isEmpty() || !mantString[0].isDigit())
01333 mantString = "0";
01334
01335 if (round)
01336 _round(mantString, precision);
01337
01338
01339 mantString.replace(QChar('.'), decimalSymbol());
01340
01341
01342 _insertSeparator(mantString, thousandsSeparator(), decimalSymbol());
01343
01344
01345 mantString.prepend(neg?negativeSign():positiveSign());
01346
01347
01348 if (d->digitSet != KLocale::ArabicDigits) {
01349 mantString = convertDigits(mantString, d->digitSet);
01350 expString = convertDigits(expString, d->digitSet);
01351 }
01352
01353 return mantString + expString;
01354 }
01355
01356
01357
01358
01359
01360 QString KLocale::formatByteSize( double size ) const
01361 {
01362
01363
01364
01365
01366
01367
01368
01369
01370 if (d->byteSizeFmt.size() == 0) {
01371 QMutexLocker lock(kLocaleMutex());
01372
01373 #define CACHEBYTEFMT(x) { \
01374 QString s; \
01375 translateRaw(x, 0, &s); \
01376 d->byteSizeFmt.append(s); \
01377 } while(0)
01378
01379 CACHEBYTEFMT(I18N_NOOP("%1 TiB"));
01380
01381 CACHEBYTEFMT(I18N_NOOP("%1 GiB"));
01382
01383 CACHEBYTEFMT(I18N_NOOP("%1 MiB"));
01384
01385 CACHEBYTEFMT(I18N_NOOP("%1 KiB"));
01386
01387 CACHEBYTEFMT(I18N_NOOP("%1 B"));
01388 }
01389
01390 #define BYTEFMT(unit, n) (d->byteSizeFmt[KLocalePrivate::unit].arg(n))
01391 QString s;
01392 if (size >= 1073741824.0) {
01393 size /= 1073741824.0;
01394 if (size > 1024.0) {
01395 s = BYTEFMT(TiB, formatNumber(size / 1024.0, 1));
01396 } else {
01397 s = BYTEFMT(GiB, formatNumber(size, 1));
01398 }
01399 } else if (size >= 1048576.0) {
01400 size /= 1048576.0;
01401 s = BYTEFMT(MiB, formatNumber(size, 1));
01402 } else if (size >= 1024.0) {
01403 size /= 1024.0;
01404 s = BYTEFMT(KiB, formatNumber(size, 1));
01405 } else {
01406 s = BYTEFMT(B, formatNumber(size, 0));
01407 }
01408 return s;
01409 }
01410
01411 QString KLocale::formatDuration( unsigned long mSec) const
01412 {
01413 if( mSec >= 24*3600000) {
01414 return i18n( "%1 days", formatNumber( mSec/(24*3600000), 3));
01415 } else if(mSec >= 3600000)
01416 {
01417 return i18n( "%1 hours", formatNumber( mSec/3600000.0, 2));
01418 } else if(mSec >= 60000)
01419 {
01420 return i18n( "%1 minutes", formatNumber( mSec/60000.0, 2));
01421 } else if(mSec >= 1000)
01422 {
01423 return i18n( "%1 seconds", formatNumber( mSec/1000.0, 2));
01424 }
01425
01426 return i18n( "%1 milliseconds", formatNumber(mSec, 0));
01427 }
01428
01429 QString KLocalePrivate::formatSingleDuration( DurationType durationType, int n )
01430 {
01431 switch (durationType) {
01432 case DaysDurationType:
01433 return i18ncp("@item:intext", "1 day", "%1 days", n);
01434 case HoursDurationType:
01435 return i18ncp("@item:intext", "1 hour", "%1 hours", n);
01436 case MinutesDurationType:
01437 return i18ncp("@item:intext", "1 minute", "%1 minutes", n);
01438 case SecondsDurationType:
01439 return i18ncp("@item:intext", "1 second", "%1 seconds", n);
01440 }
01441 return QString();
01442 }
01443
01444 QString KLocale::prettyFormatDuration( unsigned long mSec ) const
01445 {
01446 unsigned long ms = mSec;
01447 int days = ms/(24*3600000);
01448 ms = ms%(24*3600000);
01449 int hours = ms/3600000;
01450 ms = ms%3600000;
01451 int minutes = ms/60000;
01452 ms = ms%60000;
01453 int seconds = qRound(ms/1000.0);
01454
01455
01456
01457 if (seconds == 60) {
01458 return prettyFormatDuration(mSec - ms + 60000);
01459 }
01460
01461 if (days && hours) {
01462 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", "%1 and %2", d->formatSingleDuration(KLocalePrivate::DaysDurationType, days), d->formatSingleDuration(KLocalePrivate::HoursDurationType, hours));
01463 } else if (days) {
01464 return d->formatSingleDuration(KLocalePrivate::DaysDurationType, days);
01465 } else if (hours && minutes) {
01466 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", "%1 and %2", d->formatSingleDuration(KLocalePrivate::HoursDurationType, hours), d->formatSingleDuration(KLocalePrivate::MinutesDurationType, minutes));
01467 } else if (hours) {
01468 return d->formatSingleDuration(KLocalePrivate::HoursDurationType, hours);
01469 } else if (minutes && seconds) {
01470 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", "%1 and %2", d->formatSingleDuration(KLocalePrivate::MinutesDurationType, minutes), d->formatSingleDuration(KLocalePrivate::SecondsDurationType, seconds));
01471 } else if (minutes) {
01472 return d->formatSingleDuration(KLocalePrivate::MinutesDurationType, minutes);
01473 } else {
01474 return d->formatSingleDuration(KLocalePrivate::SecondsDurationType, seconds);
01475 }
01476 }
01477
01478 QString KLocale::formatDate(const QDate &pDate, DateFormat format) const
01479 {
01480 if (format == FancyShortDate || format == FancyLongDate)
01481 {
01482 int days = pDate.daysTo(QDate::currentDate());
01483 if (days >= 0 && days < 7)
01484 return KLocalePrivate::fancyDate(this, pDate, days);
01485 format = (format == FancyShortDate) ? ShortDate : LongDate;
01486 }
01487 const QString rst = (format == ShortDate) ? dateFormatShort() : dateFormat();
01488
01489 QString buffer;
01490
01491 if ( ! pDate.isValid() ) return buffer;
01492
01493 bool escape = false;
01494
01495 int year = calendar()->year(pDate);
01496 int month = calendar()->month(pDate);
01497
01498 for ( int format_index = 0; format_index < rst.length(); ++format_index )
01499 {
01500 if ( !escape )
01501 {
01502 if ( rst.at( format_index ).unicode() == '%' )
01503 escape = true;
01504 else
01505 buffer.append(rst.at(format_index));
01506 }
01507 else
01508 {
01509 switch ( rst.at( format_index ).unicode() )
01510 {
01511 case '%':
01512 buffer.append(QLatin1Char('%'));
01513 break;
01514 case 'Y':
01515 buffer.append(calendar()->yearString(pDate, KCalendarSystem::LongFormat));
01516 break;
01517 case 'y':
01518 buffer.append(calendar()->yearString(pDate, KCalendarSystem::ShortFormat));
01519 break;
01520 case 'n':
01521 buffer.append(calendar()->monthString(pDate, KCalendarSystem::ShortFormat));
01522 break;
01523 case 'e':
01524 buffer.append(calendar()->dayString(pDate, KCalendarSystem::ShortFormat));
01525 break;
01526 case 'm':
01527 buffer.append(calendar()->monthString(pDate, KCalendarSystem::LongFormat));
01528 break;
01529 case 'b':
01530 if (d->dateMonthNamePossessive)
01531 buffer.append(calendar()->monthName(month, year, KCalendarSystem::ShortNamePossessive));
01532 else
01533 buffer.append(calendar()->monthName(month, year, KCalendarSystem::ShortName));
01534 break;
01535 case 'B':
01536 if (d->dateMonthNamePossessive)
01537 buffer.append(calendar()->monthName(month, year, KCalendarSystem::LongNamePossessive));
01538 else
01539 buffer.append(calendar()->monthName(month, year, KCalendarSystem::LongName));
01540 break;
01541 case 'd':
01542 buffer.append(calendar()->dayString(pDate, KCalendarSystem::LongFormat));
01543 break;
01544 case 'a':
01545 buffer.append(calendar()->weekDayName(pDate, KCalendarSystem::ShortDayName));
01546 break;
01547 case 'A':
01548 buffer.append(calendar()->weekDayName(pDate, KCalendarSystem::LongDayName));
01549 break;
01550 default:
01551 buffer.append(rst.at(format_index));
01552 break;
01553 }
01554 escape = false;
01555 }
01556 }
01557 buffer = convertDigits(buffer, d->dateTimeDigitSet);
01558 return buffer;
01559 }
01560
01561 QString KLocalePrivate::fancyDate(const KLocale *locale, const QDate &date, int days)
01562 {
01563 switch (days)
01564 {
01565 case 0:
01566 return i18n("Today");
01567 case 1:
01568 return i18n("Yesterday");
01569 default:
01570 return locale->calendar()->weekDayName(date);
01571 }
01572 }
01573
01574 void KLocale::setMainCatalog(const char *catalog)
01575 {
01576 KLocaleStaticData *s = staticData;
01577 s->maincatalog = QString::fromUtf8(catalog);
01578 }
01579
01580 double KLocale::readNumber(const QString &_str, bool * ok) const
01581 {
01582 QString str = _str.trimmed();
01583 bool neg = str.indexOf(negativeSign()) == 0;
01584 if (neg)
01585 str.remove( 0, negativeSign().length() );
01586
01587
01588
01589
01590 QString exponentialPart;
01591 int EPos;
01592
01593 EPos = str.indexOf('E', 0, Qt::CaseInsensitive);
01594
01595 if (EPos != -1)
01596 {
01597 exponentialPart = str.mid(EPos);
01598 str = str.left(EPos);
01599 }
01600
01601 int pos = str.indexOf(decimalSymbol());
01602 QString major;
01603 QString minor;
01604 if ( pos == -1 )
01605 major = str;
01606 else
01607 {
01608 major = str.left(pos);
01609 minor = str.mid(pos + decimalSymbol().length());
01610 }
01611
01612
01613 int thlen = thousandsSeparator().length();
01614 int lastpos = 0;
01615 while ( ( pos = major.indexOf( thousandsSeparator() ) ) > 0 )
01616 {
01617
01618 int fromEnd = major.length() - pos;
01619 if ( fromEnd % (3+thlen) != 0
01620 || pos - lastpos > 3
01621 || pos == 0
01622 || (lastpos>0 && pos-lastpos!=3))
01623 {
01624 if (ok) *ok = false;
01625 return 0.0;
01626 }
01627
01628 lastpos = pos;
01629 major.remove( pos, thlen );
01630 }
01631 if (lastpos>0 && major.length()-lastpos!=3)
01632 {
01633 if (ok) *ok = false;
01634 return 0.0;
01635 }
01636
01637 QString tot;
01638 if (neg) tot = '-';
01639
01640 tot += major + '.' + minor + exponentialPart;
01641
01642 tot = toArabicDigits(tot);
01643
01644 return tot.toDouble(ok);
01645 }
01646
01647 double KLocale::readMoney(const QString &_str, bool * ok) const
01648 {
01649 QString str = _str.trimmed();
01650 bool neg = false;
01651 bool currencyFound = false;
01652 QString symbol = currencySymbol();
01653
01654
01655 int pos = str.indexOf(symbol);
01656 if ( pos == 0 || pos == (int) str.length()-symbol.length() )
01657 {
01658 str.remove(pos,symbol.length());
01659 str = str.trimmed();
01660 currencyFound = true;
01661 }
01662 if (str.isEmpty())
01663 {
01664 if (ok) *ok = false;
01665 return 0;
01666 }
01667
01668
01669 if (negativeMonetarySignPosition() == ParensAround)
01670 {
01671 if (str[0] == '(' && str[str.length()-1] == ')')
01672 {
01673 neg = true;
01674 str.remove(str.length()-1,1);
01675 str.remove(0,1);
01676 }
01677 }
01678 else
01679 {
01680 int i1 = str.indexOf(negativeSign());
01681 if ( i1 == 0 || i1 == (int) str.length()-1 )
01682 {
01683 neg = true;
01684 str.remove(i1,negativeSign().length());
01685 }
01686 }
01687 if (neg) str = str.trimmed();
01688
01689
01690
01691 if ( !currencyFound )
01692 {
01693 pos = str.indexOf(symbol);
01694 if ( pos == 0 || pos == (int) str.length()-symbol.length() )
01695 {
01696 str.remove(pos,symbol.length());
01697 str = str.trimmed();
01698 }
01699 }
01700
01701
01702 pos = str.indexOf(monetaryDecimalSymbol());
01703 QString major;
01704 QString minior;
01705 if (pos == -1)
01706 major = str;
01707 else
01708 {
01709 major = str.left(pos);
01710 minior = str.mid(pos + monetaryDecimalSymbol().length());
01711 }
01712
01713
01714 int thlen = monetaryThousandsSeparator().length();
01715 int lastpos = 0;
01716 while ( ( pos = major.indexOf( monetaryThousandsSeparator() ) ) > 0 )
01717 {
01718
01719 int fromEnd = major.length() - pos;
01720 if ( fromEnd % (3+thlen) != 0
01721 || pos - lastpos > 3
01722 || pos == 0
01723 || (lastpos>0 && pos-lastpos!=3))
01724 {
01725 if (ok) *ok = false;
01726 return 0.0;
01727 }
01728 lastpos = pos;
01729 major.remove( pos, thlen );
01730 }
01731 if (lastpos>0 && major.length()-lastpos!=3)
01732 {
01733 if (ok) *ok = false;
01734 return 0.0;
01735 }
01736
01737 QString tot;
01738 if (neg) tot = '-';
01739 tot += major + '.' + minior;
01740 tot = toArabicDigits(tot);
01741 return tot.toDouble(ok);
01742 }
01743
01750 static int readInt(const QString &str, int &pos)
01751 {
01752 if (!str.at(pos).isDigit()) return -1;
01753 int result = 0;
01754 for (; str.length() > pos && str.at(pos).isDigit(); ++pos)
01755 {
01756 result *= 10;
01757 result += str.at(pos).digitValue();
01758 }
01759
01760 return result;
01761 }
01762
01763 QDate KLocale::readDate(const QString &intstr, bool* ok) const
01764 {
01765 QDate date;
01766 date = readDate(intstr, ShortFormat, ok);
01767 if (date.isValid()) return date;
01768 return readDate(intstr, NormalFormat, ok);
01769 }
01770
01771 QDate KLocale::readDate(const QString &intstr, ReadDateFlags flags, bool* ok) const
01772 {
01773 QString fmt = ((flags & ShortFormat) ? dateFormatShort() : dateFormat()).simplified();
01774 return readDate( intstr, fmt, ok );
01775 }
01776
01777 QDate KLocale::readDate(const QString &intstr, const QString &fmt, bool* ok) const
01778 {
01779
01780 QString str = intstr.simplified().toLower();
01781 int day = -1, month = -1;
01782
01783 int year = calendar()->year(QDate::currentDate());
01784 int strpos = 0;
01785 int fmtpos = 0;
01786
01787 int iLength;
01788
01789 bool error = false;
01790
01791 while (fmt.length() > fmtpos && str.length() > strpos && !error) {
01792
01793 QChar c = fmt.at(fmtpos++);
01794 if (c != '%') {
01795 if (c.isSpace() && str.at(strpos).isSpace())
01796 strpos++;
01797 else if (c != str.at(strpos++))
01798 error = true;
01799 } else {
01800 int j;
01801
01802 if (str.length() > strpos && str.at(strpos).isSpace())
01803 strpos++;
01804
01805 c = fmt.at(fmtpos++);
01806 switch (c.unicode())
01807 {
01808 case 'a':
01809 case 'A':
01810 error = true;
01811 j = 1;
01812 while (error && (j < 8)) {
01813 QString s;
01814 if ( c == 'a') {
01815 s = calendar()->weekDayName(j, KCalendarSystem::ShortDayName).toLower();
01816 } else {
01817 s = calendar()->weekDayName(j, KCalendarSystem::LongDayName).toLower();
01818 }
01819 int len = s.length();
01820 if (str.mid(strpos, len) == s)
01821 {
01822 strpos += len;
01823 error = false;
01824 }
01825 j++;
01826 }
01827 break;
01828 case 'b':
01829 case 'B':
01830 error = true;
01831 if (d->dateMonthNamePossessive) {
01832 j = 1;
01833 while (error && (j < 13)) {
01834 QString s;
01835 if ( c == 'b' ) {
01836 s = calendar()->monthName(j, year, KCalendarSystem::ShortNamePossessive).toLower();
01837 } else {
01838 s = calendar()->monthName(j, year, KCalendarSystem::LongNamePossessive).toLower();
01839 }
01840 int len = s.length();
01841 if (str.mid(strpos, len) == s) {
01842 month = j;
01843 strpos += len;
01844 error = false;
01845 }
01846 j++;
01847 }
01848 }
01849 j = 1;
01850 while (error && (j < 13)) {
01851 QString s;
01852 if ( c == 'b' ) {
01853 s = calendar()->monthName(j, year, KCalendarSystem::ShortName).toLower();
01854 } else {
01855 s = calendar()->monthName(j, year, KCalendarSystem::LongName).toLower();
01856 }
01857 int len = s.length();
01858 if (str.mid(strpos, len) == s) {
01859 month = j;
01860 strpos += len;
01861 error = false;
01862 }
01863 j++;
01864 }
01865 break;
01866 case 'd':
01867 case 'e':
01868 day = calendar()->dayStringToInteger(str.mid(strpos), iLength);
01869 strpos += iLength;
01870
01871 error = iLength <= 0;
01872 break;
01873
01874 case 'n':
01875 case 'm':
01876 month = calendar()->monthStringToInteger(str.mid(strpos), iLength);
01877 strpos += iLength;
01878
01879 error = iLength <= 0;
01880 break;
01881
01882 case 'Y':
01883 case 'y':
01884 year = calendar()->yearStringToInteger(str.mid(strpos), iLength);
01885 strpos += iLength;
01886 if (c == 'y' && year < 100)
01887 year += 2000;
01888
01889 error = iLength <= 0;
01890 break;
01891 }
01892 }
01893 }
01894
01895
01896
01897 if (fmt.length() > fmtpos || str.length() > strpos) {
01898 error = true;
01899 }
01900
01901
01902 if (year != -1 && month != -1 && day != -1 && !error) {
01903 if (ok) *ok = true;
01904
01905 QDate result;
01906 calendar()->setYMD(result, year, month, day);
01907
01908 return result;
01909 }
01910
01911 if (ok) *ok = false;
01912 return QDate();
01913 }
01914
01915 QTime KLocale::readTime(const QString &intstr, bool *ok) const
01916 {
01917 QTime _time;
01918 _time = readTime(intstr, WithSeconds, ok);
01919 if (_time.isValid()) return _time;
01920 return readTime(intstr, WithoutSeconds, ok);
01921 }
01922
01923 QTime KLocale::readTime(const QString &intstr, ReadTimeFlags flags, bool *ok) const
01924 {
01925 QString str = intstr.simplified().toLower();
01926 QString Format = timeFormat().simplified();
01927 if (flags & WithoutSeconds)
01928 Format.remove(QRegExp(".%S"));
01929
01930 int hour = -1, minute = -1;
01931 int second = ( (flags & WithoutSeconds) == 0 ) ? -1 : 0;
01932 bool g_12h = false;
01933 bool pm = false;
01934 int strpos = 0;
01935 int Formatpos = 0;
01936
01937 while (Format.length() > Formatpos || str.length() > strpos) {
01938 if ( !(Format.length() > Formatpos && str.length() > strpos) )
01939 goto error;
01940
01941 QChar c = Format.at(Formatpos++);
01942
01943 if (c != '%') {
01944 if (c.isSpace())
01945 strpos++;
01946 else if (c != str.at(strpos++))
01947 goto error;
01948 continue;
01949 }
01950
01951
01952 if (str.length() > strpos && str.at(strpos).isSpace())
01953 strpos++;
01954
01955 c = Format.at(Formatpos++);
01956 switch (c.unicode()) {
01957 case 'p':
01958 {
01959 QString s = i18n("pm").toLower();
01960 int len = s.length();
01961 if (str.mid(strpos, len) == s) {
01962 pm = true;
01963 strpos += len;
01964 } else {
01965 s = i18n("am").toLower();
01966 len = s.length();
01967 if (str.mid(strpos, len) == s) {
01968 pm = false;
01969 strpos += len;
01970 } else
01971 goto error;
01972 }
01973 }
01974 break;
01975
01976 case 'k':
01977 case 'H':
01978 g_12h = false;
01979 hour = readInt(str, strpos);
01980 if (hour < 0 || hour > 23)
01981 goto error;
01982
01983 break;
01984
01985 case 'l':
01986 case 'I':
01987 g_12h = true;
01988 hour = readInt(str, strpos);
01989 if (hour < 1 || hour > 12)
01990 goto error;
01991
01992 break;
01993
01994 case 'M':
01995 minute = readInt(str, strpos);
01996 if (minute < 0 || minute > 59)
01997 goto error;
01998
01999 break;
02000
02001 case 'S':
02002 second = readInt(str, strpos);
02003 if (second < 0 || second > 59)
02004 goto error;
02005
02006 break;
02007 }
02008 }
02009 if (g_12h) {
02010 hour %= 12;
02011 if (pm) hour += 12;
02012 }
02013
02014 if (ok) *ok = true;
02015 return QTime(hour, minute, second);
02016
02017 error:
02018 if (ok) *ok = false;
02019 return QTime();
02020 }
02021
02022 QString KLocale::formatTime(const QTime &pTime, bool includeSecs, bool isDuration) const
02023 {
02024 const QString rst = timeFormat();
02025
02026
02027
02028 QChar *buffer = new QChar[rst.length() * 3 / 2 + 30];
02029
02030 int index = 0;
02031 bool escape = false;
02032 int number = 0;
02033
02034 for ( int format_index = 0; format_index < rst.length(); format_index++ )
02035 {
02036 if ( !escape )
02037 {
02038 if ( rst.at( format_index ).unicode() == '%' )
02039 escape = true;
02040 else
02041 buffer[index++] = rst.at( format_index );
02042 }
02043 else
02044 {
02045 switch ( rst.at( format_index ).unicode() )
02046 {
02047 case '%':
02048 buffer[index++] = '%';
02049 break;
02050 case 'H':
02051 put_it_in( buffer, index, pTime.hour() );
02052 break;
02053 case 'I':
02054 if ( isDuration )
02055 put_it_in( buffer, index, pTime.hour() );
02056 else
02057 put_it_in( buffer, index, ( pTime.hour() + 11) % 12 + 1 );
02058 break;
02059 case 'M':
02060 put_it_in( buffer, index, pTime.minute() );
02061 break;
02062 case 'S':
02063 if (includeSecs)
02064 put_it_in( buffer, index, pTime.second() );
02065 else if (index > 0) {
02066
02067 while(index > 0 && buffer[index-1].isSpace())
02068 --index;
02069
02070
02071 --index;
02072
02073 while(index > 0 && buffer[index-1].isSpace())
02074 --index;
02075 break;
02076 }
02077 break;
02078 case 'k':
02079 number = pTime.hour();
02080 case 'l':
02081
02082 if ( rst.at( format_index ).unicode() == 'l' )
02083 number = isDuration ? pTime.hour() : (pTime.hour() + 11) % 12 + 1;
02084 if ( number / 10 )
02085 buffer[index++] = number / 10 + '0';
02086 buffer[index++] = number % 10 + '0';
02087 break;
02088 case 'p':
02089 if ( !isDuration )
02090 {
02091 QString s;
02092 if ( pTime.hour() >= 12 )
02093 put_it_in( buffer, index, i18n("pm") );
02094 else
02095 put_it_in( buffer, index, i18n("am") );
02096 }
02097 break;
02098 default:
02099 buffer[index++] = rst.at( format_index );
02100 break;
02101 }
02102 escape = false;
02103 }
02104 }
02105 QString ret( buffer, index );
02106 delete [] buffer;
02107 ret = convertDigits(ret, d->dateTimeDigitSet);
02108 if ( isDuration )
02109 return ret.trimmed();
02110 else
02111 return ret;
02112 }
02113
02114 bool KLocale::use12Clock() const
02115 {
02116 if ((timeFormat().contains(QString::fromLatin1("%I")) > 0) ||
02117 (timeFormat().contains(QString::fromLatin1("%l")) > 0))
02118 return true;
02119 else
02120 return false;
02121 }
02122
02123 QStringList KLocale::languageList() const
02124 {
02125 return d->languageList;
02126 }
02127
02128 QString KLocalePrivate::formatDateTime(const KLocale *locale, const QDateTime &dateTime,
02129 KLocale::DateFormat format, bool includeSeconds, int daysTo)
02130 {
02131 QString dateStr = (format == KLocale::FancyShortDate || format == KLocale::FancyLongDate)
02132 ? KLocalePrivate::fancyDate(locale, dateTime.date(), daysTo)
02133 : locale->formatDate(dateTime.date(), format);
02134 return i18nc("concatenation of dates and time", "%1 %2",
02135 dateStr, locale->formatTime(dateTime.time(), includeSeconds));
02136 }
02137
02138 QString KLocale::formatDateTime(const QDateTime &dateTime, DateFormat format,
02139 bool includeSeconds) const
02140 {
02141 QString dateStr;
02142 int days = -1;
02143 if (format == FancyShortDate || format == FancyLongDate)
02144 {
02145 QDateTime now = QDateTime::currentDateTime();
02146 days = dateTime.date().daysTo(now.date());
02147 if ((days == 0 && now.secsTo(dateTime) <= 3600)
02148 || (days > 0 && days < 7))
02149 ;
02150 else
02151 format = (format == FancyShortDate) ? ShortDate : LongDate;
02152 }
02153 return KLocalePrivate::formatDateTime(this, dateTime, format, includeSeconds, days);
02154 }
02155
02156 QString KLocale::formatDateTime(const KDateTime &dateTime, DateFormat format,
02157 DateTimeFormatOptions options) const
02158 {
02159 QString dt;
02160 if (dateTime.isDateOnly())
02161 dt = formatDate( dateTime.date(), format );
02162 else
02163 {
02164 int days = -1;
02165 if (format == FancyShortDate || format == FancyLongDate)
02166 {
02167
02168
02169 KDateTime now = KDateTime::currentDateTime(dateTime.timeSpec());
02170 days = dateTime.date().daysTo(now.date());
02171 if ((days == 0 && now.secsTo(dateTime) <= 3600)
02172 || (days > 0 && days < 7))
02173 ;
02174 else
02175 format = (format == FancyShortDate) ? ShortDate : LongDate;
02176 }
02177 dt = KLocalePrivate::formatDateTime(this, dateTime.dateTime(), format, (options & Seconds), days);
02178 }
02179 if (options & TimeZone)
02180 {
02181 QString tz;
02182 switch (dateTime.timeType())
02183 {
02184 case KDateTime::OffsetFromUTC:
02185 tz = i18n(dateTime.toString("%z").toUtf8());
02186 break;
02187 case KDateTime::UTC:
02188 case KDateTime::TimeZone:
02189 tz = i18n(dateTime.toString((format == ShortDate) ? "%Z" : "%:Z").toUtf8());
02190 break;
02191 case KDateTime::ClockTime:
02192 default:
02193 break;
02194 }
02195 return i18nc( "concatenation of date/time and time zone", "%1 %2", dt, tz );
02196 }
02197 else
02198 return dt;
02199 }
02200
02201 QString KLocale::langLookup(const QString &fname, const char *rtype)
02202 {
02203 QStringList search;
02204
02205
02206 const QStringList localDoc = KGlobal::dirs()->resourceDirs(rtype);
02207
02208
02209 for (int id=localDoc.count()-1; id >= 0; --id)
02210 {
02211 QStringList langs = KGlobal::locale()->languageList();
02212 langs.replaceInStrings("en_US", "en");
02213 langs.append("en");
02214 Q_FOREACH(const QString &lang, langs)
02215 search.append(QString("%1%2/%3").arg(localDoc[id]).arg(lang).arg(fname));
02216 }
02217
02218
02219 Q_FOREACH (const QString &file, search)
02220 {
02221 kDebug(173) << "Looking for help in: " << file;
02222
02223 QFileInfo info(file);
02224 if (info.exists() && info.isFile() && info.isReadable())
02225 return file;
02226 }
02227
02228 return QString();
02229 }
02230
02231 bool KLocalePrivate::useDefaultLanguage() const
02232 {
02233 return language == KLocale::defaultLanguage();
02234 }
02235
02236 void KLocalePrivate::initEncoding()
02237 {
02238 codecForEncoding = 0;
02239
02240
02241 #if defined(HAVE_LANGINFO_H) && !defined(Q_OS_WIN)
02242
02243
02244
02245
02246 QByteArray systemLocale = nl_langinfo(CODESET);
02247 #if defined(Q_OS_MAC)
02248
02249 systemLocale = "UTF-8";
02250 #endif
02251
02252 if (systemLocale == "ANSI_X3.4-1968")
02253 systemLocale = "ISO-8859-1";
02254
02255 QTextCodec* codec = QTextCodec::codecForName(systemLocale);
02256 if ( codec )
02257 setEncoding( codec->mibEnum() );
02258 #else
02259 setEncoding( QTextCodec::codecForLocale()->mibEnum() );
02260 #endif
02261
02262 if ( !codecForEncoding ) {
02263 kWarning() << "Cannot resolve system encoding, defaulting to ISO 8859-1.";
02264 const int mibDefault = 4;
02265 setEncoding(mibDefault);
02266 }
02267
02268 Q_ASSERT( codecForEncoding );
02269 }
02270
02271 void KLocalePrivate::initFileNameEncoding()
02272 {
02273
02274
02275 utf8FileEncoding = !qgetenv("KDE_UTF8_FILENAMES").isEmpty();
02276 if (utf8FileEncoding)
02277 {
02278 QFile::setEncodingFunction(KLocalePrivate::encodeFileNameUTF8);
02279 QFile::setDecodingFunction(KLocalePrivate::decodeFileNameUTF8);
02280 }
02281
02282
02283 }
02284
02285 QByteArray KLocalePrivate::encodeFileNameUTF8( const QString & fileName )
02286 {
02287 return fileName.toUtf8();
02288 }
02289
02290 QString KLocalePrivate::decodeFileNameUTF8( const QByteArray & localFileName )
02291 {
02292 return QString::fromUtf8(localFileName);
02293 }
02294
02295 void KLocale::setDateFormat(const QString & format)
02296 {
02297 d->dateFormat = format.trimmed();
02298 }
02299
02300 void KLocale::setDateFormatShort(const QString & format)
02301 {
02302 d->dateFormatShort = format.trimmed();
02303 }
02304
02305 void KLocale::setDateMonthNamePossessive(bool possessive)
02306 {
02307 d->dateMonthNamePossessive = possessive;
02308 }
02309
02310 void KLocale::setTimeFormat(const QString & format)
02311 {
02312 d->timeFormat = format.trimmed();
02313 }
02314
02315 void KLocale::setWeekStartDay(int day)
02316 {
02317 if (day >= 1 && day <= calendar()->daysInWeek(QDate()))
02318 d->weekStartDay = day;
02319 }
02320
02321 void KLocale::setWorkingWeekStartDay(int day)
02322 {
02323 if (day >= 1 && day <= calendar()->daysInWeek(QDate()))
02324 d->workingWeekStartDay = day;
02325 }
02326
02327 void KLocale::setWorkingWeekEndDay(int day)
02328 {
02329 if (day >= 1 && day <= calendar()->daysInWeek(QDate()))
02330 d->workingWeekEndDay = day;
02331 }
02332
02333 void KLocale::setWeekDayOfPray(int day)
02334 {
02335 if (day >= 0 && day <= calendar()->daysInWeek(QDate()))
02336 d->weekDayOfPray = day;
02337 }
02338
02339 QString KLocale::dateFormat() const
02340 {
02341 return d->dateFormat;
02342 }
02343
02344 QString KLocale::dateFormatShort() const
02345 {
02346 return d->dateFormatShort;
02347 }
02348
02349 QString KLocale::timeFormat() const
02350 {
02351 return d->timeFormat;
02352 }
02353
02354 void KLocale::setDecimalSymbol(const QString & symbol)
02355 {
02356 d->decimalSymbol = symbol.trimmed();
02357 }
02358
02359 void KLocale::setThousandsSeparator(const QString & separator)
02360 {
02361
02362 d->thousandsSeparator = separator;
02363 }
02364
02365 void KLocale::setPositiveSign(const QString & sign)
02366 {
02367 d->positiveSign = sign.trimmed();
02368 }
02369
02370 void KLocale::setNegativeSign(const QString & sign)
02371 {
02372 d->negativeSign = sign.trimmed();
02373 }
02374
02375 void KLocale::setPositiveMonetarySignPosition(SignPosition signpos)
02376 {
02377 d->positiveMonetarySignPosition = signpos;
02378 }
02379
02380 void KLocale::setNegativeMonetarySignPosition(SignPosition signpos)
02381 {
02382 d->negativeMonetarySignPosition = signpos;
02383 }
02384
02385 void KLocale::setPositivePrefixCurrencySymbol(bool prefix)
02386 {
02387 d->positivePrefixCurrencySymbol = prefix;
02388 }
02389
02390 void KLocale::setNegativePrefixCurrencySymbol(bool prefix)
02391 {
02392 d->negativePrefixCurrencySymbol = prefix;
02393 }
02394
02395 void KLocale::setFracDigits(int digits)
02396 {
02397 d->fracDigits = digits;
02398 }
02399
02400 void KLocale::setMonetaryThousandsSeparator(const QString & separator)
02401 {
02402
02403 d->monetaryThousandsSeparator = separator;
02404 }
02405
02406 void KLocale::setMonetaryDecimalSymbol(const QString & symbol)
02407 {
02408 d->monetaryDecimalSymbol = symbol.trimmed();
02409 }
02410
02411 void KLocale::setCurrencySymbol(const QString & symbol)
02412 {
02413 d->currencySymbol = symbol.trimmed();
02414 }
02415
02416 int KLocale::pageSize() const
02417 {
02418 return d->pageSize;
02419 }
02420
02421 void KLocale::setPageSize(int size)
02422 {
02423
02424 d->pageSize = size;
02425 }
02426
02427 KLocale::MeasureSystem KLocale::measureSystem() const
02428 {
02429 return d->measureSystem;
02430 }
02431
02432 void KLocale::setMeasureSystem(MeasureSystem value)
02433 {
02434 d->measureSystem = value;
02435 }
02436
02437 QString KLocale::defaultLanguage()
02438 {
02439 return QString::fromLatin1("en_US");
02440 }
02441
02442 QString KLocale::defaultCountry()
02443 {
02444 return QString::fromLatin1("C");
02445 }
02446
02447 bool KLocale::useTranscript() const
02448 {
02449 return d->useTranscript;
02450 }
02451
02452 const QByteArray KLocale::encoding() const
02453 {
02454 #ifdef Q_WS_WIN
02455 if (0==qstrcmp("System", codecForEncoding()->name()))
02456 {
02457
02458 strcpy(d->win32SystemEncoding, "cp ");
02459 if (GetLocaleInfoA( MAKELCID(MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), SORT_DEFAULT),
02460 LOCALE_IDEFAULTANSICODEPAGE, d->win32SystemEncoding+3, sizeof(d->win32SystemEncoding)-3-1 ))
02461 {
02462 return d->win32SystemEncoding;
02463 }
02464 }
02465 #endif
02466 return codecForEncoding()->name();
02467 }
02468
02469 int KLocale::encodingMib() const
02470 {
02471 return codecForEncoding()->mibEnum();
02472 }
02473
02474 int KLocale::fileEncodingMib() const
02475 {
02476 if (d->utf8FileEncoding)
02477 return 106;
02478 return codecForEncoding()->mibEnum();
02479 }
02480
02481 QTextCodec * KLocale::codecForEncoding() const
02482 {
02483 return d->codecForEncoding;
02484 }
02485
02486 bool KLocale::setEncoding(int mibEnum)
02487 {
02488 return d->setEncoding(mibEnum);
02489 }
02490
02491 bool KLocalePrivate::setEncoding(int mibEnum)
02492 {
02493 QTextCodec * codec = QTextCodec::codecForMib(mibEnum);
02494 if (codec)
02495 codecForEncoding = codec;
02496
02497 return codec != 0;
02498 }
02499
02500 QStringList KLocale::allLanguagesList() const
02501 {
02502 if (!d->languages)
02503 d->languages = new KConfig("all_languages", KConfig::NoGlobals, "locale");
02504
02505 return d->languages->groupList();
02506 }
02507
02508 QString KLocale::languageCodeToName(const QString &language) const
02509 {
02510 if (!d->languages)
02511 d->languages = new KConfig("all_languages", KConfig::NoGlobals, "locale");
02512
02513 KConfigGroup cg(d->languages, language);
02514 return cg.readEntry("Name");
02515 }
02516
02517 QStringList KLocale::allCountriesList() const
02518 {
02519 QStringList countries;
02520 const QStringList paths = KGlobal::dirs()->findAllResources("locale", "l10n/*/entry.desktop");
02521 for(QStringList::ConstIterator it = paths.begin();
02522 it != paths.end(); ++it)
02523 {
02524 QString code = (*it).mid((*it).length()-16, 2);
02525 if (code != "/C")
02526 countries.append(code);
02527 }
02528 return countries;
02529 }
02530
02531 QString KLocale::countryCodeToName(const QString &country) const
02532 {
02533 QString countryName;
02534 QString entryFile = KStandardDirs::locate("locale", "l10n/"+country.toLower()+"/entry.desktop");
02535 if (!entryFile.isEmpty()) {
02536 KConfig cfg(entryFile);
02537 KConfigGroup cg(&cfg, "KCM Locale");
02538 countryName = cg.readEntry("Name");
02539 }
02540 return countryName;
02541 }
02542
02543 void KLocale::setCalendar(const QString & calType)
02544 {
02545 d->calendarType = calType;
02546
02547 delete d->calendar;
02548 d->calendar = 0;
02549 }
02550
02551 QString KLocale::calendarType() const
02552 {
02553 return d->calendarType;
02554 }
02555
02556 const KCalendarSystem * KLocale::calendar() const
02557 {
02558
02559 if ( !d->calendar )
02560 d->calendar = KCalendarSystem::create( d->calendarType, this );
02561
02562 return d->calendar;
02563 }
02564
02565 KLocale::KLocale(const KLocale & rhs) : d(new KLocalePrivate(*rhs.d))
02566 {
02567 d->languages = 0;
02568 d->calendar = 0;
02569 }
02570
02571 KLocale & KLocale::operator=(const KLocale & rhs)
02572 {
02573
02574 *d = *rhs.d;
02575 d->languages = 0;
02576 d->calendar = 0;
02577
02578 return *this;
02579 }
02580
02581 void KLocale::copyCatalogsTo(KLocale *locale)
02582 {
02583 QMutexLocker lock(kLocaleMutex());
02584 locale->d->catalogNames = d->catalogNames;
02585 locale->d->updateCatalogs();
02586 }
02587
02588 QString KLocale::localizedFilePath(const QString &filePath) const
02589 {
02590
02591 if (d->useDefaultLanguage()) {
02592 return filePath;
02593 }
02594
02595
02596 QFileInfo fileInfo(filePath);
02597 QString locDirPath = fileInfo.path() + "/l10n";
02598 QFileInfo locDirInfo(locDirPath);
02599 if (!locDirInfo.isDir()) {
02600 return filePath;
02601 }
02602
02603
02604
02605 QString fileName = fileInfo.fileName();
02606 foreach (const QString &lang, d->languageList) {
02607
02608 if (lang == KLocale::defaultLanguage()) {
02609 return filePath;
02610 }
02611 QString locFilePath = locDirPath + '/' + lang + '/' + fileName;
02612 QFileInfo locFileInfo(locFilePath);
02613 if (locFileInfo.isFile() && locFileInfo.isReadable()) {
02614 return locFilePath;
02615 }
02616 }
02617
02618 return filePath;
02619 }
02620
02621 QString KLocale::removeAcceleratorMarker(const QString &label) const
02622 {
02623 return ::removeAcceleratorMarker(label);
02624 }
02625
02626 void KLocale::setDigitSet (DigitSet digitSet)
02627 {
02628 d->digitSet = digitSet;
02629 }
02630
02631 KLocale::DigitSet KLocale::digitSet () const
02632 {
02633 return d->digitSet;
02634 }
02635
02636 void KLocale::setMonetaryDigitSet (DigitSet digitSet)
02637 {
02638 d->monetaryDigitSet = digitSet;
02639 }
02640
02641 KLocale::DigitSet KLocale::monetaryDigitSet () const
02642 {
02643 return d->monetaryDigitSet;
02644 }
02645
02646 void KLocale::setDateTimeDigitSet (DigitSet digitSet)
02647 {
02648 d->dateTimeDigitSet = digitSet;
02649 }
02650
02651 KLocale::DigitSet KLocale::dateTimeDigitSet () const
02652 {
02653 return d->dateTimeDigitSet;
02654 }
02655
02656 Q_GLOBAL_STATIC_WITH_ARGS(QMutex, s_kLocaleMutex, (QMutex::Recursive))
02657 QMutex* kLocaleMutex()
02658 {
02659 return s_kLocaleMutex();
02660 }