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