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