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