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 languageList +=
QStringList::split
00140 (
':',
QFile::decodeName( ::getenv(
"KDE_LANG") ));
00141
00142 languageList += config->
readListEntry(
"Language",
':');
00143
00144
00145
if ( useEnv )
00146 {
00147
00148
QStringList langs;
00149
00150 langs <<
QFile::decodeName( ::getenv(
"LC_ALL") );
00151 langs <<
QFile::decodeName( ::getenv(
"LC_MESSAGES") );
00152 langs <<
QFile::decodeName( ::getenv(
"LANG") );
00153 langs <<
QFile::decodeName( ::getenv(
"LC_CTYPE") );
00154
00155
for ( QStringList::Iterator it = langs.begin();
00156 it != langs.end();
00157 ++it )
00158 {
00159
QString ln, ct, chrset;
00160
splitLocale(*it, ln, ct, chrset);
00161
00162
if (!ct.
isEmpty()) {
00163 langs.insert(it, ln +
'_' + ct);
00164
if (!chrset.
isEmpty())
00165 langs.insert(it, ln +
'_' + ct +
'.' + chrset);
00166 }
00167
00168 langs.insert(it, ln);
00169 }
00170
00171 languageList += langs;
00172 }
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