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