KI18n

klocalizedqmlcontext.cpp
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
20class KLocalizedQmlContextPrivate
21{
22public:
23 void markCurrentFunctionAsTranslationBinding(const KLocalizedQmlContext *q) const;
24
25 QString m_translationDomain;
26};
27
28void KLocalizedQmlContextPrivate::markCurrentFunctionAsTranslationBinding(const KLocalizedQmlContext *q) const
29{
30 if (auto engine = qmlEngine(q); engine) {
31 engine->markCurrentFunctionAsTranslationBinding();
32 } else {
33 qCDebug(KI18N) << "No QML engine available, KLocalizedQmlContext not properly set up?";
34 }
35}
36
37KLocalizedQmlContext::KLocalizedQmlContext(QObject *parent)
38 : QObject(parent)
39 , d(new KLocalizedQmlContextPrivate)
40{
42}
43
44KLocalizedQmlContext::~KLocalizedQmlContext() = default;
45
47{
48 return d->m_translationDomain;
49}
50
51void KLocalizedQmlContext::setTranslationDomain(const QString &domain)
52{
53 if (domain != d->m_translationDomain) {
54 d->m_translationDomain = domain;
55 Q_EMIT translationDomainChanged(domain);
56 }
57}
58
59static void subsVariant(KLocalizedString &trMessage, const QVariant &value)
60{
61 switch (value.userType()) {
63 trMessage = trMessage.subs(value.toString());
64 break;
65 case QMetaType::Int:
66 trMessage = trMessage.subs(value.toInt());
67 break;
69 trMessage = trMessage.subs(value.toDouble());
70 break;
71 case QMetaType::Char:
72 trMessage = trMessage.subs(value.toChar());
73 break;
74 default:
75 if (value.canConvert<QString>()) {
76 trMessage = trMessage.subs(value.toString());
77 } else {
78 trMessage = trMessage.subs(QStringLiteral("???"));
79 qCWarning(KI18N) << "couldn't convert" << value << "to translate";
80 }
81 }
82}
83
84static void resolveMessage(KLocalizedString &trMessage,
85 const QVariant &param1,
86 const QVariant &param2,
87 const QVariant &param3,
88 const QVariant &param4,
89 const QVariant &param5,
90 const QVariant &param6,
91 const QVariant &param7,
92 const QVariant &param8,
93 const QVariant &param9,
94 const QVariant &param10 = QVariant())
95{
96 if (param1.isValid()) {
97 subsVariant(trMessage, param1);
98 }
99 if (param2.isValid()) {
100 subsVariant(trMessage, param2);
101 }
102 if (param3.isValid()) {
103 subsVariant(trMessage, param3);
104 }
105 if (param4.isValid()) {
106 subsVariant(trMessage, param4);
107 }
108 if (param5.isValid()) {
109 subsVariant(trMessage, param5);
110 }
111 if (param6.isValid()) {
112 subsVariant(trMessage, param6);
113 }
114 if (param7.isValid()) {
115 subsVariant(trMessage, param7);
116 }
117 if (param8.isValid()) {
118 subsVariant(trMessage, param8);
119 }
120 if (param9.isValid()) {
121 subsVariant(trMessage, param9);
122 }
123 if (param10.isValid()) {
124 subsVariant(trMessage, param10);
125 }
126}
127
128static void resolvePlural(KLocalizedString &trMessage, const QVariant &param)
129{
130 trMessage = trMessage.subs(param.toInt());
131}
132
133QString KLocalizedQmlContext::i18n(const QString &message,
134 const QVariant &param1,
135 const QVariant &param2,
136 const QVariant &param3,
137 const QVariant &param4,
138 const QVariant &param5,
139 const QVariant &param6,
140 const QVariant &param7,
141 const QVariant &param8,
142 const QVariant &param9,
143 const QVariant &param10) const
144{
145 if (message.isEmpty()) {
146 qCWarning(KI18N) << "i18n() needs at least one parameter";
147 return QString();
148 }
149
150 KLocalizedString trMessage;
151 if (!d->m_translationDomain.isEmpty()) {
152 trMessage = ki18nd(d->m_translationDomain.toUtf8().constData(), message.toUtf8().constData());
153 } else {
154 trMessage = ki18n(message.toUtf8().constData());
155 }
156
157 resolveMessage(trMessage, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10);
158
159 d->markCurrentFunctionAsTranslationBinding(this);
160 return trMessage.toString();
161}
162
163QString KLocalizedQmlContext::i18nc(const QString &context,
164 const QString &message,
165 const QVariant &param1,
166 const QVariant &param2,
167 const QVariant &param3,
168 const QVariant &param4,
169 const QVariant &param5,
170 const QVariant &param6,
171 const QVariant &param7,
172 const QVariant &param8,
173 const QVariant &param9,
174 const QVariant &param10) const
175{
176 if (context.isEmpty() || message.isEmpty()) {
177 qCWarning(KI18N).noquote().nospace() << "i18nc(\"" << context << message << "\") needs at least two arguments";
178 return QString();
179 }
180
181 KLocalizedString trMessage;
182 if (!d->m_translationDomain.isEmpty()) {
183 trMessage = ki18ndc(d->m_translationDomain.toUtf8().constData(), context.toUtf8().constData(), message.toUtf8().constData());
184 } else {
185 trMessage = ki18nc(context.toUtf8().constData(), message.toUtf8().constData());
186 }
187
188 resolveMessage(trMessage, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10);
189
190 d->markCurrentFunctionAsTranslationBinding(this);
191 return trMessage.toString();
192}
193
194QString KLocalizedQmlContext::i18np(const QString &singular,
195 const QString &plural,
196 const QVariant &param1,
197 const QVariant &param2,
198 const QVariant &param3,
199 const QVariant &param4,
200 const QVariant &param5,
201 const QVariant &param6,
202 const QVariant &param7,
203 const QVariant &param8,
204 const QVariant &param9,
205 const QVariant &param10) const
206{
207 if (singular.isEmpty() || plural.isEmpty()) {
208 qCWarning(KI18N).noquote().nospace() << "i18np(\"" << singular << plural << "\") needs at least two arguments";
209 return QString();
210 }
211
212 KLocalizedString trMessage;
213 if (!d->m_translationDomain.isEmpty()) {
214 trMessage = ki18ndp(d->m_translationDomain.toUtf8().constData(), singular.toUtf8().constData(), plural.toUtf8().constData());
215 } else {
216 trMessage = ki18np(singular.toUtf8().constData(), plural.toUtf8().constData());
217 }
218
219 resolvePlural(trMessage, param1);
220 resolveMessage(trMessage, param2, param3, param4, param5, param6, param7, param8, param9, param10);
221
222 d->markCurrentFunctionAsTranslationBinding(this);
223 return trMessage.toString();
224}
225
226QString KLocalizedQmlContext::i18ncp(const QString &context,
227 const QString &singular,
228 const QString &plural,
229 const QVariant &param1,
230 const QVariant &param2,
231 const QVariant &param3,
232 const QVariant &param4,
233 const QVariant &param5,
234 const QVariant &param6,
235 const QVariant &param7,
236 const QVariant &param8,
237 const QVariant &param9,
238 const QVariant &param10) const
239{
240 if (context.isEmpty() || singular.isEmpty() || plural.isEmpty()) {
241 qCWarning(KI18N) << "i18ncp() needs at least three arguments";
242 return QString();
243 }
244
245 KLocalizedString trMessage;
246 if (!d->m_translationDomain.isEmpty()) {
247 trMessage =
248 ki18ndcp(d->m_translationDomain.toUtf8().constData(), context.toUtf8().constData(), singular.toUtf8().constData(), plural.toUtf8().constData());
249 } else {
250 trMessage = ki18ncp(context.toUtf8().constData(), singular.toUtf8().constData(), plural.toUtf8().constData());
251 }
252
253 resolvePlural(trMessage, param1);
254 resolveMessage(trMessage, param2, param3, param4, param5, param6, param7, param8, param9, param10);
255
256 d->markCurrentFunctionAsTranslationBinding(this);
257 return trMessage.toString();
258}
259
260QString KLocalizedQmlContext::i18nd(const QString &domain,
261 const QString &message,
262 const QVariant &param1,
263 const QVariant &param2,
264 const QVariant &param3,
265 const QVariant &param4,
266 const QVariant &param5,
267 const QVariant &param6,
268 const QVariant &param7,
269 const QVariant &param8,
270 const QVariant &param9,
271 const QVariant &param10) const
272{
273 if (domain.isEmpty() || message.isEmpty()) {
274 qCWarning(KI18N).noquote().nospace() << "i18nd(\"" << domain << message << "\") needs at least two parameters";
275 return QString();
276 }
277
278 KLocalizedString trMessage = ki18nd(domain.toUtf8().constData(), message.toUtf8().constData());
279
280 resolveMessage(trMessage, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10);
281
282 d->markCurrentFunctionAsTranslationBinding(this);
283 return trMessage.toString();
284}
285
286QString KLocalizedQmlContext::i18ndc(const QString &domain,
287 const QString &context,
288 const QString &message,
289 const QVariant &param1,
290 const QVariant &param2,
291 const QVariant &param3,
292 const QVariant &param4,
293 const QVariant &param5,
294 const QVariant &param6,
295 const QVariant &param7,
296 const QVariant &param8,
297 const QVariant &param9,
298 const QVariant &param10) const
299{
300 if (domain.isEmpty() || context.isEmpty() || message.isEmpty()) {
301 qCWarning(KI18N) << "i18ndc() needs at least three arguments";
302 return QString();
303 }
304
305 KLocalizedString trMessage = ki18ndc(domain.toUtf8().constData(), context.toUtf8().constData(), message.toUtf8().constData());
306
307 resolveMessage(trMessage, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10);
308
309 d->markCurrentFunctionAsTranslationBinding(this);
310 return trMessage.toString();
311}
312
313QString KLocalizedQmlContext::i18ndp(const QString &domain,
314 const QString &singular,
315 const QString &plural,
316 const QVariant &param1,
317 const QVariant &param2,
318 const QVariant &param3,
319 const QVariant &param4,
320 const QVariant &param5,
321 const QVariant &param6,
322 const QVariant &param7,
323 const QVariant &param8,
324 const QVariant &param9,
325 const QVariant &param10) const
326{
327 if (domain.isEmpty() || singular.isEmpty() || plural.isEmpty()) {
328 qCWarning(KI18N) << "i18ndp() needs at least three arguments";
329 return QString();
330 }
331
332 KLocalizedString trMessage = ki18ndp(domain.toUtf8().constData(), singular.toUtf8().constData(), plural.toUtf8().constData());
333
334 resolvePlural(trMessage, param1);
335 resolveMessage(trMessage, param2, param3, param4, param5, param6, param7, param8, param9, param10);
336
337 d->markCurrentFunctionAsTranslationBinding(this);
338 return trMessage.toString();
339}
340
341QString KLocalizedQmlContext::i18ndcp(const QString &domain,
342 const QString &context,
343 const QString &singular,
344 const QString &plural,
345 const QVariant &param1,
346 const QVariant &param2,
347 const QVariant &param3,
348 const QVariant &param4,
349 const QVariant &param5,
350 const QVariant &param6,
351 const QVariant &param7,
352 const QVariant &param8,
353 const QVariant &param9,
354 const QVariant &param10) const
355{
356 if (domain.isEmpty() || context.isEmpty() || singular.isEmpty() || plural.isEmpty()) {
357 qCWarning(KI18N) << "i18ndcp() needs at least four arguments";
358 return QString();
359 }
360
361 KLocalizedString trMessage =
362 ki18ndcp(domain.toUtf8().constData(), context.toUtf8().constData(), singular.toUtf8().constData(), plural.toUtf8().constData());
363
364 resolvePlural(trMessage, param1);
365 resolveMessage(trMessage, param2, param3, param4, param5, param6, param7, param8, param9, param10);
366
367 d->markCurrentFunctionAsTranslationBinding(this);
368 return trMessage.toString();
369}
370
371/////////////////////////
372
373QString KLocalizedQmlContext::xi18n(const QString &message,
374 const QVariant &param1,
375 const QVariant &param2,
376 const QVariant &param3,
377 const QVariant &param4,
378 const QVariant &param5,
379 const QVariant &param6,
380 const QVariant &param7,
381 const QVariant &param8,
382 const QVariant &param9,
383 const QVariant &param10) const
384{
385 if (message.isEmpty()) {
386 qCWarning(KI18N) << "xi18n() needs at least one parameter";
387 return QString();
388 }
389
390 KLocalizedString trMessage;
391 if (!d->m_translationDomain.isEmpty()) {
392 trMessage = kxi18nd(d->m_translationDomain.toUtf8().constData(), message.toUtf8().constData());
393 } else {
394 trMessage = kxi18n(message.toUtf8().constData());
395 }
396
397 resolveMessage(trMessage, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10);
398
399 d->markCurrentFunctionAsTranslationBinding(this);
400 return trMessage.toString();
401}
402
403QString KLocalizedQmlContext::xi18nc(const QString &context,
404 const QString &message,
405 const QVariant &param1,
406 const QVariant &param2,
407 const QVariant &param3,
408 const QVariant &param4,
409 const QVariant &param5,
410 const QVariant &param6,
411 const QVariant &param7,
412 const QVariant &param8,
413 const QVariant &param9,
414 const QVariant &param10) const
415{
416 if (context.isEmpty() || message.isEmpty()) {
417 qCWarning(KI18N).noquote().nospace() << "xi18nc(\"" << context << message << "\") needs at least two arguments";
418 return QString();
419 }
420
421 KLocalizedString trMessage;
422 if (!d->m_translationDomain.isEmpty()) {
423 trMessage = kxi18ndc(d->m_translationDomain.toUtf8().constData(), context.toUtf8().constData(), message.toUtf8().constData());
424 } else {
425 trMessage = kxi18nc(context.toUtf8().constData(), message.toUtf8().constData());
426 }
427
428 resolveMessage(trMessage, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10);
429
430 d->markCurrentFunctionAsTranslationBinding(this);
431 return trMessage.toString();
432}
433
434QString KLocalizedQmlContext::xi18np(const QString &singular,
435 const QString &plural,
436 const QVariant &param1,
437 const QVariant &param2,
438 const QVariant &param3,
439 const QVariant &param4,
440 const QVariant &param5,
441 const QVariant &param6,
442 const QVariant &param7,
443 const QVariant &param8,
444 const QVariant &param9,
445 const QVariant &param10) const
446{
447 if (singular.isEmpty() || plural.isEmpty()) {
448 qCWarning(KI18N).noquote().nospace() << "xi18np(\"" << singular << plural << "\") needs at least two arguments";
449 return QString();
450 }
451
452 KLocalizedString trMessage;
453 if (!d->m_translationDomain.isEmpty()) {
454 trMessage = kxi18ndp(d->m_translationDomain.toUtf8().constData(), singular.toUtf8().constData(), plural.toUtf8().constData());
455 } else {
456 trMessage = kxi18np(singular.toUtf8().constData(), plural.toUtf8().constData());
457 }
458
459 resolvePlural(trMessage, param1);
460 resolveMessage(trMessage, param2, param3, param4, param5, param6, param7, param8, param9, param10);
461
462 d->markCurrentFunctionAsTranslationBinding(this);
463 return trMessage.toString();
464}
465
466QString KLocalizedQmlContext::xi18ncp(const QString &context,
467 const QString &singular,
468 const QString &plural,
469 const QVariant &param1,
470 const QVariant &param2,
471 const QVariant &param3,
472 const QVariant &param4,
473 const QVariant &param5,
474 const QVariant &param6,
475 const QVariant &param7,
476 const QVariant &param8,
477 const QVariant &param9,
478 const QVariant &param10) const
479{
480 if (context.isEmpty() || singular.isEmpty() || plural.isEmpty()) {
481 qCWarning(KI18N) << "xi18ncp() needs at least three arguments";
482 return QString();
483 }
484
485 KLocalizedString trMessage;
486 if (!d->m_translationDomain.isEmpty()) {
487 trMessage =
488 kxi18ndcp(d->m_translationDomain.toUtf8().constData(), context.toUtf8().constData(), singular.toUtf8().constData(), plural.toUtf8().constData());
489 } else {
490 trMessage = kxi18ncp(context.toUtf8().constData(), singular.toUtf8().constData(), plural.toUtf8().constData());
491 }
492
493 resolvePlural(trMessage, param1);
494 resolveMessage(trMessage, param2, param3, param4, param5, param6, param7, param8, param9, param10);
495
496 d->markCurrentFunctionAsTranslationBinding(this);
497 return trMessage.toString();
498}
499
500QString KLocalizedQmlContext::xi18nd(const QString &domain,
501 const QString &message,
502 const QVariant &param1,
503 const QVariant &param2,
504 const QVariant &param3,
505 const QVariant &param4,
506 const QVariant &param5,
507 const QVariant &param6,
508 const QVariant &param7,
509 const QVariant &param8,
510 const QVariant &param9,
511 const QVariant &param10) const
512{
513 if (domain.isEmpty() || message.isEmpty()) {
514 qCWarning(KI18N).noquote().nospace() << "xi18nd(\"" << domain << message << "\") needs at least two parameters";
515 return QString();
516 }
517
518 KLocalizedString trMessage = kxi18nd(domain.toUtf8().constData(), message.toUtf8().constData());
519
520 resolveMessage(trMessage, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10);
521
522 d->markCurrentFunctionAsTranslationBinding(this);
523 return trMessage.toString();
524}
525
526QString KLocalizedQmlContext::xi18ndc(const QString &domain,
527 const QString &context,
528 const QString &message,
529 const QVariant &param1,
530 const QVariant &param2,
531 const QVariant &param3,
532 const QVariant &param4,
533 const QVariant &param5,
534 const QVariant &param6,
535 const QVariant &param7,
536 const QVariant &param8,
537 const QVariant &param9,
538 const QVariant &param10) const
539{
540 if (domain.isEmpty() || context.isEmpty() || message.isEmpty()) {
541 qCWarning(KI18N) << "x18ndc() needs at least three arguments";
542 return QString();
543 }
544
545 KLocalizedString trMessage = kxi18ndc(domain.toUtf8().constData(), context.toUtf8().constData(), message.toUtf8().constData());
546
547 resolveMessage(trMessage, param1, param2, param3, param4, param5, param6, param7, param8, param9, param10);
548
549 d->markCurrentFunctionAsTranslationBinding(this);
550 return trMessage.toString();
551}
552
553QString KLocalizedQmlContext::xi18ndp(const QString &domain,
554 const QString &singular,
555 const QString &plural,
556 const QVariant &param1,
557 const QVariant &param2,
558 const QVariant &param3,
559 const QVariant &param4,
560 const QVariant &param5,
561 const QVariant &param6,
562 const QVariant &param7,
563 const QVariant &param8,
564 const QVariant &param9,
565 const QVariant &param10) const
566{
567 if (domain.isEmpty() || singular.isEmpty() || plural.isEmpty()) {
568 qCWarning(KI18N) << "xi18ndp() needs at least three arguments";
569 return QString();
570 }
571
572 KLocalizedString trMessage = kxi18ndp(domain.toUtf8().constData(), singular.toUtf8().constData(), plural.toUtf8().constData());
573
574 resolvePlural(trMessage, param1);
575 resolveMessage(trMessage, param2, param3, param4, param5, param6, param7, param8, param9, param10);
576
577 d->markCurrentFunctionAsTranslationBinding(this);
578 return trMessage.toString();
579}
580
581QString KLocalizedQmlContext::xi18ndcp(const QString &domain,
582 const QString &context,
583 const QString &singular,
584 const QString &plural,
585 const QVariant &param1,
586 const QVariant &param2,
587 const QVariant &param3,
588 const QVariant &param4,
589 const QVariant &param5,
590 const QVariant &param6,
591 const QVariant &param7,
592 const QVariant &param8,
593 const QVariant &param9,
594 const QVariant &param10) const
595{
596 if (domain.isEmpty() || context.isEmpty() || singular.isEmpty() || plural.isEmpty()) {
597 qCWarning(KI18N) << "xi18ndcp() needs at least four arguments";
598 return QString();
599 }
600
601 KLocalizedString trMessage =
602 kxi18ndcp(domain.toUtf8().constData(), context.toUtf8().constData(), singular.toUtf8().constData(), plural.toUtf8().constData());
603
604 resolvePlural(trMessage, param1);
605 resolveMessage(trMessage, param2, param3, param4, param5, param6, param7, param8, param9, param10);
606
607 d->markCurrentFunctionAsTranslationBinding(this);
608 return trMessage.toString();
609}
610
611bool KLocalizedQmlContext::eventFilter(QObject *watched, QEvent *event)
612{
613 if (event->type() == QEvent::LanguageChange && watched == QCoreApplication::instance()) {
614 qCDebug(KI18N) << "triggering binding reevaluation";
615 // run this deferred so we can be sure other things have reacted, such as KLocalizedString
616 // having updated its internal caches
617 if (auto engine = qmlEngine(this); engine) {
619 }
620 }
621 return QObject::eventFilter(watched, event);
622}
623
624KLocalizedQmlContext *KLocalization::Internal::createLocalizedContext(QQmlEngine *engine)
625{
626 auto ctx = new KLocalizedQmlContext(engine);
627 engine->rootContext()->setContextObject(ctx);
629 return ctx;
630}
631
632#include "moc_klocalizedqmlcontext.cpp"
This class is meant to be used to simplify integration of the KI18n framework in QML.
QString translationDomain
This property only needs to be specified if the context is being run on a library.
Class for producing and handling localized messages.
QString toString() const
Finalize the translation.
KLocalizedString subs(int a, int fieldWidth=0, int base=10, QChar fillChar=QLatin1Char(' ')) const
Substitute an int argument into the message.
const char * constData() const const
QCoreApplication * instance()
bool invokeMethod(QObject *context, Functor &&function, FunctorReturnType *ret)
Q_EMITQ_EMIT
virtual bool event(QEvent *e)
virtual bool eventFilter(QObject *watched, QEvent *event)
void installEventFilter(QObject *filterObj)
void setContextObject(QObject *object)
void retranslate()
QQmlContext * rootContext() const const
void setContextForObject(QObject *object, QQmlContext *context)
bool isEmpty() const const
QByteArray toUtf8() const const
QueuedConnection
bool canConvert() const const
bool isValid() const const
QChar toChar() const const
double toDouble(bool *ok) const const
int toInt(bool *ok) const const
QString toString() const const
int userType() const const
This file is part of the KDE documentation.
Documentation copyright © 1996-2025 The KDE developers.
Generated on Fri Apr 25 2025 12:05:13 by doxygen 1.13.2 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.