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

KDE's Doxygen guidelines are available online.