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