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