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