From 90a4284c56856f0cbdb1a7af151d575a468c59eb Mon Sep 17 00:00:00 2001 From: EndrII Date: Sun, 1 Oct 2023 11:27:35 +0200 Subject: [PATCH] added tr method for custom translations --- locales.cpp | 122 ++++++++++++++++++++++++++++++++++++++++++---------- locales.h | 37 ++++++++++++++-- 2 files changed, 132 insertions(+), 27 deletions(-) diff --git a/locales.cpp b/locales.cpp index 1a06129..ce1c463 100644 --- a/locales.cpp +++ b/locales.cpp @@ -13,6 +13,8 @@ #include #include #include +#include +#include #include "params.h" using namespace QuasarAppUtils; @@ -78,20 +80,8 @@ bool QuasarAppUtils::Locales::findQm(QString localePrefix, return findQmPrivate(localePrefix, qmFiles); } -bool Locales::setLocalePrivate(const QLocale &locale) { - removeOldTranslation(); - - const auto list = locale.uiLanguages(); - QList qmFiles; - - auto it = list.rbegin(); - while (qmFiles.isEmpty() && it != list.rend() && !findQm(*it, qmFiles)) { - it++; - } - - if (qmFiles.isEmpty()) - return false; - +void QuasarAppUtils::Locales::installTranslations( QList &qmFiles) +{ for (const auto & translator: qAsConst(qmFiles)) { if (!QCoreApplication::installTranslator(translator)) { @@ -99,17 +89,59 @@ bool Locales::setLocalePrivate(const QLocale &locale) { QuasarAppUtils::Warning); delete translator; + // we use a link of qmFiles so remove all invalid translations. + qmFiles.removeAll(translator); + continue; } + } +} - _translations.push_back(translator); +QString Locales::translatePrivate(const char *source, const QLocale &locale) { + auto translations = _translations.value(locale); + + for (const auto& tr : translations) { + auto result = tr->translate("QuasarAppUtils::Locales", source); + if (result.size()) { + return result; + } + } + + return source; +} + +bool Locales::setLocalePrivate(const QLocale &locale, bool force, bool install) { + if (force) { + clearCache(locale); + } + + removeOldTranslation(_currentLocate); + + // take a link to list of translations. + QList &qmFiles = _translations[locale]; + + if (qmFiles.isEmpty()) { + // fill list of translations + const auto list = locale.uiLanguages(); + + auto it = list.rbegin(); + while (qmFiles.isEmpty() && it != list.rend() && !findQm(*it, qmFiles)) { + it++; + } + + if (qmFiles.isEmpty()) + return false; } + + if (install) + installTranslations(qmFiles); + emit sigTranslationChanged(); _currentLocate = locale; - return _translations.size(); + return _translations[locale].size(); } const QLocale &Locales::currentLocate() { @@ -117,9 +149,19 @@ const QLocale &Locales::currentLocate() { return obj->currentLocatePrivate(); } -bool Locales::setLocale(const QLocale &locale) { +QString Locales::tr(const char *source, const QLocale &locale) { auto obj = instance(); - return obj->setLocalePrivate(locale); + return obj->translatePrivate(source, locale); +} + +bool Locales::setLocale(const QLocale &locale, bool force) { + auto obj = instance(); + return obj->setLocalePrivate(locale, force); +} + +bool Locales::init(const QList &locales, const QSet &location) { + auto obj = instance(); + return obj->initPrivate(locales, location); } bool Locales::init(const QLocale &locale, const QSet & location) { @@ -142,17 +184,51 @@ bool Locales::initPrivate(const QLocale &locale, const QSet & locations return setLocalePrivate(locale); } +bool Locales::initPrivate(const QList &locales, const QSet &locations) { +#if QT_VERSION <= QT_VERSION_CHECK(6, 0, 0) + auto defaultTr = QLibraryInfo::location(QLibraryInfo::TranslationsPath); +#else + auto defaultTr = QLibraryInfo::path(QLibraryInfo::TranslationsPath); +#endif + _locations = locations; + if (!_locations.contains(defaultTr)) { + _locations += defaultTr; + } + + for (const auto& locale: locales) { + if (!setLocalePrivate(locale, false, false)) { + return false; + } + } + + return true; +} + +void Locales::clearCache(const QLocale &locale) { + for (const auto & tr :qAsConst(_translations[locale])) { + QCoreApplication::removeTranslator(tr); + delete tr; + } + + _translations[locale].clear(); +} + +void Locales::clearCache() { + for (auto it = _translations.keyBegin(); it != _translations.keyEnd(); it = std::next(it)) { + clearCache(*it); + } + _translations.clear(); +} + Locales *Locales::instance() { static auto instance = new Locales(); return instance; } -void Locales::removeOldTranslation() { - for (const auto & tr :qAsConst(_translations)) { +void Locales::removeOldTranslation(const QLocale &locale) { + for (const auto & tr :qAsConst(_translations[locale])) { QCoreApplication::removeTranslator(tr); - delete tr; } - _translations.clear(); } void Locales::addLocationPrivate(const QString &location) { @@ -169,5 +245,5 @@ void Locales::addLocation(const QString &location) { } Locales::~Locales() { - removeOldTranslation(); + clearCache(); } diff --git a/locales.h b/locales.h index cda8798..8265d0a 100644 --- a/locales.h +++ b/locales.h @@ -46,7 +46,16 @@ public: * @param locale This is new locale. * @return true if the all ltranstations files loaded successful. */ - static bool setLocale(const QLocale &locale); + static bool setLocale(const QLocale &locale, bool force = false); + + /** + * @brief init This method initialize translations of applictaion. + * @param locales This is list of locales that you want to locad to application cache. See info about QLocale. + * @param location Path to folder with qm files. example (:/tr). + * @return return true if locale set for application. + */ + static bool init(const QList & locales, + const QSet & location = {}); /** * @brief init This method initialize translation of applictaion. @@ -75,6 +84,15 @@ public: */ static const QLocale ¤tLocate(); + /** + * @brief tr This method will translate single string to choosed language. + * @param source This is source string of translations. + * @param locale This is choosed language. + * @return translated string value. + * @note use instant QOBject::tr, This method must be read by the lupdate utility + */ + static QString tr(const char *source, const QLocale& locale); + signals: /** * @brief sigTranslationChanged Emited when set new locale for application. @@ -85,10 +103,18 @@ private: Locales() = default; ~Locales(); - bool setLocalePrivate(const QLocale &locale = QLocale::system()); + bool setLocalePrivate(const QLocale &locale = QLocale::system(), bool force = false, bool install = true); bool initPrivate(const QLocale &locale = QLocale::system(), const QSet &location = {}); - void removeOldTranslation(); + + bool initPrivate(const QList &locales, + const QSet &location = {}); + + void clearCache(const QLocale& locale); + void clearCache(); + + void removeOldTranslation(const QLocale& locale); + void addLocationPrivate(const QString& location); const QLocale ¤tLocatePrivate() const; @@ -97,10 +123,13 @@ private: QList &result); bool findQmPrivate(const QString &prefix, QList &qmFiles); + void installTranslations(QList &qmFiles); + QString translatePrivate(const char *source, const QLocale& locale); + QLocale _currentLocate; QSet _locations; - QList _translations; + QHash> _translations; }; }