1/*
2 SPDX-FileCopyrightText: 2013 Marco Martin <mart@kde.org>
3
4 SPDX-License-Identifier: LGPL-2.0-or-later
5*/
6
7// Undefine this because we don't want our i18n*() method names to be turned into i18nd*()
8#undef TRANSLATION_DOMAIN
9
10#include "klocalizedqmlcontext.h"
11
12#include <klocalizedstring.h>
13
14#include <QCoreApplication>
15#include <QQmlContext>
16#include <QQmlEngine>
17
18#include "ki18n_qml_logging.h"
19
20namespace
21{
22/*!
23 \internal
24 \brief Watches for QCoreApplication::languageChange() events and notifies
25 QML engines to re-evaluate their bindings.
26*/
27class LanguageChangeWatcher : public QObject
28{
29 Q_OBJECT
30public:
31 /*!
32 \brief Registers a QML engine to be notified on language change events.
33
34 \a engine The engine to notify.
35
36 If the engine is already registered, this is a no-op.
37 */
38 void hello(const QPointer<QQmlEngine> &engine)
39 {
40 Q_ASSERT(QThread::currentThread() == QCoreApplication::instance()->thread());
41 if (!engine) {
42 return;
43 }
44
45 if (!engines.contains(t: engine)) {
46 engines.push_back(t: engine);
47 qCDebug(KI18N) << "registered engine" << engine << "engines:" << engines;
48 }
49 }
50
51 bool eventFilter(QObject *watched, QEvent *event) override
52 {
53 if (event->type() == QEvent::LanguageChange && watched == QCoreApplication::instance()) {
54 // For simplicity we don't have Contexts say bye to us (would require refcounting).
55 // Instead we always make sure we only operate on living engines.
56 engines.removeIf(pred: [](const auto &engine) {
57 return !engine;
58 });
59 for (const auto &engine : std::as_const(t&: engines)) {
60 qCDebug(KI18N) << "triggering binding reevaluation for engine" << engine;
61 // run this deferred so we can be sure other things have reacted, such as KLocalizedString
62 // having updated its internal caches
63 QMetaObject::invokeMethod(object: engine, function: &QQmlEngine::retranslate, type: Qt::QueuedConnection);
64 }
65 }
66 return QObject::eventFilter(watched, event);
67 }
68
69private:
70 QList<QPointer<QQmlEngine>> engines;
71};
72
73LanguageChangeWatcher s_watcher;
74} // namespace
75
76class KLocalizedQmlContextPrivate
77{
78public:
79 void markCurrentFunctionAsTranslationBinding(const KLocalizedQmlContext *q) const;
80
81 QString m_translationDomain;
82};
83
84void KLocalizedQmlContextPrivate::markCurrentFunctionAsTranslationBinding(const KLocalizedQmlContext *q) const
85{
86 if (auto engine = qmlEngine(q); engine) {
87 engine->markCurrentFunctionAsTranslationBinding();
88 } else {
89 qCDebug(KI18N) << "No QML engine available, KLocalizedQmlContext not properly set up?";
90 }
91}
92
93KLocalizedQmlContext::KLocalizedQmlContext(QObject *parent)
94 : QObject(parent)
95 , d(new KLocalizedQmlContextPrivate)
96{
97 static bool filtered = [] {
98 QCoreApplication::instance()->installEventFilter(filterObj: &s_watcher);
99 return true;
100 }();
101 Q_UNUSED(filtered);
102
103 auto engine = qmlEngine(this);
104 s_watcher.hello(engine: engine ? engine : qobject_cast<QQmlEngine *>(object: parent) /* the global context has the engine as parent */);
105}
106
107KLocalizedQmlContext::~KLocalizedQmlContext() = default;
108
109QString KLocalizedQmlContext::translationDomain() const
110{
111 return d->m_translationDomain;
112}
113
114void KLocalizedQmlContext::setTranslationDomain(const QString &domain)
115{
116 if (domain != d->m_translationDomain) {
117 d->m_translationDomain = domain;
118 Q_EMIT translationDomainChanged(translationDomain: domain);
119 }
120}
121
122static void subsVariant(KLocalizedString &trMessage, const QVariant &value)
123{
124 switch (value.userType()) {
125 case QMetaType::QString:
126 trMessage = trMessage.subs(a: value.toString());
127 break;
128 case QMetaType::Int:
129 trMessage = trMessage.subs(a: value.toInt());
130 break;
131 case QMetaType::Double:
132 trMessage = trMessage.subs(a: value.toDouble());
133 break;
134 case QMetaType::Char:
135 trMessage = trMessage.subs(a: value.toChar());
136 break;
137 default:
138 if (value.canConvert<QString>()) {
139 trMessage = trMessage.subs(a: value.toString());
140 } else {
141 trMessage = trMessage.subs(QStringLiteral("???"));
142 qCWarning(KI18N) << "couldn't convert" << value << "to translate";
143 }
144 }
145}
146
147static void resolveMessage(KLocalizedString &trMessage,
148 const QVariant &param1,
149 const QVariant &param2,
150 const QVariant &param3,
151 const QVariant &param4,
152 const QVariant &param5,
153 const QVariant &param6,
154 const QVariant &param7,
155 const QVariant &param8,
156 const QVariant &param9,
157 const QVariant &param10 = QVariant())
158{
159 if (param1.isValid()) {
160 subsVariant(trMessage, value: param1);
161 }
162 if (param2.isValid()) {
163 subsVariant(trMessage, value: param2);
164 }
165 if (param3.isValid()) {
166 subsVariant(trMessage, value: param3);
167 }
168 if (param4.isValid()) {
169 subsVariant(trMessage, value: param4);
170 }
171 if (param5.isValid()) {
172 subsVariant(trMessage, value: param5);
173 }
174 if (param6.isValid()) {
175 subsVariant(trMessage, value: param6);
176 }
177 if (param7.isValid()) {
178 subsVariant(trMessage, value: param7);
179 }
180 if (param8.isValid()) {
181 subsVariant(trMessage, value: param8);
182 }
183 if (param9.isValid()) {
184 subsVariant(trMessage, value: param9);
185 }
186 if (param10.isValid()) {
187 subsVariant(trMessage, value: param10);
188 }
189}
190
191static void resolvePlural(KLocalizedString &trMessage, const QVariant &param)
192{
193 trMessage = trMessage.subs(a: param.toInt());
194}
195
196QString KLocalizedQmlContext::i18n(const QString &message,
197 const QVariant &param1,
198 const QVariant &param2,
199 const QVariant &param3,
200 const QVariant &param4,
201 const QVariant &param5,
202 const QVariant &param6,
203 const QVariant &param7,
204 const QVariant &param8,
205 const QVariant &param9,
206 const QVariant &param10) const
207{
208 if (message.isEmpty()) {
209 qCWarning(KI18N) << "i18n() needs at least one parameter";
210 return QString();
211 }
212
213 KLocalizedString trMessage;
214 if (!d->m_translationDomain.isEmpty()) {
215 trMessage = ki18nd(domain: d->m_translationDomain.toUtf8().constData(), text: message.toUtf8().constData());
216 } else {
217 trMessage = ki18n(text: message.toUtf8().constData());
218 }
219
220 resolveMessage(trMessage, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10);
221
222 d->markCurrentFunctionAsTranslationBinding(q: this);
223 return trMessage.toString();
224}
225
226QString KLocalizedQmlContext::i18nc(const QString &context,
227 const QString &message,
228 const QVariant &param1,
229 const QVariant &param2,
230 const QVariant &param3,
231 const QVariant &param4,
232 const QVariant &param5,
233 const QVariant &param6,
234 const QVariant &param7,
235 const QVariant &param8,
236 const QVariant &param9,
237 const QVariant &param10) const
238{
239 if (context.isEmpty() || message.isEmpty()) {
240 qCWarning(KI18N).noquote().nospace() << "i18nc(\"" << context << message << "\") needs at least two arguments";
241 return QString();
242 }
243
244 KLocalizedString trMessage;
245 if (!d->m_translationDomain.isEmpty()) {
246 trMessage = ki18ndc(domain: d->m_translationDomain.toUtf8().constData(), context: context.toUtf8().constData(), text: message.toUtf8().constData());
247 } else {
248 trMessage = ki18nc(context: context.toUtf8().constData(), text: message.toUtf8().constData());
249 }
250
251 resolveMessage(trMessage, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10);
252
253 d->markCurrentFunctionAsTranslationBinding(q: this);
254 return trMessage.toString();
255}
256
257QString KLocalizedQmlContext::i18np(const QString &singular,
258 const QString &plural,
259 const QVariant &param1,
260 const QVariant &param2,
261 const QVariant &param3,
262 const QVariant &param4,
263 const QVariant &param5,
264 const QVariant &param6,
265 const QVariant &param7,
266 const QVariant &param8,
267 const QVariant &param9,
268 const QVariant &param10) const
269{
270 if (singular.isEmpty() || plural.isEmpty()) {
271 qCWarning(KI18N).noquote().nospace() << "i18np(\"" << singular << plural << "\") needs at least two arguments";
272 return QString();
273 }
274
275 KLocalizedString trMessage;
276 if (!d->m_translationDomain.isEmpty()) {
277 trMessage = ki18ndp(domain: d->m_translationDomain.toUtf8().constData(), singular: singular.toUtf8().constData(), plural: plural.toUtf8().constData());
278 } else {
279 trMessage = ki18np(singular: singular.toUtf8().constData(), plural: plural.toUtf8().constData());
280 }
281
282 resolvePlural(trMessage, param: param1);
283 resolveMessage(trMessage, param1: param2, param2: param3, param3: param4, param4: param5, param5: param6, param6: param7, param7: param8, param8: param9, param9: param10);
284
285 d->markCurrentFunctionAsTranslationBinding(q: this);
286 return trMessage.toString();
287}
288
289QString KLocalizedQmlContext::i18ncp(const QString &context,
290 const QString &singular,
291 const QString &plural,
292 const QVariant &param1,
293 const QVariant &param2,
294 const QVariant &param3,
295 const QVariant &param4,
296 const QVariant &param5,
297 const QVariant &param6,
298 const QVariant &param7,
299 const QVariant &param8,
300 const QVariant &param9,
301 const QVariant &param10) const
302{
303 if (context.isEmpty() || singular.isEmpty() || plural.isEmpty()) {
304 qCWarning(KI18N) << "i18ncp() needs at least three arguments";
305 return QString();
306 }
307
308 KLocalizedString trMessage;
309 if (!d->m_translationDomain.isEmpty()) {
310 trMessage =
311 ki18ndcp(domain: d->m_translationDomain.toUtf8().constData(), context: context.toUtf8().constData(), singular: singular.toUtf8().constData(), plural: plural.toUtf8().constData());
312 } else {
313 trMessage = ki18ncp(context: context.toUtf8().constData(), singular: singular.toUtf8().constData(), plural: plural.toUtf8().constData());
314 }
315
316 resolvePlural(trMessage, param: param1);
317 resolveMessage(trMessage, param1: param2, param2: param3, param3: param4, param4: param5, param5: param6, param6: param7, param7: param8, param8: param9, param9: param10);
318
319 d->markCurrentFunctionAsTranslationBinding(q: this);
320 return trMessage.toString();
321}
322
323QString KLocalizedQmlContext::i18nd(const QString &domain,
324 const QString &message,
325 const QVariant &param1,
326 const QVariant &param2,
327 const QVariant &param3,
328 const QVariant &param4,
329 const QVariant &param5,
330 const QVariant &param6,
331 const QVariant &param7,
332 const QVariant &param8,
333 const QVariant &param9,
334 const QVariant &param10) const
335{
336 if (domain.isEmpty() || message.isEmpty()) {
337 qCWarning(KI18N).noquote().nospace() << "i18nd(\"" << domain << message << "\") needs at least two parameters";
338 return QString();
339 }
340
341 KLocalizedString trMessage = ki18nd(domain: domain.toUtf8().constData(), text: message.toUtf8().constData());
342
343 resolveMessage(trMessage, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10);
344
345 d->markCurrentFunctionAsTranslationBinding(q: this);
346 return trMessage.toString();
347}
348
349QString KLocalizedQmlContext::i18ndc(const QString &domain,
350 const QString &context,
351 const QString &message,
352 const QVariant &param1,
353 const QVariant &param2,
354 const QVariant &param3,
355 const QVariant &param4,
356 const QVariant &param5,
357 const QVariant &param6,
358 const QVariant &param7,
359 const QVariant &param8,
360 const QVariant &param9,
361 const QVariant &param10) const
362{
363 if (domain.isEmpty() || context.isEmpty() || message.isEmpty()) {
364 qCWarning(KI18N) << "i18ndc() needs at least three arguments";
365 return QString();
366 }
367
368 KLocalizedString trMessage = ki18ndc(domain: domain.toUtf8().constData(), context: context.toUtf8().constData(), text: message.toUtf8().constData());
369
370 resolveMessage(trMessage, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10);
371
372 d->markCurrentFunctionAsTranslationBinding(q: this);
373 return trMessage.toString();
374}
375
376QString KLocalizedQmlContext::i18ndp(const QString &domain,
377 const QString &singular,
378 const QString &plural,
379 const QVariant &param1,
380 const QVariant &param2,
381 const QVariant &param3,
382 const QVariant &param4,
383 const QVariant &param5,
384 const QVariant &param6,
385 const QVariant &param7,
386 const QVariant &param8,
387 const QVariant &param9,
388 const QVariant &param10) const
389{
390 if (domain.isEmpty() || singular.isEmpty() || plural.isEmpty()) {
391 qCWarning(KI18N) << "i18ndp() needs at least three arguments";
392 return QString();
393 }
394
395 KLocalizedString trMessage = ki18ndp(domain: domain.toUtf8().constData(), singular: singular.toUtf8().constData(), plural: plural.toUtf8().constData());
396
397 resolvePlural(trMessage, param: param1);
398 resolveMessage(trMessage, param1: param2, param2: param3, param3: param4, param4: param5, param5: param6, param6: param7, param7: param8, param8: param9, param9: param10);
399
400 d->markCurrentFunctionAsTranslationBinding(q: this);
401 return trMessage.toString();
402}
403
404QString KLocalizedQmlContext::i18ndcp(const QString &domain,
405 const QString &context,
406 const QString &singular,
407 const QString &plural,
408 const QVariant &param1,
409 const QVariant &param2,
410 const QVariant &param3,
411 const QVariant &param4,
412 const QVariant &param5,
413 const QVariant &param6,
414 const QVariant &param7,
415 const QVariant &param8,
416 const QVariant &param9,
417 const QVariant &param10) const
418{
419 if (domain.isEmpty() || context.isEmpty() || singular.isEmpty() || plural.isEmpty()) {
420 qCWarning(KI18N) << "i18ndcp() needs at least four arguments";
421 return QString();
422 }
423
424 KLocalizedString trMessage =
425 ki18ndcp(domain: domain.toUtf8().constData(), context: context.toUtf8().constData(), singular: singular.toUtf8().constData(), plural: plural.toUtf8().constData());
426
427 resolvePlural(trMessage, param: param1);
428 resolveMessage(trMessage, param1: param2, param2: param3, param3: param4, param4: param5, param5: param6, param6: param7, param7: param8, param8: param9, param9: param10);
429
430 d->markCurrentFunctionAsTranslationBinding(q: this);
431 return trMessage.toString();
432}
433
434/////////////////////////
435
436QString KLocalizedQmlContext::xi18n(const QString &message,
437 const QVariant &param1,
438 const QVariant &param2,
439 const QVariant &param3,
440 const QVariant &param4,
441 const QVariant &param5,
442 const QVariant &param6,
443 const QVariant &param7,
444 const QVariant &param8,
445 const QVariant &param9,
446 const QVariant &param10) const
447{
448 if (message.isEmpty()) {
449 qCWarning(KI18N) << "xi18n() needs at least one parameter";
450 return QString();
451 }
452
453 KLocalizedString trMessage;
454 if (!d->m_translationDomain.isEmpty()) {
455 trMessage = kxi18nd(domain: d->m_translationDomain.toUtf8().constData(), text: message.toUtf8().constData());
456 } else {
457 trMessage = kxi18n(text: message.toUtf8().constData());
458 }
459
460 resolveMessage(trMessage, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10);
461
462 d->markCurrentFunctionAsTranslationBinding(q: this);
463 return trMessage.toString();
464}
465
466QString KLocalizedQmlContext::xi18nc(const QString &context,
467 const QString &message,
468 const QVariant &param1,
469 const QVariant &param2,
470 const QVariant &param3,
471 const QVariant &param4,
472 const QVariant &param5,
473 const QVariant &param6,
474 const QVariant &param7,
475 const QVariant &param8,
476 const QVariant &param9,
477 const QVariant &param10) const
478{
479 if (context.isEmpty() || message.isEmpty()) {
480 qCWarning(KI18N).noquote().nospace() << "xi18nc(\"" << context << message << "\") needs at least two arguments";
481 return QString();
482 }
483
484 KLocalizedString trMessage;
485 if (!d->m_translationDomain.isEmpty()) {
486 trMessage = kxi18ndc(domain: d->m_translationDomain.toUtf8().constData(), context: context.toUtf8().constData(), text: message.toUtf8().constData());
487 } else {
488 trMessage = kxi18nc(context: context.toUtf8().constData(), text: message.toUtf8().constData());
489 }
490
491 resolveMessage(trMessage, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10);
492
493 d->markCurrentFunctionAsTranslationBinding(q: this);
494 return trMessage.toString();
495}
496
497QString KLocalizedQmlContext::xi18np(const QString &singular,
498 const QString &plural,
499 const QVariant &param1,
500 const QVariant &param2,
501 const QVariant &param3,
502 const QVariant &param4,
503 const QVariant &param5,
504 const QVariant &param6,
505 const QVariant &param7,
506 const QVariant &param8,
507 const QVariant &param9,
508 const QVariant &param10) const
509{
510 if (singular.isEmpty() || plural.isEmpty()) {
511 qCWarning(KI18N).noquote().nospace() << "xi18np(\"" << singular << plural << "\") needs at least two arguments";
512 return QString();
513 }
514
515 KLocalizedString trMessage;
516 if (!d->m_translationDomain.isEmpty()) {
517 trMessage = kxi18ndp(domain: d->m_translationDomain.toUtf8().constData(), singular: singular.toUtf8().constData(), plural: plural.toUtf8().constData());
518 } else {
519 trMessage = kxi18np(singular: singular.toUtf8().constData(), plural: plural.toUtf8().constData());
520 }
521
522 resolvePlural(trMessage, param: param1);
523 resolveMessage(trMessage, param1: param2, param2: param3, param3: param4, param4: param5, param5: param6, param6: param7, param7: param8, param8: param9, param9: param10);
524
525 d->markCurrentFunctionAsTranslationBinding(q: this);
526 return trMessage.toString();
527}
528
529QString KLocalizedQmlContext::xi18ncp(const QString &context,
530 const QString &singular,
531 const QString &plural,
532 const QVariant &param1,
533 const QVariant &param2,
534 const QVariant &param3,
535 const QVariant &param4,
536 const QVariant &param5,
537 const QVariant &param6,
538 const QVariant &param7,
539 const QVariant &param8,
540 const QVariant &param9,
541 const QVariant &param10) const
542{
543 if (context.isEmpty() || singular.isEmpty() || plural.isEmpty()) {
544 qCWarning(KI18N) << "xi18ncp() needs at least three arguments";
545 return QString();
546 }
547
548 KLocalizedString trMessage;
549 if (!d->m_translationDomain.isEmpty()) {
550 trMessage =
551 kxi18ndcp(domain: d->m_translationDomain.toUtf8().constData(), context: context.toUtf8().constData(), singular: singular.toUtf8().constData(), plural: plural.toUtf8().constData());
552 } else {
553 trMessage = kxi18ncp(context: context.toUtf8().constData(), singular: singular.toUtf8().constData(), plural: plural.toUtf8().constData());
554 }
555
556 resolvePlural(trMessage, param: param1);
557 resolveMessage(trMessage, param1: param2, param2: param3, param3: param4, param4: param5, param5: param6, param6: param7, param7: param8, param8: param9, param9: param10);
558
559 d->markCurrentFunctionAsTranslationBinding(q: this);
560 return trMessage.toString();
561}
562
563QString KLocalizedQmlContext::xi18nd(const QString &domain,
564 const QString &message,
565 const QVariant &param1,
566 const QVariant &param2,
567 const QVariant &param3,
568 const QVariant &param4,
569 const QVariant &param5,
570 const QVariant &param6,
571 const QVariant &param7,
572 const QVariant &param8,
573 const QVariant &param9,
574 const QVariant &param10) const
575{
576 if (domain.isEmpty() || message.isEmpty()) {
577 qCWarning(KI18N).noquote().nospace() << "xi18nd(\"" << domain << message << "\") needs at least two parameters";
578 return QString();
579 }
580
581 KLocalizedString trMessage = kxi18nd(domain: domain.toUtf8().constData(), text: message.toUtf8().constData());
582
583 resolveMessage(trMessage, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10);
584
585 d->markCurrentFunctionAsTranslationBinding(q: this);
586 return trMessage.toString();
587}
588
589QString KLocalizedQmlContext::xi18ndc(const QString &domain,
590 const QString &context,
591 const QString &message,
592 const QVariant &param1,
593 const QVariant &param2,
594 const QVariant &param3,
595 const QVariant &param4,
596 const QVariant &param5,
597 const QVariant &param6,
598 const QVariant &param7,
599 const QVariant &param8,
600 const QVariant &param9,
601 const QVariant &param10) const
602{
603 if (domain.isEmpty() || context.isEmpty() || message.isEmpty()) {
604 qCWarning(KI18N) << "x18ndc() needs at least three arguments";
605 return QString();
606 }
607
608 KLocalizedString trMessage = kxi18ndc(domain: domain.toUtf8().constData(), context: context.toUtf8().constData(), text: message.toUtf8().constData());
609
610 resolveMessage(trMessage, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10);
611
612 d->markCurrentFunctionAsTranslationBinding(q: this);
613 return trMessage.toString();
614}
615
616QString KLocalizedQmlContext::xi18ndp(const QString &domain,
617 const QString &singular,
618 const QString &plural,
619 const QVariant &param1,
620 const QVariant &param2,
621 const QVariant &param3,
622 const QVariant &param4,
623 const QVariant &param5,
624 const QVariant &param6,
625 const QVariant &param7,
626 const QVariant &param8,
627 const QVariant &param9,
628 const QVariant &param10) const
629{
630 if (domain.isEmpty() || singular.isEmpty() || plural.isEmpty()) {
631 qCWarning(KI18N) << "xi18ndp() needs at least three arguments";
632 return QString();
633 }
634
635 KLocalizedString trMessage = kxi18ndp(domain: domain.toUtf8().constData(), singular: singular.toUtf8().constData(), plural: plural.toUtf8().constData());
636
637 resolvePlural(trMessage, param: param1);
638 resolveMessage(trMessage, param1: param2, param2: param3, param3: param4, param4: param5, param5: param6, param6: param7, param7: param8, param8: param9, param9: param10);
639
640 d->markCurrentFunctionAsTranslationBinding(q: this);
641 return trMessage.toString();
642}
643
644QString KLocalizedQmlContext::xi18ndcp(const QString &domain,
645 const QString &context,
646 const QString &singular,
647 const QString &plural,
648 const QVariant &param1,
649 const QVariant &param2,
650 const QVariant &param3,
651 const QVariant &param4,
652 const QVariant &param5,
653 const QVariant &param6,
654 const QVariant &param7,
655 const QVariant &param8,
656 const QVariant &param9,
657 const QVariant &param10) const
658{
659 if (domain.isEmpty() || context.isEmpty() || singular.isEmpty() || plural.isEmpty()) {
660 qCWarning(KI18N) << "xi18ndcp() needs at least four arguments";
661 return QString();
662 }
663
664 KLocalizedString trMessage =
665 kxi18ndcp(domain: domain.toUtf8().constData(), context: context.toUtf8().constData(), singular: singular.toUtf8().constData(), plural: plural.toUtf8().constData());
666
667 resolvePlural(trMessage, param: param1);
668 resolveMessage(trMessage, param1: param2, param2: param3, param3: param4, param4: param5, param5: param6, param6: param7, param7: param8, param8: param9, param9: param10);
669
670 d->markCurrentFunctionAsTranslationBinding(q: this);
671 return trMessage.toString();
672}
673
674KLocalizedQmlContext *KLocalization::Internal::createLocalizedContext(QQmlEngine *engine)
675{
676 auto ctx = new KLocalizedQmlContext(engine);
677 engine->rootContext()->setContextObject(ctx);
678 QQmlEngine::setContextForObject(ctx, engine->rootContext());
679 return ctx;
680}
681
682#include "klocalizedqmlcontext.moc"
683#include "moc_klocalizedqmlcontext.cpp"
684

source code of ki18n/src/i18n-qml/klocalizedqmlcontext.cpp