#include "ngltranslator.h" #include #include "ngltranslator_p.h" #include #include #include #include #include #include #include #include #include namespace NGL { struct TranslationData { QByteArray isoCode; QString qmPrefix; QTranslator qtTranslator; QTranslator kdReportsTranslator; QTranslator ltsTranslator; Translator dynamicTranslator; TranslationData() { QCoreApplication::installTranslator(&qtTranslator); QCoreApplication::installTranslator(&kdReportsTranslator); QCoreApplication::installTranslator(<sTranslator); QCoreApplication::installTranslator(&dynamicTranslator); } ~TranslationData() { if (qApp) { QCoreApplication::removeTranslator(&qtTranslator); QCoreApplication::removeTranslator(&kdReportsTranslator); QCoreApplication::removeTranslator(<sTranslator); QCoreApplication::removeTranslator(&dynamicTranslator); } } }; Q_GLOBAL_STATIC(TranslationData, s_translationData) Translator::Translator(QObject *parent) : QTranslator(parent) {} void Translator::setTranslationCatalog(const TranslationCatalog &catalog) { m_catalog = catalog; m_md5Sum.clear(); isoCodeChanged(s_translationData()->isoCode); } bool Translator::setTranslationDataJson(const QByteArray &jsonData, const QByteArray &md5Sum, bool bCompressed) { if (m_md5Sum == md5Sum) return true; // Use fromJson; fromBinaryData is not available in this Qt build const QByteArray jsonRaw = bCompressed ? qUncompress(jsonData) : jsonData; const QJsonObject jObj = QJsonDocument::fromJson(jsonRaw).object(); const QString translationKey(QStringLiteral("translations")); if (jObj.empty() || !jObj.contains(translationKey) || !jObj.value(translationKey).isArray()) return false; const QJsonArray arr = jObj[translationKey].toArray(); m_catalog.clear(); m_catalog.reserve(arr.size()); TranslationEntry te; for (const QJsonValue &element : arr) { const QJsonObject obj = element.toObject(); te.isoCode = obj.value(QStringLiteral("isoCode")).toString().toUtf8(); te.context = obj.value(QStringLiteral("context")).toString().toUtf8(); te.key = obj.value(QStringLiteral("key")).toString().toUtf8(); te.disambiguation = obj.value(QStringLiteral("disambiguation")).toString().toUtf8(); te.translation = obj.value(QStringLiteral("translation")).toString(); m_catalog += te; } m_md5Sum = md5Sum; isoCodeChanged(s_translationData()->isoCode); return false; } QString Translator::translate(const char *context, const char *sourceText, const char *disambiguation, int n) const { if (n != -1) return QString(); const auto itCtx = m_translationLookup.find(QByteArray::fromRawData(context, strlen(context))); if (itCtx == m_translationLookup.end()) return QString(); const auto itKey = itCtx.value().find(QByteArray::fromRawData(sourceText, strlen(sourceText))); if (itKey == itCtx.value().end()) return QString(); const auto itDis = itKey.value().find(disambiguation ? QByteArray::fromRawData(disambiguation, strlen(disambiguation)) : QByteArray()); if (itDis == itKey.value().end()) return QString(); return itDis.value(); } void Translator::isoCodeChanged(const QByteArray &isoCode) { m_translationLookup.clear(); for (const TranslationEntry &te : std::as_const(m_catalog)) { if (te.isoCode != isoCode) continue; m_translationLookup[te.context][te.key][te.disambiguation] = te.translation; } } void setTranslationCatalog(const TranslationCatalog &catalog) { s_translationData()->dynamicTranslator.setTranslationCatalog(catalog); } bool setTranslationDataJson(const QByteArray &jsonData, const QByteArray &md5Sum, bool bCompressed) { return s_translationData()->dynamicTranslator.setTranslationDataJson(jsonData, md5Sum, bCompressed); } bool setTranslationLocale(const QByteArray &isoCode, const QString &qmPrefix) { if (s_translationData()->isoCode == isoCode && s_translationData()->qmPrefix == qmPrefix) return true; s_translationData()->isoCode = isoCode; s_translationData()->qmPrefix = qmPrefix; const QString relTranslationPath = QLatin1Char('/') + QString::fromLatin1(isoCode) + QLatin1Char('/'); const QStringList possiblePaths = { QCoreApplication::applicationDirPath() + QStringLiteral("/translations/"), QCoreApplication::applicationDirPath() + QStringLiteral("/../translations/"), QDir::homePath() + QStringLiteral("/translations/") }; const QString qm(QStringLiteral(".qm")); QString ltsQmPath; for (const QString &path : possiblePaths) { const QString absPath = path + relTranslationPath; if (!QDir(absPath).exists()) continue; if (QTranslator().load(qmPrefix + qm, absPath)) { ltsQmPath = absPath + qmPrefix + qm; break; } } QString kdReportsQmPath; const QString kdReportsPrefix(QStringLiteral("kdreports")); for (const QString &path : possiblePaths) { const QString absPath = path + relTranslationPath; if (!QDir(absPath).exists()) continue; if (QTranslator().load(kdReportsPrefix + qm, absPath)) { kdReportsQmPath = absPath + kdReportsPrefix + qm; break; } } QStringList isoCodeList(QString::fromLatin1(isoCode).split(QLatin1Char('_'))); if (isoCodeList.count() == 2) { if (!s_translationData->qtTranslator.load(QLatin1String("qt_") + isoCodeList.at(0), QLibraryInfo::path(QLibraryInfo::TranslationsPath))) { qWarning("qtTranslator.load failed for %s", qPrintable(isoCodeList.at(0))); } } else { qWarning() << "translation iso code not compatible with qt translations"; } if (!s_translationData->kdReportsTranslator.load(kdReportsQmPath)) qWarning("kdReportsTranslator.load failed: %s", qPrintable(kdReportsQmPath)); if (!s_translationData->ltsTranslator.load(ltsQmPath)) qWarning("ltsTranslator.load failed: %s", qPrintable(ltsQmPath)); s_translationData->dynamicTranslator.isoCodeChanged(isoCode); return !s_translationData->ltsTranslator.isEmpty(); } QByteArray translationLocale() { return s_translationData()->isoCode; } }