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 <config.h>
00025
00026 #include <stdlib.h>
00027
00028 #include <qtextcodec.h>
00029 #include <qfile.h>
00030 #include <qprinter.h>
00031 #include <qdatetime.h>
00032 #include <qfileinfo.h>
00033 #include <qregexp.h>
00034
00035 #include "kcatalogue.h"
00036 #include "kglobal.h"
00037 #include "kstandarddirs.h"
00038 #include "ksimpleconfig.h"
00039 #include "kinstance.h"
00040 #include "kconfig.h"
00041 #include "kdebug.h"
00042 #include "kcalendarsystem.h"
00043 #include "kcalendarsystemfactory.h"
00044 #include "klocale.h"
00045
00046 static const char * const SYSTEM_MESSAGES = "kdelibs";
00047
00048 static const char *maincatalogue = 0;
00049
00050 class KLocalePrivate
00051 {
00052 public:
00053 int weekStartDay;
00054 int plural_form;
00055 bool nounDeclension;
00056 bool dateMonthNamePossessive;
00057 QStringList languageList;
00058 QValueList<KCatalogue> catalogues;
00059 QString encoding;
00060 QTextCodec * codecForEncoding;
00061 KConfig * config;
00062 bool formatInited;
00063 int pageSize;
00064 KLocale::MeasureSystem measureSystem;
00065 QStringList langTwoAlpha;
00066 KConfig *languages;
00067
00068 QString calendarType;
00069 KCalendarSystem * calendar;
00070 QString first_language;
00071 bool utf8FileEncoding;
00072 };
00073
00074 static KLocale *this_klocale = 0;
00075
00076 KLocale::KLocale( const QString & catalog, KConfig * config )
00077 {
00078 d = new KLocalePrivate;
00079 d->config = config;
00080 d->languages = 0;
00081 d->calendar = 0;
00082
00083 initCatalogue(catalog);
00084 initEncoding(0);
00085 initFileNameEncoding(0);
00086
00087 KConfig *cfg = d->config;
00088 this_klocale = this;
00089 if (!cfg) cfg = KGlobal::instance()->config();
00090 this_klocale = 0;
00091 Q_ASSERT( cfg );
00092
00093 if (m_language.isEmpty())
00094 initLanguage(cfg, config == 0);
00095 }
00096
00097 QString KLocale::_initLanguage(KConfigBase *config)
00098 {
00099 if (this_klocale)
00100 {
00101
00102 this_klocale->initLanguage((KConfig *) config, true);
00103 return this_klocale->language();
00104 }
00105 return QString::null;
00106 }
00107
00108 void KLocale::initCatalogue(const QString & catalog)
00109 {
00110
00111 QString mainCatalogue = catalog;
00112 if (maincatalogue)
00113 mainCatalogue = QString::fromLatin1(maincatalogue);
00114
00115 if (mainCatalogue.isEmpty()) {
00116 kdDebug(173) << "KLocale instance created called without valid "
00117 << "catalog! Give an argument or call setMainCatalogue "
00118 << "before init" << endl;
00119 }
00120 else
00121 d->catalogues.append( KCatalogue(mainCatalogue ) );
00122
00123
00124 d->catalogues.append( KCatalogue( SYSTEM_MESSAGES ) );
00125 d->catalogues.append( KCatalogue( "kio" ) );
00126 }
00127
00128 void KLocale::initLanguage(KConfig * config, bool useEnv)
00129 {
00130 KConfigGroupSaver saver(config, "Locale");
00131
00132 m_country = config->readEntry( "Country" );
00133 if ( m_country.isEmpty() )
00134 m_country = defaultCountry();
00135
00136
00137 QStringList languageList;
00138 if ( useEnv )
00139 {
00140
00141 QStringList langs;
00142
00143 langs << QFile::decodeName( ::getenv("LC_ALL") );
00144 langs << QFile::decodeName( ::getenv("LC_MESSAGES") );
00145 langs << QFile::decodeName( ::getenv("LANG") );
00146 langs << QFile::decodeName( ::getenv("LC_CTYPE") );
00147
00148 for ( QStringList::Iterator it = langs.begin();
00149 it != langs.end();
00150 ++it )
00151 {
00152 QString ln, ct, chrset;
00153 splitLocale(*it, ln, ct, chrset);
00154
00155 if (!ct.isEmpty()) {
00156 if (!chrset.isEmpty())
00157 langs.insert(it, ln + '_' + ct + '.' + chrset);
00158 langs.insert(it, ln + '_' + ct);
00159 }
00160
00161 langs.insert(it, ln);
00162 }
00163
00164 languageList += langs;
00165 }
00166
00167
00168 if ( useEnv )
00169 languageList += QStringList::split
00170 (':', QFile::decodeName( ::getenv("KDE_LANG") ));
00171
00172 languageList += config->readListEntry("Language", ':');
00173
00174
00175 setLanguage( languageList );
00176 }
00177
00178 void KLocale::doBindInit()
00179 {
00180 for ( QValueList<KCatalogue>::Iterator it = d->catalogues.begin();
00181 it != d->catalogues.end();
00182 ++it )
00183 initCatalogue( *it );
00184
00185 if ( useDefaultLanguage() )
00186 d->plural_form = -1;
00187 else
00188 {
00189 QString pf = translate_priv
00190 ( I18N_NOOP("_: Dear translator, please do not translate this string "
00191 "in any form, but pick the _right_ value out of "
00192 "NoPlural/TwoForms/French... If not sure what to do mail "
00193 "thd@kde.org and coolo@kde.org, they will tell you. "
00194 "Better leave that out if unsure, the programs will "
00195 "crash!!\nDefinition of PluralForm - to be set by the "
00196 "translator of kdelibs.po"), 0);
00197 if ( pf.isEmpty() ) {
00198 kdWarning(173) << "found no definition of PluralForm for " << m_language << endl;
00199 d->plural_form = -1;
00200 } else if ( pf == "NoPlural" )
00201 d->plural_form = 0;
00202 else if ( pf == "TwoForms" )
00203 d->plural_form = 1;
00204 else if ( pf == "French" )
00205 d->plural_form = 2;
00206 else if ( pf == "OneTwoRest" || pf == "Gaeilge" )
00207 d->plural_form = 3;
00208 else if ( pf == "Russian" )
00209 d->plural_form = 4;
00210 else if ( pf == "Polish" )
00211 d->plural_form = 5;
00212 else if ( pf == "Slovenian" )
00213 d->plural_form = 6;
00214 else if ( pf == "Lithuanian" )
00215 d->plural_form = 7;
00216 else if ( pf == "Czech" )
00217 d->plural_form = 8;
00218 else if ( pf == "Slovak" )
00219 d->plural_form = 9;
00220 else if ( pf == "Maltese" )
00221 d->plural_form = 10;
00222 else if ( pf == "Arabic" )
00223 d->plural_form = 11;
00224 else if ( pf == "Balcan" )
00225 d->plural_form = 12;
00226 else if ( pf == "Macedonian" )
00227 d->plural_form = 13;
00228 else {
00229 kdWarning(173) << "Definition of PluralForm is none of "
00230 << "NoPlural/"
00231 << "TwoForms/"
00232 << "French/"
00233 << "OneTwoRest/"
00234 << "Russian/"
00235 << "Polish/"
00236 << "Slovenian/"
00237 << "Lithuanian/"
00238 << "Czech/"
00239 << "Slovak/"
00240 << "Arabic/"
00241 << "Balcan/"
00242 << "Macedonian/"
00243 << "Maltese: " << pf << endl;
00244 exit(1);
00245 }
00246 }
00247
00248 d->formatInited = false;
00249 }
00250
00251 void KLocale::doFormatInit() const
00252 {
00253 if ( d->formatInited ) return;
00254
00255 KLocale * that = const_cast<KLocale *>(this);
00256 that->initFormat();
00257
00258 d->formatInited = true;
00259 }
00260
00261 void KLocale::initFormat()
00262 {
00263 KConfig *config = d->config;
00264 if (!config) config = KGlobal::instance()->config();
00265 Q_ASSERT( config );
00266
00267 kdDebug(173) << "KLocale::initFormat" << endl;
00268
00269
00270
00271
00272 KLocale *lsave = KGlobal::_locale;
00273 KGlobal::_locale = this;
00274
00275 KConfigGroupSaver saver(config, "Locale");
00276
00277 KSimpleConfig entry(locate("locale",
00278 QString::fromLatin1("l10n/%1/entry.desktop")
00279 .arg(m_country)), true);
00280 entry.setGroup("KCM Locale");
00281
00282
00283 #define readConfigEntry(key, default, save) \
00284 save = entry.readEntry(key, QString::fromLatin1(default)); \
00285 save = config->readEntry(key, save);
00286
00287 #define readConfigNumEntry(key, default, save, type) \
00288 save = (type)entry.readNumEntry(key, default); \
00289 save = (type)config->readNumEntry(key, save);
00290
00291 #define readConfigBoolEntry(key, default, save) \
00292 save = entry.readBoolEntry(key, default); \
00293 save = config->readBoolEntry(key, save);
00294
00295 readConfigEntry("DecimalSymbol", ".", m_decimalSymbol);
00296 readConfigEntry("ThousandsSeparator", ",", m_thousandsSeparator);
00297 m_thousandsSeparator.replace( QString::fromLatin1("$0"), QString::null );
00298
00299
00300 readConfigEntry("PositiveSign", "", m_positiveSign);
00301 readConfigEntry("NegativeSign", "-", m_negativeSign);
00302
00303
00304 readConfigEntry("CurrencySymbol", "$", m_currencySymbol);
00305 readConfigEntry("MonetaryDecimalSymbol", ".", m_monetaryDecimalSymbol);
00306 readConfigEntry("MonetaryThousandsSeparator", ",",
00307 m_monetaryThousandsSeparator);
00308 m_monetaryThousandsSeparator.replace(QString::fromLatin1("$0"), QString::null);
00309
00310 readConfigNumEntry("FracDigits", 2, m_fracDigits, int);
00311 readConfigBoolEntry("PositivePrefixCurrencySymbol", true,
00312 m_positivePrefixCurrencySymbol);
00313 readConfigBoolEntry("NegativePrefixCurrencySymbol", true,
00314 m_negativePrefixCurrencySymbol);
00315 readConfigNumEntry("PositiveMonetarySignPosition", (int)BeforeQuantityMoney,
00316 m_positiveMonetarySignPosition, SignPosition);
00317 readConfigNumEntry("NegativeMonetarySignPosition", (int)ParensAround,
00318 m_negativeMonetarySignPosition, SignPosition);
00319
00320
00321 readConfigBoolEntry("NounDeclension", false, d->nounDeclension);
00322
00323
00324 readConfigEntry("TimeFormat", "%H:%M:%S", m_timeFormat);
00325 readConfigEntry("DateFormat", "%A %d %B %Y", m_dateFormat);
00326 readConfigEntry("DateFormatShort", "%Y-%m-%d", m_dateFormatShort);
00327 readConfigBoolEntry("DateMonthNamePossessive", false,
00328 d->dateMonthNamePossessive);
00329 readConfigNumEntry("WeekStartDay", 1, d->weekStartDay, int);
00330
00331
00332 readConfigNumEntry("PageSize", (int)QPrinter::A4, d->pageSize, int);
00333 readConfigNumEntry("MeasureSystem", (int)Metric, d->measureSystem,
00334 MeasureSystem);
00335 readConfigEntry("CalendarSystem", "gregorian", d->calendarType);
00336 delete d->calendar;
00337 d->calendar = 0;
00338
00339
00340 KGlobal::_locale = lsave;
00341 }
00342
00343 bool KLocale::setCountry(const QString & country)
00344 {
00345
00346 if ( country.isEmpty() )
00347 return false;
00348
00349 m_country = country;
00350
00351 d->formatInited = false;
00352
00353 return true;
00354 }
00355
00356 QString KLocale::catalogueFileName(const QString & language,
00357 const KCatalogue & catalog)
00358 {
00359 QString path = QString::fromLatin1("%1/LC_MESSAGES/%2.mo")
00360 .arg( language )
00361 .arg( catalog.name() );
00362
00363 return locate( "locale", path );
00364 }
00365
00366 bool KLocale::isLanguageInstalled(const QString & language) const
00367 {
00368
00369 if ( language.isEmpty() ) return false;
00370
00371 bool bRes = true;
00372 if ( language != defaultLanguage() )
00373 for ( QValueList<KCatalogue>::ConstIterator it = d->catalogues.begin();
00374 it != d->catalogues.end() && bRes;
00375 ++it )
00376 {
00377 bRes = !catalogueFileName( language, *it ).isNull();
00378 if ( !bRes )
00379 kdDebug(173) << "message catalog not found: "
00380 << (*it).name() << endl;
00381 }
00382
00383 return bRes;
00384 }
00385
00386 bool KLocale::setLanguage(const QString & language)
00387 {
00388 bool bRes = true;
00389
00390 if (d->first_language.isNull() || language != d->first_language)
00391 bRes = isLanguageInstalled( language );
00392
00393 if ( bRes )
00394 {
00395 m_language = language;
00396
00397
00398 if (d->first_language.isNull())
00399 d->first_language = language;
00400
00401 doBindInit();
00402 }
00403
00404 return bRes;
00405 }
00406
00407 bool KLocale::setLanguage(const QStringList & languages)
00408 {
00409 QStringList languageList(languages);
00410
00411
00412
00413 for( QStringList::Iterator it = languageList.fromLast();
00414 it != languageList.begin();
00415 --it )
00416 if ( languageList.contains(*it) > 1 || (*it).isEmpty() )
00417 it = languageList.remove( it );
00418
00419 bool bRes = false;
00420 for ( QStringList::ConstIterator it = languageList.begin();
00421 it != languageList.end();
00422 ++it )
00423 if ( bRes = setLanguage( *it ) )
00424 break;
00425
00426 if ( !bRes )
00427 setLanguage(defaultLanguage());
00428
00429 d->languageList = languageList;
00430 d->langTwoAlpha.clear();
00431
00432 return bRes;
00433 }
00434
00435 void KLocale::splitLocale(const QString & aStr,
00436 QString & language,
00437 QString & country,
00438 QString & chrset)
00439 {
00440 QString str = aStr;
00441
00442
00443 int f = str.find(':');
00444 if (f >= 0)
00445 str.truncate(f);
00446
00447 country = QString::null;
00448 chrset = QString::null;
00449 language = QString::null;
00450
00451 f = str.find('.');
00452 if (f >= 0)
00453 {
00454 chrset = str.mid(f + 1);
00455 str.truncate(f);
00456 }
00457
00458 f = str.find('_');
00459 if (f >= 0)
00460 {
00461 country = str.mid(f + 1);
00462 str.truncate(f);
00463 }
00464
00465 language = str;
00466 }
00467
00468 QString KLocale::language() const
00469 {
00470 return m_language;
00471 }
00472
00473 QString KLocale::country() const
00474 {
00475 return m_country;
00476 }
00477
00478 QString KLocale::monthName(int i, bool shortName) const
00479 {
00480 if ( shortName )
00481 switch ( i )
00482 {
00483 case 1: return translate("January", "Jan");
00484 case 2: return translate("February", "Feb");
00485 case 3: return translate("March", "Mar");
00486 case 4: return translate("April", "Apr");
00487 case 5: return translate("May short", "May");
00488 case 6: return translate("June", "Jun");
00489 case 7: return translate("July", "Jul");
00490 case 8: return translate("August", "Aug");
00491 case 9: return translate("September", "Sep");
00492 case 10: return translate("October", "Oct");
00493 case 11: return translate("November", "Nov");
00494 case 12: return translate("December", "Dec");
00495 }
00496 else
00497 switch (i)
00498 {
00499 case 1: return translate("January");
00500 case 2: return translate("February");
00501 case 3: return translate("March");
00502 case 4: return translate("April");
00503 case 5: return translate("May long", "May");
00504 case 6: return translate("June");
00505 case 7: return translate("July");
00506 case 8: return translate("August");
00507 case 9: return translate("September");
00508 case 10: return translate("October");
00509 case 11: return translate("November");
00510 case 12: return translate("December");
00511 }
00512
00513 return QString::null;
00514 }
00515
00516 QString KLocale::monthNamePossessive(int i, bool shortName) const
00517 {
00518 if ( shortName )
00519 switch ( i )
00520 {
00521 case 1: return translate("of January", "of Jan");
00522 case 2: return translate("of February", "of Feb");
00523 case 3: return translate("of March", "of Mar");
00524 case 4: return translate("of April", "of Apr");
00525 case 5: return translate("of May short", "of May");
00526 case 6: return translate("of June", "of Jun");
00527 case 7: return translate("of July", "of Jul");
00528 case 8: return translate("of August", "of Aug");
00529 case 9: return translate("of September", "of Sep");
00530 case 10: return translate("of October", "of Oct");
00531 case 11: return translate("of November", "of Nov");
00532 case 12: return translate("of December", "of Dec");
00533 }
00534 else
00535 switch (i)
00536 {
00537 case 1: return translate("of January");
00538 case 2: return translate("of February");
00539 case 3: return translate("of March");
00540 case 4: return translate("of April");
00541 case 5: return translate("of May long", "of May");
00542 case 6: return translate("of June");
00543 case 7: return translate("of July");
00544 case 8: return translate("of August");
00545 case 9: return translate("of September");
00546 case 10: return translate("of October");
00547 case 11: return translate("of November");
00548 case 12: return translate("of December");
00549 }
00550
00551 return QString::null;
00552 }
00553
00554 QString KLocale::weekDayName (int i, bool shortName) const
00555 {
00556 if ( shortName )
00557 switch ( i )
00558 {
00559 case 1: return translate("Monday", "Mon");
00560 case 2: return translate("Tuesday", "Tue");
00561 case 3: return translate("Wednesday", "Wed");
00562 case 4: return translate("Thursday", "Thu");
00563 case 5: return translate("Friday", "Fri");
00564 case 6: return translate("Saturday", "Sat");
00565 case 7: return translate("Sunday", "Sun");
00566 }
00567 else
00568 switch ( i )
00569 {
00570 case 1: return translate("Monday");
00571 case 2: return translate("Tuesday");
00572 case 3: return translate("Wednesday");
00573 case 4: return translate("Thursday");
00574 case 5: return translate("Friday");
00575 case 6: return translate("Saturday");
00576 case 7: return translate("Sunday");
00577 }
00578
00579 return QString::null;
00580 }
00581
00582 void KLocale::insertCatalogue( const QString & catalog )
00583 {
00584 KCatalogue cat( catalog );
00585
00586 initCatalogue( cat );
00587
00588 d->catalogues.append( cat );
00589 }
00590
00591 void KLocale::removeCatalogue(const QString &catalog)
00592 {
00593 for ( QValueList<KCatalogue>::Iterator it = d->catalogues.begin();
00594 it != d->catalogues.end(); )
00595 if ((*it).name() == catalog) {
00596 it = d->catalogues.remove(it);
00597 return;
00598 } else
00599 ++it;
00600 }
00601
00602 void KLocale::setActiveCatalogue(const QString &catalog)
00603 {
00604 for ( QValueList<KCatalogue>::Iterator it = d->catalogues.begin();
00605 it != d->catalogues.end(); ++it)
00606 if ((*it).name() == catalog) {
00607 KCatalogue save = *it;
00608 d->catalogues.remove(it);
00609 d->catalogues.prepend(save);
00610 return;
00611 }
00612 }
00613
00614 KLocale::~KLocale()
00615 {
00616 delete d->calendar;
00617 delete d->languages;
00618 delete d;
00619 d = 0L;
00620 }
00621
00622 QString KLocale::translate_priv(const char *msgid,
00623 const char *fallback,
00624 const char **translated) const
00625 {
00626 if (!msgid || !msgid[0])
00627 {
00628 kdWarning() << "KLocale: trying to look up \"\" in catalog. "
00629 << "Fix the program" << endl;
00630 return QString::null;
00631 }
00632
00633 if ( useDefaultLanguage() )
00634 return QString::fromUtf8( fallback );
00635
00636 for ( QValueList<KCatalogue>::ConstIterator it = d->catalogues.begin();
00637 it != d->catalogues.end();
00638 ++it )
00639 {
00640
00641 const char * text = (*it).translate( msgid );
00642
00643 if ( text )
00644 {
00645
00646 if (translated)
00647 *translated = text;
00648 return QString::fromUtf8( text );
00649 }
00650 }
00651
00652
00653 return QString::fromUtf8( fallback );
00654 }
00655
00656 QString KLocale::translate(const char* msgid) const
00657 {
00658 return translate_priv(msgid, msgid);
00659 }
00660
00661 QString KLocale::translate( const char *index, const char *fallback) const
00662 {
00663 if (!index || !index[0] || !fallback || !fallback[0])
00664 {
00665 kdDebug(173) << "KLocale: trying to look up \"\" in catalog. "
00666 << "Fix the program" << endl;
00667 return QString::null;
00668 }
00669
00670 if ( useDefaultLanguage() )
00671 return QString::fromUtf8( fallback );
00672
00673 char *newstring = new char[strlen(index) + strlen(fallback) + 5];
00674 sprintf(newstring, "_: %s\n%s", index, fallback);
00675
00676 QString r = translate_priv(newstring, fallback);
00677 delete [] newstring;
00678
00679 return r;
00680 }
00681
00682 static QString put_n_in(const QString &orig, unsigned long n)
00683 {
00684 QString ret = orig;
00685 int index = ret.find("%n");
00686 if (index == -1)
00687 return ret;
00688 ret.replace(index, 2, QString::number(n));
00689 return ret;
00690 }
00691
00692 #define EXPECT_LENGTH(x) \
00693 if (forms.count() != x) { \
00694 kdError() << "translation of \"" << singular << "\" doesn't contain " << x << " different plural forms as expected\n"; \
00695 return QString( "BROKEN TRANSLATION %1" ).arg( singular ); }
00696
00697 QString KLocale::translate( const char *singular, const char *plural,
00698 unsigned long n ) const
00699 {
00700 if (!singular || !singular[0] || !plural || !plural[0])
00701 {
00702 kdWarning() << "KLocale: trying to look up \"\" in catalog. "
00703 << "Fix the program" << endl;
00704 return QString::null;
00705 }
00706
00707 char *newstring = new char[strlen(singular) + strlen(plural) + 6];
00708 sprintf(newstring, "_n: %s\n%s", singular, plural);
00709
00710 QString r = translate_priv(newstring, 0);
00711 delete [] newstring;
00712
00713 if ( r.isEmpty() || useDefaultLanguage() || d->plural_form == -1) {
00714 if ( n == 1 ) {
00715 return put_n_in( QString::fromUtf8( singular ), n );
00716 } else {
00717 QString tmp = QString::fromUtf8( plural );
00718 #ifndef NDEBUG
00719 if (tmp.find("%n") == -1) {
00720 kdWarning() << "the message for i18n should contain a '%n'! " << plural << endl;
00721 }
00722 #endif
00723 return put_n_in( tmp, n );
00724 }
00725 }
00726
00727 QStringList forms = QStringList::split( "\n", r, false );
00728 switch ( d->plural_form ) {
00729 case 0:
00730 EXPECT_LENGTH( 1 );
00731 return put_n_in( forms[0], n);
00732 case 1:
00733 EXPECT_LENGTH( 2 );
00734 if ( n == 1 )
00735 return put_n_in( forms[0], n);
00736 else
00737 return put_n_in( forms[1], n);
00738 case 2:
00739 EXPECT_LENGTH( 2 );
00740 if ( n == 1 || n == 0 )
00741 return put_n_in( forms[0], n);
00742 else
00743 return put_n_in( forms[1], n);
00744 case 3:
00745 EXPECT_LENGTH( 3 );
00746 if ( n == 1 )
00747 return put_n_in( forms[0], n);
00748 else if ( n == 2 )
00749 return put_n_in( forms[1], n);
00750 else
00751 return put_n_in( forms[2], n);
00752 case 4:
00753 EXPECT_LENGTH( 3 );
00754 if ( n%10 == 1 && n%100 != 11)
00755 return put_n_in( forms[0], n);
00756 else if (( n%10 >= 2 && n%10 <=4 ) && (n%100<10 || n%100>20))
00757 return put_n_in( forms[1], n);
00758 else
00759 return put_n_in( forms[2], n);
00760 case 5:
00761 EXPECT_LENGTH( 3 );
00762 if ( n == 1 )
00763 return put_n_in( forms[0], n);
00764 else if ( n%10 >= 2 && n%10 <=4 && (n%100<10 || n%100>=20) )
00765 return put_n_in( forms[1], n);
00766 else
00767 return put_n_in( forms[2], n);
00768 case 6:
00769 EXPECT_LENGTH( 4 );
00770 if ( n%100 == 1 )
00771 return put_n_in( forms[1], n);
00772 else if ( n%100 == 2 )
00773 return put_n_in( forms[2], n);
00774 else if ( n%100 == 3 || n%100 == 4 )
00775 return put_n_in( forms[3], n);
00776 else
00777 return put_n_in( forms[0], n);
00778 case 7:
00779 EXPECT_LENGTH( 3 );
00780 if ( n%10 == 0 || (n%100>=11 && n%100<=19) )
00781 return put_n_in( forms[2], n);
00782 else if ( n%10 == 1 )
00783 return put_n_in( forms[0], n);
00784 else
00785 return put_n_in( forms[1], n);
00786 case 8:
00787 EXPECT_LENGTH( 3 );
00788 if ( n%100 == 1 )
00789 return put_n_in( forms[0], n);
00790 else if (( n%100 >= 2 ) && ( n%100 <= 4 ))
00791 return put_n_in( forms[1], n);
00792 else
00793 return put_n_in( forms[2], n);
00794 case 9:
00795 EXPECT_LENGTH( 3 );
00796 if ( n == 1 )
00797 return put_n_in( forms[0], n);
00798 else if (( n >= 2 ) && ( n <= 4 ))
00799 return put_n_in( forms[1], n);
00800 else
00801 return put_n_in( forms[2], n);
00802 case 10:
00803 EXPECT_LENGTH( 4 );
00804 if ( n == 1 )
00805 return put_n_in( forms[0], n );
00806 else if ( ( n == 0 ) || ( n%100 > 0 && n%100 <= 10 ) )
00807 return put_n_in( forms[1], n );
00808 else if ( n%100 > 10 && n%100 < 20 )
00809 return put_n_in( forms[2], n );
00810 else
00811 return put_n_in( forms[3], n );
00812 case 11:
00813 EXPECT_LENGTH( 4 );
00814 if (n == 1)
00815 return put_n_in(forms[0], n);
00816 else if (n == 2)
00817 return put_n_in(forms[1], n);
00818 else if ( n < 11)
00819 return put_n_in(forms[2], n);
00820 else
00821 return put_n_in(forms[3], n);
00822 case 12:
00823 EXPECT_LENGTH( 3 );
00824 if (n != 11 && n % 10 == 1)
00825 return put_n_in(forms[0], n);
00826 else if (n / 10 != 1 && n % 10 >= 2 && n % 10 <= 4)
00827 return put_n_in(forms[1], n);
00828 else
00829 return put_n_in(forms[2], n);
00830 case 13:
00831 EXPECT_LENGTH(3);
00832 if (n % 10 == 1)
00833 return put_n_in(forms[0], n);
00834 else if (n % 10 == 2)
00835 return put_n_in(forms[1], n);
00836 else
00837 return put_n_in(forms[2], n);
00838 }
00839 kdFatal() << "The function should have been returned in another way\n";
00840
00841 return QString::null;
00842 }
00843
00844 QString KLocale::translateQt( const char *context, const char *source,
00845 const char *message) const
00846 {
00847 if (!source || !source[0]) {
00848 kdWarning() << "KLocale: trying to look up \"\" in catalog. "
00849 << "Fix the program" << endl;
00850 return QString::null;
00851 }
00852
00853 if ( useDefaultLanguage() ) {
00854 return QString::null;
00855 }
00856
00857 char *newstring = 0;
00858 const char *translation = 0;
00859 QString r;
00860
00861 if ( message && message[0]) {
00862 char *newstring = new char[strlen(source) + strlen(message) + 5];
00863 sprintf(newstring, "_: %s\n%s", source, message);
00864 const char *translation = 0;
00865
00866 r = translate_priv(newstring, source, &translation);
00867 delete [] newstring;
00868 if (translation)
00869 return r;
00870 }
00871
00872 if ( context && context[0] && message && message[0]) {
00873 newstring = new char[strlen(context) + strlen(message) + 5];
00874 sprintf(newstring, "_: %s\n%s", context, message);
00875
00876 r = translate_priv(newstring, source, &translation);
00877 delete [] newstring;
00878 if (translation)
00879 return r;
00880 }
00881
00882 r = translate_priv(source, source, &translation);
00883 if (translation)
00884 return r;
00885 return QString::null;
00886 }
00887
00888 bool KLocale::nounDeclension() const
00889 {
00890 doFormatInit();
00891 return d->nounDeclension;
00892 }
00893
00894 bool KLocale::dateMonthNamePossessive() const
00895 {
00896 doFormatInit();
00897 return d->dateMonthNamePossessive;
00898 }
00899
00900 int KLocale::weekStartDay() const
00901 {
00902 doFormatInit();
00903 return d->weekStartDay;
00904 }
00905
00906 bool KLocale::weekStartsMonday() const
00907 {
00908 doFormatInit();
00909 return (d->weekStartDay==1);
00910 }
00911
00912 QString KLocale::decimalSymbol() const
00913 {
00914 doFormatInit();
00915 return m_decimalSymbol;
00916 }
00917
00918 QString KLocale::thousandsSeparator() const
00919 {
00920 doFormatInit();
00921 return m_thousandsSeparator;
00922 }
00923
00924 QString KLocale::currencySymbol() const
00925 {
00926 doFormatInit();
00927 return m_currencySymbol;
00928 }
00929
00930 QString KLocale::monetaryDecimalSymbol() const
00931 {
00932 doFormatInit();
00933 return m_monetaryDecimalSymbol;
00934 }
00935
00936 QString KLocale::monetaryThousandsSeparator() const
00937 {
00938 doFormatInit();
00939 return m_monetaryThousandsSeparator;
00940 }
00941
00942 QString KLocale::positiveSign() const
00943 {
00944 doFormatInit();
00945 return m_positiveSign;
00946 }
00947
00948 QString KLocale::negativeSign() const
00949 {
00950 doFormatInit();
00951 return m_negativeSign;
00952 }
00953
00954 int KLocale::fracDigits() const
00955 {
00956 doFormatInit();
00957 return m_fracDigits;
00958 }
00959
00960 bool KLocale::positivePrefixCurrencySymbol() const
00961 {
00962 doFormatInit();
00963 return m_positivePrefixCurrencySymbol;
00964 }
00965
00966 bool KLocale::negativePrefixCurrencySymbol() const
00967 {
00968 doFormatInit();
00969 return m_negativePrefixCurrencySymbol;
00970 }
00971
00972 KLocale::SignPosition KLocale::positiveMonetarySignPosition() const
00973 {
00974 doFormatInit();
00975 return m_positiveMonetarySignPosition;
00976 }
00977
00978 KLocale::SignPosition KLocale::negativeMonetarySignPosition() const
00979 {
00980 doFormatInit();
00981 return m_negativeMonetarySignPosition;
00982 }
00983
00984 static inline void put_it_in( QChar *buffer, uint& index, const QString &s )
00985 {
00986 for ( uint l = 0; l < s.length(); l++ )
00987 buffer[index++] = s.at( l );
00988 }
00989
00990 static inline void put_it_in( QChar *buffer, uint& index, int number )
00991 {
00992 buffer[index++] = number / 10 + '0';
00993 buffer[index++] = number % 10 + '0';
00994 }
00995
00996 QString KLocale::formatMoney(double num,
00997 const QString & symbol,
00998 int precision) const
00999 {
01000
01001 QString currency = symbol.isNull()
01002 ? currencySymbol()
01003 : symbol;
01004 if (precision < 0) precision = fracDigits();
01005
01006
01007 bool neg = num < 0;
01008 QString res = QString::number(neg?-num:num, 'f', precision);
01009 int pos = res.find('.');
01010 if (pos == -1) pos = res.length();
01011 else res.replace(pos, 1, monetaryDecimalSymbol());
01012
01013 while (0 < (pos -= 3))
01014 res.insert(pos, monetaryThousandsSeparator());
01015
01016
01017 int signpos = neg
01018 ? negativeMonetarySignPosition()
01019 : positiveMonetarySignPosition();
01020 QString sign = neg
01021 ? negativeSign()
01022 : positiveSign();
01023
01024 switch (signpos)
01025 {
01026 case ParensAround:
01027 res.prepend('(');
01028 res.append (')');
01029 break;
01030 case BeforeQuantityMoney:
01031 res.prepend(sign);
01032 break;
01033 case AfterQuantityMoney:
01034 res.append(sign);
01035 break;
01036 case BeforeMoney:
01037 currency.prepend(sign);
01038 break;
01039 case AfterMoney:
01040 currency.append(sign);
01041 break;
01042 }
01043
01044 if (neg?negativePrefixCurrencySymbol():
01045 positivePrefixCurrencySymbol())
01046 {
01047 res.prepend(' ');
01048 res.prepend(currency);
01049 } else {
01050 res.append (' ');
01051 res.append (currency);
01052 }
01053
01054 return res;
01055 }
01056
01057 QString KLocale::formatMoney(const QString &numStr) const
01058 {
01059 return formatMoney(numStr.toDouble());
01060 }
01061
01062 QString KLocale::formatNumber(double num, int precision) const
01063 {
01064 bool neg = num < 0;
01065 if (precision == -1) precision = 2;
01066 QString res = QString::number(neg?-num:num, 'f', precision);
01067 int pos = res.find('.');
01068 if (pos == -1) pos = res.length();
01069 else res.replace(pos, 1, decimalSymbol());
01070
01071 while (0 < (pos -= 3))
01072 res.insert(pos, thousandsSeparator());
01073
01074
01075 res.prepend(neg?negativeSign():positiveSign());
01076
01077 return res;
01078 }
01079
01080 QString KLocale::formatLong(long num) const
01081 {
01082 return formatNumber((double)num, 0);
01083 }
01084
01085 QString KLocale::formatNumber(const QString &numStr) const
01086 {
01087 return formatNumber(numStr.toDouble());
01088 }
01089
01090 QString KLocale::formatDate(const QDate &pDate, bool shortFormat) const
01091 {
01092 const QString rst = shortFormat?dateFormatShort():dateFormat();
01093
01094 QString buffer;
01095
01096 bool escape = false;
01097
01098 int year = calendar()->year(pDate);
01099 int month = calendar()->month(pDate);
01100
01101 for ( uint format_index = 0; format_index < rst.length(); ++format_index )
01102 {
01103 if ( !escape )
01104 {
01105 if ( rst.at( format_index ).unicode() == '%' )
01106 escape = true;
01107 else
01108 buffer.append(rst.at(format_index));
01109 }
01110 else
01111 {
01112 switch ( rst.at( format_index ).unicode() )
01113 {
01114 case '%':
01115 buffer.append('%');
01116 break;
01117 case 'Y':
01118 buffer.append(calendar()->yearString(pDate, false));
01119 break;
01120 case 'y':
01121 buffer.append(calendar()->yearString(pDate, true));
01122 break;
01123 case 'n':
01124 buffer.append(calendar()->monthString(pDate, true));
01125 break;
01126 case 'e':
01127 buffer.append(calendar()->dayString(pDate, true));
01128 break;
01129 case 'm':
01130 buffer.append(calendar()->monthString(pDate, false));
01131 break;
01132 case 'b':
01133 if (d->nounDeclension && d->dateMonthNamePossessive)
01134 buffer.append(calendar()->monthNamePossessive(month, year, true));
01135 else
01136 buffer.append(calendar()->monthName(month, year, true));
01137 break;
01138 case 'B':
01139 if (d->nounDeclension && d->dateMonthNamePossessive)
01140 buffer.append(calendar()->monthNamePossessive(month, year, false));
01141 else
01142 buffer.append(calendar()->monthName(month, year, false));
01143 break;
01144 case 'd':
01145 buffer.append(calendar()->dayString(pDate, false));
01146 break;
01147 case 'a':
01148 buffer.append(calendar()->weekDayName(pDate, true));
01149 break;
01150 case 'A':
01151 buffer.append(calendar()->weekDayName(pDate, false));
01152 break;
01153 default:
01154 buffer.append(rst.at(format_index));
01155 break;
01156 }
01157 escape = false;
01158 }
01159 }
01160 return buffer;
01161 }
01162
01163 void KLocale::setMainCatalogue(const char *catalog)
01164 {
01165 maincatalogue = catalog;
01166 }
01167
01168 double KLocale::readNumber(const QString &_str, bool * ok) const
01169 {
01170 QString str = _str.stripWhiteSpace();
01171 bool neg = str.find(negativeSign()) == 0;
01172 if (neg)
01173 str.remove( 0, negativeSign().length() );
01174
01175
01176
01177
01178 QString exponentialPart;
01179 int EPos;
01180
01181 EPos = str.find('E', 0, false);
01182
01183 if (EPos != -1)
01184 {
01185 exponentialPart = str.mid(EPos);
01186 str = str.left(EPos);
01187 }
01188
01189 int pos = str.find(decimalSymbol());
01190 QString major;
01191 QString minor;
01192 if ( pos == -1 )
01193 major = str;
01194 else
01195 {
01196 major = str.left(pos);
01197 minor = str.mid(pos + decimalSymbol().length());
01198 }
01199
01200
01201 int thlen = thousandsSeparator().length();
01202 int lastpos = 0;
01203 while ( ( pos = major.find( thousandsSeparator() ) ) > 0 )
01204 {
01205
01206 int fromEnd = major.length() - pos;
01207 if ( fromEnd % (3+thlen) != 0
01208 || pos - lastpos > 3
01209 || pos == 0
01210 || (lastpos>0 && pos-lastpos!=3))
01211 {
01212 if (ok) *ok = false;
01213 return 0.0;
01214 }
01215
01216 lastpos = pos;
01217 major.remove( pos, thlen );
01218 }
01219 if (lastpos>0 && major.length()-lastpos!=3)
01220 {
01221 if (ok) *ok = false;
01222 return 0.0;
01223 }
01224
01225 QString tot;
01226 if (neg) tot = '-';
01227
01228 tot += major + '.' + minor + exponentialPart;
01229
01230 return tot.toDouble(ok);
01231 }
01232
01233 double KLocale::readMoney(const QString &_str, bool * ok) const
01234 {
01235 QString str = _str.stripWhiteSpace();
01236 bool neg = false;
01237 bool currencyFound = false;
01238
01239 int pos = str.find(currencySymbol());
01240 if ( pos == 0 || pos == (int) str.length()-1 )
01241 {
01242 str.remove(pos,currencySymbol().length());
01243 str = str.stripWhiteSpace();
01244 currencyFound = true;
01245 }
01246 if (str.isEmpty())
01247 {
01248 if (ok) *ok = false;
01249 return 0;
01250 }
01251
01252
01253 if (negativeMonetarySignPosition() == ParensAround)
01254 {
01255 if (str[0] == '(' && str[str.length()-1] == ')')
01256 {
01257 neg = true;
01258 str.remove(str.length()-1,1);
01259 str.remove(0,1);
01260 }
01261 }
01262 else
01263 {
01264 int i1 = str.find(negativeSign());
01265 if ( i1 == 0 || i1 == (int) str.length()-1 )
01266 {
01267 neg = true;
01268 str.remove(i1,negativeSign().length());
01269 }
01270 }
01271 if (neg) str = str.stripWhiteSpace();
01272
01273
01274
01275 if ( !currencyFound )
01276 {
01277 pos = str.find(currencySymbol());
01278 if ( pos == 0 || pos == (int) str.length()-1 )
01279 {
01280 str.remove(pos,currencySymbol().length());
01281 str = str.stripWhiteSpace();
01282 }
01283 }
01284
01285
01286 pos = str.find(monetaryDecimalSymbol());
01287 QString major;
01288 QString minior;
01289 if (pos == -1)
01290 major = str;
01291 else
01292 {
01293 major = str.left(pos);
01294 minior = str.mid(pos + monetaryDecimalSymbol().length());
01295 }
01296
01297
01298 int thlen = monetaryThousandsSeparator().length();
01299 int lastpos = 0;
01300 while ( ( pos = major.find( monetaryThousandsSeparator() ) ) > 0 )
01301 {
01302
01303 int fromEnd = major.length() - pos;
01304 if ( fromEnd % (3+thlen) != 0
01305 || pos - lastpos > 3
01306 || pos == 0
01307 || (lastpos>0 && pos-lastpos!=3))
01308 {
01309 if (ok) *ok = false;
01310 return 0.0;
01311 }
01312 lastpos = pos;
01313 major.remove( pos, thlen );
01314 }
01315 if (lastpos>0 && major.length()-lastpos!=3)
01316 {
01317 if (ok) *ok = false;
01318 return 0.0;
01319 }
01320
01321 QString tot;
01322 if (neg) tot = '-';
01323 tot += major + '.' + minior;
01324 return tot.toDouble(ok);
01325 }
01326
01333 static int readInt(const QString &str, uint &pos)
01334 {
01335 if (!str.at(pos).isDigit()) return -1;
01336 int result = 0;
01337 for (; str.length() > pos && str.at(pos).isDigit(); pos++)
01338 {
01339 result *= 10;
01340 result += str.at(pos).digitValue();
01341 }
01342
01343 return result;
01344 }
01345
01346 QDate KLocale::readDate(const QString &intstr, bool* ok) const
01347 {
01348 QDate date;
01349 date = readDate(intstr, ShortFormat, ok);
01350 if (date.isValid()) return date;
01351 return readDate(intstr, NormalFormat, ok);
01352 }
01353
01354 QDate KLocale::readDate(const QString &intstr, ReadDateFlags flags, bool* ok) const
01355 {
01356 QString fmt = ((flags & ShortFormat) ? dateFormatShort() : dateFormat()).simplifyWhiteSpace();
01357 return readDate( intstr, fmt, ok );
01358 }
01359
01360 QDate KLocale::readDate(const QString &intstr, const QString &fmt, bool* ok) const
01361 {
01362
01363 QString str = intstr.simplifyWhiteSpace().lower();
01364 int day = -1, month = -1;
01365
01366 int year = calendar()->year(QDate::currentDate());
01367 uint strpos = 0;
01368 uint fmtpos = 0;
01369
01370 int iLength;
01371
01372 bool error = false;
01373
01374 while (fmt.length() > fmtpos && str.length() > strpos && !error)
01375 {
01376
01377 QChar c = fmt.at(fmtpos++);
01378
01379 if (c != '%') {
01380 if (c.isSpace() && str.at(strpos).isSpace())
01381 strpos++;
01382 else if (c != str.at(strpos++))
01383 error = true;
01384 }
01385 else
01386 {
01387 int j;
01388
01389 if (str.length() > strpos && str.at(strpos).isSpace())
01390 strpos++;
01391
01392 c = fmt.at(fmtpos++);
01393 switch (c)
01394 {
01395 case 'a':
01396 case 'A':
01397
01398 error = true;
01399 j = 1;
01400 while (error && (j < 8)) {
01401 QString s = calendar()->weekDayName(j, c == 'a').lower();
01402 int len = s.length();
01403 if (str.mid(strpos, len) == s)
01404 {
01405 strpos += len;
01406 error = false;
01407 }
01408 j++;
01409 }
01410 break;
01411 case 'b':
01412 case 'B':
01413
01414 error = true;
01415 if (d->nounDeclension && d->dateMonthNamePossessive) {
01416 j = 1;
01417 while (error && (j < 13)) {
01418 QString s = calendar()->monthNamePossessive(j, year, c == 'b').lower();
01419 int len = s.length();
01420 if (str.mid(strpos, len) == s) {
01421 month = j;
01422 strpos += len;
01423 error = false;
01424 }
01425 j++;
01426 }
01427 }
01428 j = 1;
01429 while (error && (j < 13)) {
01430 QString s = calendar()->monthName(j, year, c == 'b').lower();
01431 int len = s.length();
01432 if (str.mid(strpos, len) == s) {
01433 month = j;
01434 strpos += len;
01435 error = false;
01436 }
01437 j++;
01438 }
01439 break;
01440 case 'd':
01441 case 'e':
01442 day = calendar()->dayStringToInteger(str.mid(strpos), iLength);
01443 strpos += iLength;
01444
01445 error = iLength <= 0;
01446 break;
01447
01448 case 'n':
01449 case 'm':
01450 month = calendar()->monthStringToInteger(str.mid(strpos), iLength);
01451 strpos += iLength;
01452
01453 error = iLength <= 0;
01454 break;
01455
01456 case 'Y':
01457 case 'y':
01458 year = calendar()->yearStringToInteger(str.mid(strpos), iLength);
01459 strpos += iLength;
01460
01461 error = iLength <= 0;
01462
01463
01464
01465
01466
01467
01468
01469
01470
01471
01472 break;
01473 }
01474 }
01475 }
01476
01477
01478
01479 if ( fmt.length() > fmtpos || str.length() > strpos )
01480 {
01481 error = true;
01482 }
01483
01484
01485 if ( year != -1 && month != -1 && day != -1 && !error)
01486 {
01487 if (ok) *ok = true;
01488
01489 QDate result;
01490 calendar()->setYMD(result, year, month, day);
01491
01492 return result;
01493 }
01494 else
01495 {
01496 if (ok) *ok = false;
01497 return QDate();
01498 }
01499 }
01500
01501 QTime KLocale::readTime(const QString &intstr, bool *ok) const
01502 {
01503 QTime _time;
01504 _time = readTime(intstr, WithSeconds, ok);
01505 if (_time.isValid()) return _time;
01506 return readTime(intstr, WithoutSeconds, ok);
01507 }
01508
01509 QTime KLocale::readTime(const QString &intstr, ReadTimeFlags flags, bool *ok) const
01510 {
01511 QString str = intstr.simplifyWhiteSpace().lower();
01512 QString Format = timeFormat().simplifyWhiteSpace();
01513 if (flags & WithoutSeconds)
01514 Format.remove(QRegExp(".%S"));
01515
01516 int hour = -1, minute = -1;
01517 int second = ( flags & WithoutSeconds == 0 ) ? -1 : 0;
01518 bool g_12h = false;
01519 bool pm = false;
01520 uint strpos = 0;
01521 uint Formatpos = 0;
01522
01523 while (Format.length() > Formatpos || str.length() > strpos)
01524 {
01525 if ( !(Format.length() > Formatpos && str.length() > strpos) ) goto error;
01526
01527 QChar c = Format.at(Formatpos++);
01528
01529 if (c != '%')
01530 {
01531 if (c.isSpace())
01532 strpos++;
01533 else if (c != str.at(strpos++))
01534 goto error;
01535 continue;
01536 }
01537
01538
01539 if (str.length() > strpos && str.at(strpos).isSpace())
01540 strpos++;
01541
01542 c = Format.at(Formatpos++);
01543 switch (c)
01544 {
01545 case 'p':
01546 {
01547 QString s;
01548 s = translate("pm").lower();
01549 int len = s.length();
01550 if (str.mid(strpos, len) == s)
01551 {
01552 pm = true;
01553 strpos += len;
01554 }
01555 else
01556 {
01557 s = translate("am").lower();
01558 len = s.length();
01559 if (str.mid(strpos, len) == s) {
01560 pm = false;
01561 strpos += len;
01562 }
01563 else
01564 goto error;
01565 }
01566 }
01567 break;
01568
01569 case 'k':
01570 case 'H':
01571 g_12h = false;
01572 hour = readInt(str, strpos);
01573 if (hour < 0 || hour > 23)
01574 goto error;
01575
01576 break;
01577
01578 case 'l':
01579 case 'I':
01580 g_12h = true;
01581 hour = readInt(str, strpos);
01582 if (hour < 1 || hour > 12)
01583 goto error;
01584
01585 break;
01586
01587 case 'M':
01588 minute = readInt(str, strpos);
01589 if (minute < 0 || minute > 59)
01590 goto error;
01591
01592 break;
01593
01594 case 'S':
01595 second = readInt(str, strpos);
01596 if (second < 0 || second > 59)
01597 goto error;
01598
01599 break;
01600 }
01601 }
01602 if (g_12h) {
01603 hour %= 12;
01604 if (pm) hour += 12;
01605 }
01606
01607 if (ok) *ok = true;
01608 return QTime(hour, minute, second);
01609
01610 error:
01611 if (ok) *ok = false;
01612 return QTime(-1, -1, -1);
01613 }
01614
01615 QString KLocale::formatTime(const QTime &pTime, bool includeSecs) const
01616 {
01617 const QString rst = timeFormat();
01618
01619
01620
01621 QChar *buffer = new QChar[rst.length() * 3 / 2 + 30];
01622
01623 uint index = 0;
01624 bool escape = false;
01625 int number = 0;
01626
01627 for ( uint format_index = 0; format_index < rst.length(); format_index++ )
01628 {
01629 if ( !escape )
01630 {
01631 if ( rst.at( format_index ).unicode() == '%' )
01632 escape = true;
01633 else
01634 buffer[index++] = rst.at( format_index );
01635 }
01636 else
01637 {
01638 switch ( rst.at( format_index ).unicode() )
01639 {
01640 case '%':
01641 buffer[index++] = '%';
01642 break;
01643 case 'H':
01644 put_it_in( buffer, index, pTime.hour() );
01645 break;
01646 case 'I':
01647 put_it_in( buffer, index, ( pTime.hour() + 11) % 12 + 1 );
01648 break;
01649 case 'M':
01650 put_it_in( buffer, index, pTime.minute() );
01651 break;
01652 case 'S':
01653 if (includeSecs)
01654 put_it_in( buffer, index, pTime.second() );
01655 else if ( index > 0 )
01656 {
01657
01658
01659 --index;
01660 break;
01661 }
01662 break;
01663 case 'k':
01664 number = pTime.hour();
01665 case 'l':
01666
01667 if ( rst.at( format_index ).unicode() == 'l' )
01668 number = (pTime.hour() + 11) % 12 + 1;
01669 if ( number / 10 )
01670 buffer[index++] = number / 10 + '0';
01671 buffer[index++] = number % 10 + '0';
01672 break;
01673 case 'p':
01674 {
01675 QString s;
01676 if ( pTime.hour() >= 12 )
01677 put_it_in( buffer, index, translate("pm") );
01678 else
01679 put_it_in( buffer, index, translate("am") );
01680 break;
01681 }
01682 default:
01683 buffer[index++] = rst.at( format_index );
01684 break;
01685 }
01686 escape = false;
01687 }
01688 }
01689 QString ret( buffer, index );
01690 delete [] buffer;
01691 return ret;
01692 }
01693
01694 bool KLocale::use12Clock() const
01695 {
01696 if ((timeFormat().contains(QString::fromLatin1("%I")) > 0) ||
01697 (timeFormat().contains(QString::fromLatin1("%l")) > 0))
01698 return true;
01699 else
01700 return false;
01701 }
01702
01703 QString KLocale::languages() const
01704 {
01705 return d->languageList.join( QString::fromLatin1(":") );
01706 }
01707
01708 QStringList KLocale::languageList() const
01709 {
01710 return d->languageList;
01711 }
01712
01713 QString KLocale::formatDateTime(const QDateTime &pDateTime,
01714 bool shortFormat,
01715 bool includeSeconds) const
01716 {
01717 return translate("concatenation of dates and time", "%1 %2")
01718 .arg( formatDate( pDateTime.date(), shortFormat ) )
01719 .arg( formatTime( pDateTime.time(), includeSeconds ) );
01720 }
01721
01722 QString i18n(const char* text)
01723 {
01724 register KLocale *instance = KGlobal::locale();
01725 if (instance)
01726 return instance->translate(text);
01727 return QString::fromUtf8(text);
01728 }
01729
01730 QString i18n(const char* index, const char *text)
01731 {
01732 register KLocale *instance = KGlobal::locale();
01733 if (instance)
01734 return instance->translate(index, text);
01735 return QString::fromUtf8(text);
01736 }
01737
01738 QString i18n(const char* singular, const char* plural, unsigned long n)
01739 {
01740 register KLocale *instance = KGlobal::locale();
01741 if (instance)
01742 return instance->translate(singular, plural, n);
01743 if (n == 1)
01744 return put_n_in(QString::fromUtf8(singular), n);
01745 else
01746 return put_n_in(QString::fromUtf8(plural), n);
01747 }
01748
01749 void KLocale::initInstance()
01750 {
01751 if (KGlobal::_locale)
01752 return;
01753
01754 KInstance *app = KGlobal::instance();
01755 if (app) {
01756 KGlobal::_locale = new KLocale(QString::fromLatin1(app->instanceName()));
01757
01758
01759 QTextCodec::setCodecForLocale(KGlobal::_locale->codecForEncoding());
01760 }
01761 else
01762 kdDebug(173) << "no app name available using KLocale - nothing to do\n";
01763 }
01764
01765 QString KLocale::langLookup(const QString &fname, const char *rtype)
01766 {
01767 QStringList search;
01768
01769
01770 const QStringList localDoc = KGlobal::dirs()->resourceDirs(rtype);
01771
01772
01773 for (int id=localDoc.count()-1; id >= 0; --id)
01774 {
01775 QStringList langs = KGlobal::locale()->languageList();
01776 langs.append( "en" );
01777 langs.remove( defaultLanguage() );
01778 QStringList::ConstIterator lang;
01779 for (lang = langs.begin(); lang != langs.end(); ++lang)
01780 search.append(QString("%1%2/%3").arg(localDoc[id]).arg(*lang).arg(fname));
01781 }
01782
01783
01784 QStringList::Iterator it;
01785 for (it = search.begin(); it != search.end(); ++it)
01786 {
01787 kdDebug(173) << "Looking for help in: " << *it << endl;
01788
01789 QFileInfo info(*it);
01790 if (info.exists() && info.isFile() && info.isReadable())
01791 return *it;
01792 }
01793
01794 return QString::null;
01795 }
01796
01797 bool KLocale::useDefaultLanguage() const
01798 {
01799 return language() == defaultLanguage();
01800 }
01801
01802 void KLocale::initEncoding(KConfig *)
01803 {
01804 const int mibDefault = 4;
01805
01806
01807 setEncoding( QTextCodec::codecForLocale()->mibEnum() );
01808
01809 if ( !d->codecForEncoding )
01810 {
01811 kdWarning(173) << " Defaulting to ISO 8859-1 encoding." << endl;
01812 setEncoding(mibDefault);
01813 }
01814
01815 Q_ASSERT( d->codecForEncoding );
01816 }
01817
01818 void KLocale::initFileNameEncoding(KConfig *)
01819 {
01820
01821
01822 d->utf8FileEncoding = getenv("KDE_UTF8_FILENAMES") != 0;
01823 if (d->utf8FileEncoding)
01824 {
01825 QFile::setEncodingFunction(KLocale::encodeFileNameUTF8);
01826 QFile::setDecodingFunction(KLocale::decodeFileNameUTF8);
01827 }
01828
01829
01830 }
01831
01832 QCString KLocale::encodeFileNameUTF8( const QString & fileName )
01833 {
01834 return fileName.utf8();
01835 }
01836
01837 QString KLocale::decodeFileNameUTF8( const QCString & localFileName )
01838 {
01839 return QString::fromUtf8(localFileName);
01840 }
01841
01842 void KLocale::initCatalogue( KCatalogue & catalog )
01843 {
01844 catalog.setFileName( catalogueFileName( language(), catalog ) );
01845 }
01846
01847 void KLocale::setDateFormat(const QString & format)
01848 {
01849 doFormatInit();
01850 m_dateFormat = format.stripWhiteSpace();
01851 }
01852
01853 void KLocale::setDateFormatShort(const QString & format)
01854 {
01855 doFormatInit();
01856 m_dateFormatShort = format.stripWhiteSpace();
01857 }
01858
01859 void KLocale::setDateMonthNamePossessive(bool possessive)
01860 {
01861 doFormatInit();
01862 d->dateMonthNamePossessive = possessive;
01863 }
01864
01865 void KLocale::setTimeFormat(const QString & format)
01866 {
01867 doFormatInit();
01868 m_timeFormat = format.stripWhiteSpace();
01869 }
01870
01871 void KLocale::setWeekStartsMonday(bool start)
01872 {
01873 doFormatInit();
01874 if (start)
01875 d->weekStartDay = 1;
01876 else
01877 d->weekStartDay = 7;
01878 }
01879
01880 void KLocale::setWeekStartDay(int day)
01881 {
01882 doFormatInit();
01883 if (day>7 || day<1)
01884 d->weekStartDay = 1;
01885 else
01886 d->weekStartDay = day;
01887 }
01888
01889 QString KLocale::dateFormat() const
01890 {
01891 doFormatInit();
01892 return m_dateFormat;
01893 }
01894
01895 QString KLocale::dateFormatShort() const
01896 {
01897 doFormatInit();
01898 return m_dateFormatShort;
01899 }
01900
01901 QString KLocale::timeFormat() const
01902 {
01903 doFormatInit();
01904 return m_timeFormat;
01905 }
01906
01907 void KLocale::setDecimalSymbol(const QString & symbol)
01908 {
01909 doFormatInit();
01910 m_decimalSymbol = symbol.stripWhiteSpace();
01911 }
01912
01913 void KLocale::setThousandsSeparator(const QString & separator)
01914 {
01915 doFormatInit();
01916
01917 m_thousandsSeparator = separator;
01918 }
01919
01920 void KLocale::setPositiveSign(const QString & sign)
01921 {
01922 doFormatInit();
01923 m_positiveSign = sign.stripWhiteSpace();
01924 }
01925
01926 void KLocale::setNegativeSign(const QString & sign)
01927 {
01928 doFormatInit();
01929 m_negativeSign = sign.stripWhiteSpace();
01930 }
01931
01932 void KLocale::setPositiveMonetarySignPosition(SignPosition signpos)
01933 {
01934 doFormatInit();
01935 m_positiveMonetarySignPosition = signpos;
01936 }
01937
01938 void KLocale::setNegativeMonetarySignPosition(SignPosition signpos)
01939 {
01940 doFormatInit();
01941 m_negativeMonetarySignPosition = signpos;
01942 }
01943
01944 void KLocale::setPositivePrefixCurrencySymbol(bool prefix)
01945 {
01946 doFormatInit();
01947 m_positivePrefixCurrencySymbol = prefix;
01948 }
01949
01950 void KLocale::setNegativePrefixCurrencySymbol(bool prefix)
01951 {
01952 doFormatInit();
01953 m_negativePrefixCurrencySymbol = prefix;
01954 }
01955
01956 void KLocale::setFracDigits(int digits)
01957 {
01958 doFormatInit();
01959 m_fracDigits = digits;
01960 }
01961
01962 void KLocale::setMonetaryThousandsSeparator(const QString & separator)
01963 {
01964 doFormatInit();
01965
01966 m_monetaryThousandsSeparator = separator;
01967 }
01968
01969 void KLocale::setMonetaryDecimalSymbol(const QString & symbol)
01970 {
01971 doFormatInit();
01972 m_monetaryDecimalSymbol = symbol.stripWhiteSpace();
01973 }
01974
01975 void KLocale::setCurrencySymbol(const QString & symbol)
01976 {
01977 doFormatInit();
01978 m_currencySymbol = symbol.stripWhiteSpace();
01979 }
01980
01981 int KLocale::pageSize() const
01982 {
01983 doFormatInit();
01984 return d->pageSize;
01985 }
01986
01987 void KLocale::setPageSize(int pageSize)
01988 {
01989
01990 doFormatInit();
01991 d->pageSize = pageSize;
01992 }
01993
01994 KLocale::MeasureSystem KLocale::measureSystem() const
01995 {
01996 doFormatInit();
01997 return d->measureSystem;
01998 }
01999
02000 void KLocale::setMeasureSystem(MeasureSystem value)
02001 {
02002 doFormatInit();
02003 d->measureSystem = value;
02004 }
02005
02006 QString KLocale::defaultLanguage()
02007 {
02008 return QString::fromLatin1("en_US");
02009 }
02010
02011 QString KLocale::defaultCountry()
02012 {
02013 return QString::fromLatin1("C");
02014 }
02015
02016 const char * KLocale::encoding() const
02017 {
02018 return codecForEncoding()->name();
02019 }
02020
02021 int KLocale::encodingMib() const
02022 {
02023 return codecForEncoding()->mibEnum();
02024 }
02025
02026 int KLocale::fileEncodingMib() const
02027 {
02028 if (d->utf8FileEncoding)
02029 return 106;
02030 return codecForEncoding()->mibEnum();
02031 }
02032
02033 QTextCodec * KLocale::codecForEncoding() const
02034 {
02035 return d->codecForEncoding;
02036 }
02037
02038 bool KLocale::setEncoding(int mibEnum)
02039 {
02040 QTextCodec * codec = QTextCodec::codecForMib(mibEnum);
02041 if (codec)
02042 d->codecForEncoding = codec;
02043
02044 return codec != 0;
02045 }
02046
02047 QStringList KLocale::languagesTwoAlpha() const
02048 {
02049 if (d->langTwoAlpha.count())
02050 return d->langTwoAlpha;
02051
02052 const QStringList &origList = languageList();
02053
02054 QStringList result;
02055
02056 KConfig config(QString::fromLatin1("language.codes"), true, false);
02057 config.setGroup("TwoLetterCodes");
02058
02059 for ( QStringList::ConstIterator it = origList.begin();
02060 it != origList.end();
02061 ++it )
02062 {
02063 QString lang = *it;
02064 QStringList langLst;
02065 if (config.hasKey( lang ))
02066 langLst = config.readListEntry( lang );
02067 else
02068 {
02069 int i = lang.find('_');
02070 if (i >= 0)
02071 lang.truncate(i);
02072 langLst << lang;
02073 }
02074
02075 for ( QStringList::ConstIterator langIt = langLst.begin();
02076 langIt != langLst.end();
02077 ++langIt )
02078 {
02079 if ( !(*langIt).isEmpty() && !result.contains( *langIt ) )
02080 result += *langIt;
02081 }
02082 }
02083 d->langTwoAlpha = result;
02084 return result;
02085 }
02086
02087 QStringList KLocale::allLanguagesTwoAlpha() const
02088 {
02089 if (!d->languages)
02090 d->languages = new KConfig("all_languages", true, false, "locale");
02091
02092 return d->languages->groupList();
02093 }
02094
02095 QString KLocale::twoAlphaToLanguageName(const QString &code) const
02096 {
02097 if (!d->languages)
02098 d->languages = new KConfig("all_languages", true, false, "locale");
02099
02100 d->languages->setGroup(code.lower());
02101 return d->languages->readEntry("Name");
02102 }
02103
02104 QStringList KLocale::allCountriesTwoAlpha() const
02105 {
02106 QStringList countries;
02107 QStringList paths = KGlobal::dirs()->findAllResources("locale", "l10n/*/entry.desktop");
02108 for(QStringList::ConstIterator it = paths.begin();
02109 it != paths.end(); ++it)
02110 {
02111 QString code = (*it).mid((*it).length()-16, 2);
02112 if (code != "/C")
02113 countries.append(code);
02114 }
02115 return countries;
02116 }
02117
02118 QString KLocale::twoAlphaToCountryName(const QString &code) const
02119 {
02120 KConfig cfg("l10n/"+code.lower()+"/entry.desktop", true, false, "locale");
02121 cfg.setGroup("KCM Locale");
02122 return cfg.readEntry("Name");
02123 }
02124
02125 void KLocale::setCalendar(const QString & calType)
02126 {
02127 doFormatInit();
02128
02129 d->calendarType = calType;
02130
02131 delete d->calendar;
02132 d->calendar = 0;
02133 }
02134
02135 QString KLocale::calendarType() const
02136 {
02137 doFormatInit();
02138
02139 return d->calendarType;
02140 }
02141
02142 const KCalendarSystem * KLocale::calendar() const
02143 {
02144 doFormatInit();
02145
02146
02147 if ( !d->calendar )
02148 d->calendar = KCalendarSystemFactory::create( d->calendarType, this );
02149
02150 return d->calendar;
02151 }
02152
02153 KLocale::KLocale(const KLocale & rhs)
02154 {
02155 d = new KLocalePrivate;
02156
02157 *this = rhs;
02158 }
02159
02160 KLocale & KLocale::operator=(const KLocale & rhs)
02161 {
02162
02163 m_decimalSymbol = rhs.m_decimalSymbol;
02164 m_thousandsSeparator = rhs.m_thousandsSeparator;
02165 m_currencySymbol = rhs.m_currencySymbol;
02166 m_monetaryDecimalSymbol = rhs.m_monetaryDecimalSymbol;
02167 m_monetaryThousandsSeparator = rhs.m_monetaryThousandsSeparator;
02168 m_positiveSign = rhs.m_positiveSign;
02169 m_negativeSign = rhs.m_negativeSign;
02170 m_fracDigits = rhs.m_fracDigits;
02171 m_positivePrefixCurrencySymbol = rhs.m_positivePrefixCurrencySymbol;
02172 m_negativePrefixCurrencySymbol = rhs.m_negativePrefixCurrencySymbol;
02173 m_positiveMonetarySignPosition = rhs.m_positiveMonetarySignPosition;
02174 m_negativeMonetarySignPosition = rhs.m_negativeMonetarySignPosition;
02175
02176
02177 m_timeFormat = rhs.m_timeFormat;
02178 m_dateFormat = rhs.m_dateFormat;
02179 m_dateFormatShort = rhs.m_dateFormatShort;
02180
02181 m_language = rhs.m_language;
02182 m_country = rhs.m_country;
02183
02184
02185 *d = *rhs.d;
02186 d->languages = 0;
02187 d->calendar = 0;
02188
02189 return *this;
02190 }
02191
02192 bool KLocale::setCharset(const QString & ) { return true; }
02193 QString KLocale::charset() const { return QString::fromLatin1("UTF-8"); }
02194