00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include <klocalizedstring.h>
00021
00022 #include <config.h>
00023
00024 #include <kglobal.h>
00025 #include <kdebug.h>
00026 #include <klocale.h>
00027 #include <kcomponentdata.h>
00028 #include <klibrary.h>
00029 #include <kstandarddirs.h>
00030 #include <ktranscript_p.h>
00031 #include <ktranslit_p.h>
00032 #include <kuitsemantics_p.h>
00033 #include "kcatalogname_p.h"
00034
00035 #include <QMutexLocker>
00036 #include <QStringList>
00037 #include <QByteArray>
00038 #include <QChar>
00039 #include <QHash>
00040 #include <QList>
00041 #include <QVector>
00042
00043
00044 static QString shortenMessage (const QString &str)
00045 {
00046 const int maxlen = 20;
00047 if (str.length() <= maxlen)
00048 return str;
00049 else
00050 return str.left(maxlen).append("...");
00051 }
00052
00053 typedef qulonglong pluraln;
00054 typedef qlonglong intn;
00055 typedef qulonglong uintn;
00056 typedef double realn;
00057
00058 class KLocalizedStringPrivateStatics;
00059
00060 class KLocalizedStringPrivate
00061 {
00062 friend class KLocalizedString;
00063
00064 QStringList args;
00065 QList<QVariant> vals;
00066 bool numberSet;
00067 pluraln number;
00068 int numberOrd;
00069 QByteArray ctxt;
00070 QHash<QString, QString> dynctxt;
00071 QByteArray msg;
00072 QByteArray plural;
00073
00074 QString toString (const KLocale *locale) const;
00075 QString selectForEnglish () const;
00076 QString substituteSimple (const QString &trans,
00077 const QChar &plchar = '%',
00078 bool partial = false) const;
00079 QString postFormat (const QString &text,
00080 const QString &lang,
00081 const QString &lscr,
00082 const QString &ctxt) const;
00083 QString substituteTranscript (const QString &trans,
00084 const QString &lang,
00085 const QString &lscr,
00086 const QString &final,
00087 bool &fallback) const;
00088 int resolveInterpolation (const QString &trans, int pos,
00089 const QString &lang,
00090 const QString &lscr,
00091 const QString &final,
00092 QString &result,
00093 bool &fallback) const;
00094 QVariant segmentToValue (const QString &arg) const;
00095 QString postTranscript (const QString &pcall,
00096 const QString &lang,
00097 const QString &lscr,
00098 const QString &final) const;
00099
00100 static void notifyCatalogsUpdated (const QStringList &languages,
00101 const QList<KCatalogName> &catalogs);
00102 static void loadTranscript ();
00103 };
00104
00105 class KLocalizedStringPrivateStatics
00106 {
00107 public:
00108
00109 const QString theFence;
00110 const QString startInterp;
00111 const QString endInterp;
00112 const QChar scriptPlchar;
00113 const QChar scriptVachar;
00114
00115 const QString scriptDir;
00116 QHash<QString, QStringList> scriptModules;
00117 QList<QStringList> scriptModulesToLoad;
00118
00119 bool loadTranscriptCalled;
00120 KTranscript *ktrs;
00121
00122 QHash<QString, KTranslit*> translits;
00123
00124 QHash<QString, KuitSemantics*> formatters;
00125
00126 QMutex mutex;
00127
00128 KLocalizedStringPrivateStatics () :
00129 theFence("|/|"),
00130 startInterp("$["),
00131 endInterp("]"),
00132 scriptPlchar('%'),
00133 scriptVachar('^'),
00134
00135 scriptDir("LC_SCRIPTS"),
00136 scriptModules(),
00137 scriptModulesToLoad(),
00138
00139 loadTranscriptCalled(false),
00140 ktrs(NULL),
00141
00142 translits(),
00143
00144 formatters(),
00145
00146 mutex(QMutex::Recursive)
00147 {}
00148
00149 ~KLocalizedStringPrivateStatics ()
00150 {
00151
00152
00153 qDeleteAll(translits);
00154 qDeleteAll(formatters);
00155 }
00156 };
00157 K_GLOBAL_STATIC(KLocalizedStringPrivateStatics, staticsKLSP)
00158
00159 KLocalizedString::KLocalizedString ()
00160 : d(new KLocalizedStringPrivate)
00161 {
00162 d->numberSet = false;
00163 d->number = 0;
00164 d->numberOrd = 0;
00165 }
00166
00167 KLocalizedString::KLocalizedString (const char *ctxt,
00168 const char *msg, const char *plural)
00169 : d(new KLocalizedStringPrivate)
00170 {
00171 d->ctxt = ctxt;
00172 d->msg = msg;
00173 d->plural = plural;
00174 d->numberSet = false;
00175 d->number = 0;
00176 d->numberOrd = 0;
00177 }
00178
00179 KLocalizedString::KLocalizedString(const KLocalizedString &rhs)
00180 : d(new KLocalizedStringPrivate(*rhs.d))
00181 {
00182 }
00183
00184 KLocalizedString& KLocalizedString::operator= (const KLocalizedString &rhs)
00185 {
00186 if (&rhs != this)
00187 {
00188 *d = *rhs.d;
00189 }
00190 return *this;
00191 }
00192
00193 KLocalizedString::~KLocalizedString ()
00194 {
00195 delete d;
00196 }
00197
00198 bool KLocalizedString::isEmpty () const
00199 {
00200 return d->msg.isEmpty();
00201 }
00202
00203 QString KLocalizedString::toString () const
00204 {
00205 return d->toString(KGlobal::locale());
00206 }
00207
00208 QString KLocalizedString::toString (const KLocale *locale) const
00209 {
00210 return d->toString(locale);
00211 }
00212
00213 QString KLocalizedStringPrivate::toString (const KLocale *locale) const
00214 {
00215 KLocalizedStringPrivateStatics *s = staticsKLSP;
00216 QMutexLocker lock(&s->mutex);
00217
00218
00219 if (msg.isEmpty())
00220 {
00221 kDebug(173) << "Trying to convert empty KLocalizedString to QString.";
00222 #ifndef NDEBUG
00223 return QString("(I18N_EMPTY_MESSAGE)");
00224 #else
00225 return QString();
00226 #endif
00227 }
00228
00229
00230 if (!plural.isEmpty() && !numberSet)
00231 kDebug(173) << QString("Plural argument to message {%1} not supplied before conversion.")
00232 .arg(shortenMessage(QString::fromUtf8(msg)));
00233
00234
00235 QString lang, rawtrans, lscr;
00236 if (locale != NULL)
00237 {
00238 if (!ctxt.isEmpty() && !plural.isEmpty())
00239 locale->translateRaw(ctxt, msg, plural, number, &lang, &rawtrans);
00240 else if (!plural.isEmpty())
00241 locale->translateRaw(msg, plural, number, &lang, &rawtrans);
00242 else if (!ctxt.isEmpty())
00243 locale->translateRaw(ctxt, msg, &lang, &rawtrans);
00244 else
00245 locale->translateRaw(msg, &lang, &rawtrans);
00246
00247
00248 lscr = KTranslit::higherPriorityScript(lang, locale);
00249 }
00250 else
00251 {
00252 lang = KLocale::defaultLanguage();
00253 rawtrans = selectForEnglish();
00254 }
00255
00256
00257 QString trans, strans;
00258 int cdpos = rawtrans.indexOf(s->theFence);
00259 if (cdpos > 0)
00260 {
00261
00262
00263 trans = rawtrans.left(cdpos);
00264
00265
00266 strans = rawtrans.mid(cdpos + s->theFence.length());
00267
00268
00269 if ( !s->loadTranscriptCalled && !strans.isEmpty()
00270 && locale && locale->useTranscript())
00271 {
00272 if (KGlobal::hasMainComponent())
00273 loadTranscript();
00274 else
00275 kDebug(173) << QString("Scripted message {%1} before transcript engine can be loaded.")
00276 .arg(shortenMessage(trans));
00277 }
00278 }
00279 else if (cdpos < 0)
00280 {
00281
00282 trans = rawtrans;
00283 }
00284 else
00285 {
00286
00287
00288 kDebug(173) << QString("Scripted message {%1} without ordinary translation, discarded.")
00289 .arg(shortenMessage(trans)) ;
00290 trans = selectForEnglish();
00291 }
00292
00293
00294 QString final = substituteSimple(trans);
00295
00296 final = postFormat(final, lang, lscr, ctxt);
00297
00298
00299 if (!strans.isEmpty()) {
00300
00301 bool fallback;
00302 QString sfinal = substituteTranscript(strans, lang, lscr, final, fallback);
00303
00304
00305 if (!sfinal.isEmpty() && !fallback) {
00306 final = postFormat(sfinal, lang, lscr, ctxt);
00307 }
00308 }
00309
00310
00311
00312 if (s->ktrs != NULL)
00313 {
00314 QStringList pcalls = s->ktrs->postCalls(lang);
00315 foreach(const QString &pcall, pcalls)
00316 postTranscript(pcall, lang, lscr, final);
00317 }
00318
00319 return final;
00320 }
00321
00322 QString KLocalizedStringPrivate::selectForEnglish () const
00323 {
00324 QString trans;
00325
00326 if (!plural.isEmpty()) {
00327 if (number == 1) {
00328 trans = QString::fromUtf8(msg);
00329 }
00330 else {
00331 trans = QString::fromUtf8(plural);
00332 }
00333 }
00334 else {
00335 trans = QString::fromUtf8(msg);
00336 }
00337
00338 return trans;
00339 }
00340
00341 QString KLocalizedStringPrivate::substituteSimple (const QString &trans,
00342 const QChar &plchar,
00343 bool partial) const
00344 {
00345 #ifdef NDEBUG
00346 Q_UNUSED(partial);
00347 #endif
00348
00349 QStringList tsegs;
00350 QList<int> plords;
00351 #ifndef NDEBUG
00352 QVector<int> ords;
00353 #endif
00354 int slen = trans.length();
00355 int spos = 0;
00356 int tpos = trans.indexOf(plchar);
00357 while (tpos >= 0)
00358 {
00359 int ctpos = tpos;
00360
00361 tpos++;
00362 if (tpos == slen)
00363 break;
00364
00365 if (trans[tpos].digitValue() > 0)
00366 {
00367
00368 int plord = 0;
00369 while (tpos < slen && trans[tpos].digitValue() >= 0)
00370 {
00371 plord = 10 * plord + trans[tpos].digitValue();
00372 tpos++;
00373 }
00374 plord--;
00375
00376 #ifndef NDEBUG
00377
00378
00379
00380 if (plord >= ords.size())
00381 ords.resize(plord + 1);
00382
00383
00384 ords[plord] = 1;
00385 #endif
00386
00387
00388 tsegs.append(trans.mid(spos, ctpos - spos));
00389 plords.append(plord);
00390
00391
00392 spos = tpos;
00393 }
00394
00395 tpos = trans.indexOf(plchar, tpos);
00396 }
00397
00398 tsegs.append(trans.mid(spos));
00399
00400 #ifndef NDEBUG
00401
00402 if (!plural.isEmpty() && numberOrd >= ords.size())
00403 ords.resize(numberOrd + 1);
00404
00405
00406
00407
00408 if (!plural.isEmpty())
00409 ords[numberOrd] = 1;
00410 #endif
00411
00412
00413 QString final;
00414 for (int i = 0; i < plords.size(); i++)
00415 {
00416 final.append(tsegs.at(i));
00417 if (plords.at(i) >= args.size())
00418
00419 {
00420
00421 final.append('%' + QString::number(plords.at(i) + 1));
00422 #ifndef NDEBUG
00423 if (!partial)
00424
00425 final.append("(I18N_ARGUMENT_MISSING)");
00426 #endif
00427 }
00428 else
00429
00430 final.append(args.at(plords.at(i)));
00431 }
00432 final.append(tsegs.last());
00433
00434 #ifndef NDEBUG
00435 if (!partial)
00436 {
00437
00438 bool gaps = false;
00439 for (int i = 0; i < ords.size(); i++)
00440 if (!ords.at(i))
00441 {
00442 gaps = true;
00443 kDebug(173) << QString("Placeholder %%1 skipped in message {%2}.")
00444 .arg(QString::number(i + 1), shortenMessage(trans));
00445 }
00446
00447
00448 if (!gaps && ords.size() != args.size())
00449 kDebug(173) << QString("%1 instead of %2 arguments to message {%3} supplied before conversion.")
00450 .arg(args.size()).arg(ords.size()).arg(shortenMessage(trans));
00451
00452
00453 if (gaps)
00454 final.append("(I18N_GAPS_IN_PLACEHOLDER_SEQUENCE)");
00455 if (ords.size() < args.size())
00456 final.append("(I18N_EXCESS_ARGUMENTS_SUPPLIED)");
00457 if (!plural.isEmpty() && !numberSet)
00458 final.append("(I18N_PLURAL_ARGUMENT_MISSING)");
00459 }
00460 #endif
00461
00462 return final;
00463 }
00464
00465 QString KLocalizedStringPrivate::postFormat (const QString &text,
00466 const QString &lang,
00467 const QString &lscr,
00468 const QString &ctxt) const
00469 {
00470 KLocalizedStringPrivateStatics *s = staticsKLSP;
00471 QMutexLocker lock(&s->mutex);
00472
00473 QString final = text;
00474
00475
00476 if (s->formatters.contains(lang)) {
00477 final = s->formatters[lang]->format(final, ctxt);
00478 }
00479
00480
00481 if (s->translits.contains(lang)) {
00482 final = s->translits[lang]->transliterate(final, lscr);
00483 }
00484
00485 return final;
00486 }
00487
00488 QString KLocalizedStringPrivate::substituteTranscript (const QString &strans,
00489 const QString &lang,
00490 const QString &lscr,
00491 const QString &final,
00492 bool &fallback) const
00493 {
00494 KLocalizedStringPrivateStatics *s = staticsKLSP;
00495 QMutexLocker lock(&s->mutex);
00496
00497 if (s->ktrs == NULL)
00498
00499 return QString();
00500
00501
00502 QString sfinal;
00503 fallback = false;
00504 int ppos = 0;
00505 int tpos = strans.indexOf(s->startInterp);
00506 while (tpos >= 0)
00507 {
00508
00509 QString ptext = substituteSimple(strans.mid(ppos, tpos - ppos),
00510 s->scriptPlchar, true);
00511 sfinal.append(ptext);
00512
00513
00514 QString result;
00515 bool fallbackLocal;
00516 tpos = resolveInterpolation(strans, tpos, lang, lscr, final,
00517 result, fallbackLocal);
00518
00519
00520
00521 if (tpos < 0) {
00522 return QString();
00523 }
00524
00525
00526 if (fallbackLocal) {
00527 fallback = true;
00528 }
00529
00530
00531 sfinal.append(result);
00532
00533
00534 ppos = tpos;
00535 tpos = strans.indexOf(s->startInterp, tpos);
00536 }
00537
00538 sfinal.append(substituteSimple(strans.mid(ppos), s->scriptPlchar, true));
00539
00540
00541 return fallback ? QString() : sfinal;
00542 }
00543
00544 int KLocalizedStringPrivate::resolveInterpolation (const QString &strans,
00545 int pos,
00546 const QString &lang,
00547 const QString &lscr,
00548 const QString &final,
00549 QString &result,
00550 bool &fallback) const
00551 {
00552
00553
00554
00555
00556
00557
00558 KLocalizedStringPrivateStatics *s = staticsKLSP;
00559 QMutexLocker lock(&s->mutex);
00560
00561 result.clear();
00562 fallback = false;
00563
00564
00565 QList<QVariant> iargs;
00566 int slen = strans.length();
00567 int islen = s->startInterp.length();
00568 int ielen = s->endInterp.length();
00569 int tpos = pos + s->startInterp.length();
00570 while (1)
00571 {
00572
00573 while (tpos < slen && strans[tpos].isSpace()) {
00574 ++tpos;
00575 }
00576 if (tpos == slen) {
00577 kDebug(173) << QString("Unclosed interpolation {%1} in message {%2}.")
00578 .arg(strans.mid(pos, tpos - pos), shortenMessage(strans));
00579 return -1;
00580 }
00581 if (strans.mid(tpos, ielen) == s->endInterp) {
00582 break;
00583 }
00584
00585
00586
00587
00588
00589
00590
00591
00592 QStringList segs;
00593 QVariant vref;
00594 while ( !strans[tpos].isSpace()
00595 && strans.mid(tpos, ielen) != s->endInterp)
00596 {
00597 if (strans[tpos] == '\'') {
00598 QString seg;
00599 ++tpos;
00600
00601 while (tpos < slen && strans[tpos] != '\'') {
00602 if (strans[tpos] == '\\')
00603 ++tpos;
00604 seg.append(strans[tpos]);
00605 ++tpos;
00606 }
00607 if (tpos == slen) {
00608 kDebug(173) << QString("Unclosed quote in interpolation {%1} in message {%2}.")
00609 .arg(strans.mid(pos, tpos - pos), shortenMessage(strans));
00610 return -1;
00611 }
00612
00613
00614 segs.append(substituteSimple(seg, s->scriptPlchar, true));
00615
00616 ++tpos;
00617 }
00618 else if (strans.mid(tpos, islen) == s->startInterp) {
00619 QString resultLocal;
00620 bool fallbackLocal;
00621 tpos = resolveInterpolation(strans, tpos, lang, lscr, final,
00622 resultLocal, fallbackLocal);
00623 if (tpos < 0) {
00624
00625 return tpos;
00626 }
00627 if (fallbackLocal) {
00628 fallback = true;
00629 }
00630 segs.append(resultLocal);
00631 }
00632 else {
00633 QString seg;
00634
00635 while ( tpos < slen
00636 && !strans[tpos].isSpace() && strans[tpos] != '\''
00637 && strans.mid(tpos, islen) != s->startInterp
00638 && strans.mid(tpos, ielen) != s->endInterp)
00639 {
00640 if (strans[tpos] == '\\')
00641 ++tpos;
00642 seg.append(strans[tpos]);
00643 ++tpos;
00644 }
00645 if (tpos == slen) {
00646 kDebug(173) << QString("Non-terminated interpolation {%1} in message {%2}.")
00647 .arg(strans.mid(pos, tpos - pos), shortenMessage(strans));
00648 return -1;
00649 }
00650
00651
00652
00653
00654
00655 vref = segmentToValue(seg);
00656 if (vref.isValid()) {
00657 segs.append(seg);
00658 }
00659 else {
00660 segs.append(substituteSimple(seg, s->scriptPlchar, true));
00661 }
00662 }
00663 }
00664
00665
00666
00667
00668
00669 if (segs.size() == 1 && vref.isValid()) {
00670 iargs.append(vref);
00671 }
00672 else {
00673 iargs.append(segs.join(""));
00674 }
00675 }
00676 tpos += ielen;
00677
00678
00679
00680
00681
00682
00683
00684 QString msgctxt = QString::fromUtf8(ctxt);
00685 QString msgid = QString::fromUtf8(msg);
00686 QString scriptError;
00687 bool fallbackLocal;
00688 result = s->ktrs->eval(iargs, lang, lscr, msgctxt, dynctxt, msgid,
00689 args, vals, final, s->scriptModulesToLoad,
00690 scriptError, fallbackLocal);
00691
00692
00693 if (fallbackLocal) {
00694 fallback = true;
00695 }
00696 if (!scriptError.isEmpty()) {
00697 fallback = true;
00698 if (!scriptError.isEmpty()) {
00699 kDebug(173) << QString("Interpolation {%1} in {%2} failed: %3")
00700 .arg(strans.mid(pos, tpos - pos), shortenMessage(strans), scriptError);
00701 }
00702 }
00703
00704 return tpos;
00705 }
00706
00707 QVariant KLocalizedStringPrivate::segmentToValue (const QString &seg) const
00708 {
00709 KLocalizedStringPrivateStatics *s = staticsKLSP;
00710 QMutexLocker lock(&s->mutex);
00711
00712
00713
00714
00715
00716 if (seg.left(1) != s->scriptVachar) {
00717 return QVariant();
00718 }
00719
00720
00721
00722 QString numstr = seg.mid(1);
00723 if (numstr.left(1).toInt() < 1) {
00724 return QVariant();
00725 }
00726
00727
00728 bool ok;
00729 int index = numstr.toInt(&ok) - 1;
00730 if (!ok || index >= vals.size()) {
00731 return QVariant();
00732 }
00733
00734
00735 return vals.at(index);
00736 }
00737
00738 QString KLocalizedStringPrivate::postTranscript (const QString &pcall,
00739 const QString &lang,
00740 const QString &lscr,
00741 const QString &final) const
00742 {
00743 KLocalizedStringPrivateStatics *s = staticsKLSP;
00744 QMutexLocker lock(&s->mutex);
00745
00746 if (s->ktrs == NULL)
00747
00748
00749 return QString();
00750
00751
00752 QList<QVariant> iargs;
00753 iargs.append(pcall);
00754 QString msgctxt = QString::fromUtf8(ctxt);
00755 QString msgid = QString::fromUtf8(msg);
00756 QString scriptError;
00757 bool fallback;
00758 QString dummy = s->ktrs->eval(iargs, lang, lscr, msgctxt, dynctxt, msgid,
00759 args, vals, final, s->scriptModulesToLoad,
00760 scriptError, fallback);
00761
00762
00763
00764 if (!scriptError.isEmpty())
00765 {
00766 kDebug(173) << QString("Post call {%1} for message {%2} failed: %3")
00767 .arg(pcall, shortenMessage(msgid), scriptError);
00768 return QString();
00769 }
00770
00771 return final;
00772 }
00773
00774 static QString wrapInt (const QString &numstr)
00775 {
00776 return "<"KUIT_NUMINTG">" + numstr + "</"KUIT_NUMINTG">";
00777 }
00778
00779 static QString wrapReal (const QString &numstr)
00780 {
00781 return "<"KUIT_NUMREAL">" + numstr + "</"KUIT_NUMREAL">";
00782 }
00783
00784 KLocalizedString KLocalizedString::subs (int a, int fieldWidth, int base,
00785 const QChar &fillChar) const
00786 {
00787 if (!d->plural.isEmpty() && !d->numberSet)
00788 {
00789 d->number = static_cast<pluraln>(abs(a));
00790 d->numberSet = true;
00791 d->numberOrd = d->args.size();
00792 }
00793 KLocalizedString kls(*this);
00794 kls.d->args.append(wrapInt(QString("%1").arg(a, fieldWidth, base, fillChar)));
00795 kls.d->vals.append(static_cast<intn>(a));
00796 return kls;
00797 }
00798
00799 KLocalizedString KLocalizedString::subs (uint a, int fieldWidth, int base,
00800 const QChar &fillChar) const
00801 {
00802 if (!d->plural.isEmpty() && !d->numberSet)
00803 {
00804 d->number = static_cast<pluraln>(a);
00805 d->numberSet = true;
00806 d->numberOrd = d->args.size();
00807 }
00808 KLocalizedString kls(*this);
00809 kls.d->args.append(wrapInt(QString("%1").arg(a, fieldWidth, base, fillChar)));
00810 kls.d->vals.append(static_cast<uintn>(a));
00811 return kls;
00812 }
00813
00814 KLocalizedString KLocalizedString::subs (long a, int fieldWidth, int base,
00815 const QChar &fillChar) const
00816 {
00817 if (!d->plural.isEmpty() && !d->numberSet)
00818 {
00819 d->number = static_cast<pluraln>(abs(a));
00820 d->numberSet = true;
00821 d->numberOrd = d->args.size();
00822 }
00823 KLocalizedString kls(*this);
00824 kls.d->args.append(wrapInt(QString("%1").arg(a, fieldWidth, base, fillChar)));
00825 kls.d->vals.append(static_cast<intn>(a));
00826 return kls;
00827 }
00828
00829 KLocalizedString KLocalizedString::subs (ulong a, int fieldWidth, int base,
00830 const QChar &fillChar) const
00831 {
00832 if (!d->plural.isEmpty() && !d->numberSet)
00833 {
00834 d->number = static_cast<pluraln>(a);
00835 d->numberSet = true;
00836 d->numberOrd = d->args.size();
00837 }
00838 KLocalizedString kls(*this);
00839 kls.d->args.append(wrapInt(QString("%1").arg(a, fieldWidth, base, fillChar)));
00840 kls.d->vals.append(static_cast<uintn>(a));
00841 return kls;
00842 }
00843
00844 KLocalizedString KLocalizedString::subs (qlonglong a, int fieldWidth, int base,
00845 const QChar &fillChar) const
00846 {
00847 if (!d->plural.isEmpty() && !d->numberSet)
00848 {
00849 d->number = static_cast<pluraln>(qAbs(a));
00850 d->numberSet = true;
00851 d->numberOrd = d->args.size();
00852 }
00853 KLocalizedString kls(*this);
00854 kls.d->args.append(wrapInt(QString("%1").arg(a, fieldWidth, base, fillChar)));
00855 kls.d->vals.append(static_cast<intn>(a));
00856 return kls;
00857 }
00858
00859 KLocalizedString KLocalizedString::subs (qulonglong a, int fieldWidth, int base,
00860 const QChar &fillChar) const
00861 {
00862 if (!d->plural.isEmpty() && !d->numberSet)
00863 {
00864 d->number = static_cast<pluraln>(a);
00865 d->numberSet = true;
00866 d->numberOrd = d->args.size();
00867 }
00868 KLocalizedString kls(*this);
00869 kls.d->args.append(wrapInt(QString("%1").arg(a, fieldWidth, base, fillChar)));
00870 kls.d->vals.append(static_cast<uintn>(a));
00871 return kls;
00872 }
00873
00874 KLocalizedString KLocalizedString::subs (double a, int fieldWidth,
00875 char format, int precision,
00876 const QChar &fillChar) const
00877 {
00878 KLocalizedString kls(*this);
00879 kls.d->args.append(wrapReal(QString("%1").arg(a, fieldWidth, format, precision, fillChar)));
00880 kls.d->vals.append(static_cast<realn>(a));
00881 return kls;
00882 }
00883
00884 KLocalizedString KLocalizedString::subs (QChar a, int fieldWidth,
00885 const QChar &fillChar) const
00886 {
00887 KLocalizedString kls(*this);
00888 kls.d->args.append(QString("%1").arg(a, fieldWidth, fillChar));
00889 kls.d->vals.append(QString(a));
00890 return kls;
00891 }
00892
00893 KLocalizedString KLocalizedString::subs (const QString &a, int fieldWidth,
00894 const QChar &fillChar) const
00895 {
00896 KLocalizedString kls(*this);
00897
00898
00899
00900
00901 kls.d->args.append(QString("%1").arg(a, fieldWidth, fillChar));
00902 kls.d->vals.append(a);
00903 return kls;
00904 }
00905
00906 KLocalizedString KLocalizedString::inContext (const QString &key,
00907 const QString &text) const
00908 {
00909 KLocalizedString kls(*this);
00910 kls.d->dynctxt[key] = text;
00911 return kls;
00912 }
00913
00914 KLocalizedString ki18n (const char* msg)
00915 {
00916 return KLocalizedString(NULL, msg, NULL);
00917 }
00918
00919 KLocalizedString ki18nc (const char* ctxt, const char *msg)
00920 {
00921 return KLocalizedString(ctxt, msg, NULL);
00922 }
00923
00924 KLocalizedString ki18np (const char* singular, const char* plural)
00925 {
00926 return KLocalizedString(NULL, singular, plural);
00927 }
00928
00929 KLocalizedString ki18ncp (const char* ctxt,
00930 const char* singular, const char* plural)
00931 {
00932 return KLocalizedString(ctxt, singular, plural);
00933 }
00934
00935 extern "C"
00936 {
00937 typedef KTranscript *(*InitFunc)();
00938 }
00939
00940 void KLocalizedStringPrivate::loadTranscript ()
00941 {
00942 KLocalizedStringPrivateStatics *s = staticsKLSP;
00943 QMutexLocker lock(&s->mutex);
00944
00945 s->loadTranscriptCalled = true;
00946 s->ktrs = NULL;
00947
00948 KLibrary lib(QLatin1String("ktranscript"));
00949 if (!lib.load()) {
00950 kDebug(173) << "Cannot load transcript plugin:" << lib.errorString();
00951 return;
00952 }
00953
00954 InitFunc initf = (InitFunc) lib.resolveFunction("load_transcript");
00955 if (!initf) {
00956 lib.unload();
00957 kDebug(173) << "Cannot find function load_transcript in transcript plugin.";
00958 return;
00959 }
00960
00961 s->ktrs = initf();
00962 }
00963
00964 void KLocalizedString::notifyCatalogsUpdated (const QStringList &languages,
00965 const QList<KCatalogName> &catalogs)
00966 {
00967 KLocalizedStringPrivate::notifyCatalogsUpdated(languages, catalogs);
00968 }
00969
00970 void KLocalizedStringPrivate::notifyCatalogsUpdated (const QStringList &languages,
00971 const QList<KCatalogName> &catalogs)
00972 {
00973 if (staticsKLSP.isDestroyed()) {
00974 return;
00975 }
00976 KLocalizedStringPrivateStatics *s = staticsKLSP;
00977 QMutexLocker lock(&s->mutex);
00978
00979
00980
00981
00982
00983
00984 foreach (const QString &lang, languages) {
00985 for (int i = catalogs.size() - 1; i >= 0; --i) {
00986 const KCatalogName &cat(catalogs[i]);
00987
00988
00989 QString modrpath = lang + '/' + s->scriptDir + '/'
00990 + cat.name + '/' + cat.name + ".js";
00991
00992
00993 QString modapath = KStandardDirs::locate("locale", modrpath);
00994
00995
00996 if ( !modapath.isEmpty()
00997 && !s->scriptModules[lang].contains(cat.name))
00998 {
00999
01000 s->scriptModules[lang].append(cat.name);
01001
01002
01003
01004 QStringList mod;
01005 mod.append(modapath);
01006 mod.append(lang);
01007 s->scriptModulesToLoad.append(mod);
01008 }
01009 }
01010 }
01011
01012
01013 foreach (const QString &lang, languages) {
01014 if (!s->translits.contains(lang)) {
01015 KTranslit *t = KTranslit::create(lang);
01016 if (t != NULL) {
01017 s->translits.insert(lang, t);
01018 }
01019 }
01020 }
01021
01022
01023 foreach (const QString &lang, languages) {
01024 if (!s->formatters.contains(lang)) {
01025 s->formatters.insert(lang, new KuitSemantics(lang));
01026 }
01027 }
01028 }