From 5b525eb9ca0b80bae2497af5605da8473f8a6d4b Mon Sep 17 00:00:00 2001 From: Janek Bevendorff Date: Wed, 20 Dec 2017 00:18:42 +0100 Subject: [PATCH 1/4] Refactor Translator class to load qtbase translations from local directory if available --- src/core/Translator.cpp | 105 +++++++++++++++++++++------------------- src/core/Translator.h | 7 ++- src/main.cpp | 2 +- 3 files changed, 59 insertions(+), 55 deletions(-) diff --git a/src/core/Translator.cpp b/src/core/Translator.cpp index 713727ea..bc75a097 100644 --- a/src/core/Translator.cpp +++ b/src/core/Translator.cpp @@ -1,4 +1,5 @@ /* + * Copyright (C) 2017 KeePassXC Team * Copyright (C) 2014 Felix Geyer * * This program is free software: you can redistribute it and/or modify @@ -21,33 +22,45 @@ #include #include #include -#include #include +#include #include "config-keepassx.h" #include "core/Config.h" #include "core/FilePath.h" -void Translator::installTranslator() +/** + * Install all KeePassXC and Qt translators. + */ +void Translator::installTranslators() { QString language = config()->get("GUI/Language").toString(); if (language == "system" || language.isEmpty()) { language = QLocale::system().name(); } - if (!installTranslator(language)) { - // English fallback still needs translations for plurals - if (!installTranslator("en_plurals")) { - qWarning("Couldn't load translations."); - } + const QStringList paths = { +#ifdef QT_DEBUG + QString("%1/share/translations").arg(KEEPASSX_BINARY_DIR), +#endif + filePath()->dataPath("translations") + }; + + bool translationsLoaded = false; + for (const QString& path : paths) { + translationsLoaded |= installTranslator(language, path) || installTranslator("en_plurals", path); + installQtTranslator(language, path); + } + if (!translationsLoaded) { + // couldn't load configured language or fallback + qWarning("Couldn't load translations."); } - - installQtTranslator(language); - - availableLanguages(); } -QList > Translator::availableLanguages() +/** + * @return list of pairs of available language codes and names + */ +QList> Translator::availableLanguages() { const QStringList paths = { #ifdef QT_DEBUG @@ -59,12 +72,13 @@ QList > Translator::availableLanguages() QList > languages; languages.append(QPair("system", "System default")); - QRegExp regExp("keepassx_([a-zA-Z_]+)\\.qm", Qt::CaseInsensitive, QRegExp::RegExp2); + QRegularExpression regExp("^keepassx_([a-zA-Z_]+)\\.qm$", QRegularExpression::CaseInsensitiveOption); for (const QString& path : paths) { const QStringList fileList = QDir(path).entryList(); for (const QString& filename : fileList) { - if (regExp.exactMatch(filename)) { - QString langcode = regExp.cap(1); + QRegularExpressionMatch match = regExp.match(filename); + if (match.hasMatch()) { + QString langcode = match.captured(1); if (langcode == "en_plurals") { langcode = "en"; } @@ -85,46 +99,37 @@ QList > Translator::availableLanguages() return languages; } -bool Translator::installTranslator(const QString& language) +/** + * Install KeePassXC translator. + * + * @param language translator language + * @param path local search path + * @return true on success + */ +bool Translator::installTranslator(const QString& language, const QString& path) { - const QStringList paths = { -#ifdef QT_DEBUG - QString("%1/share/translations").arg(KEEPASSX_BINARY_DIR), -#endif - filePath()->dataPath("translations") - }; - - for (const QString& path : paths) { - if (installTranslator(language, path)) { - return true; - } + QScopedPointer translator(new QTranslator(qApp)); + if (translator->load(QString("keepassx_%1").arg(language), path)) { + return QCoreApplication::installTranslator(translator.take()); } - return false; } -bool Translator::installTranslator(const QString& language, const QString& path) +/** + * Install Qt5 base translator from the specified local search path or the default system path + * if no qtbase_* translations were found at the local path. + * + * @param language translator language + * @param path local search path + * @return true on success + */ +bool Translator::installQtTranslator(const QString& language, const QString& path) { - QTranslator* translator = new QTranslator(qApp); - if (translator->load(QString("keepassx_").append(language), path)) { - QCoreApplication::installTranslator(translator); - return true; - } - else { - delete translator; - return false; - } -} - -bool Translator::installQtTranslator(const QString& language) -{ - QTranslator* qtTranslator = new QTranslator(qApp); - if (qtTranslator->load(QString("%1/qtbase_%2").arg(QLibraryInfo::location(QLibraryInfo::TranslationsPath), language))) { - QCoreApplication::installTranslator(qtTranslator); - return true; - } - else { - delete qtTranslator; - return false; + QScopedPointer qtTranslator(new QTranslator(qApp)); + if (qtTranslator->load(QString("qtbase_%1").arg(language), path)) { + return QCoreApplication::installTranslator(qtTranslator.take()); + } else if (qtTranslator->load(QString("qtbase_%1").arg(language), QLibraryInfo::location(QLibraryInfo::TranslationsPath))) { + return QCoreApplication::installTranslator(qtTranslator.take()); } + return false; } diff --git a/src/core/Translator.h b/src/core/Translator.h index 4bc4fca3..cf62f48e 100644 --- a/src/core/Translator.h +++ b/src/core/Translator.h @@ -24,13 +24,12 @@ class Translator { public: - static void installTranslator(); - static QList > availableLanguages(); + static void installTranslators(); + static QList> availableLanguages(); private: - static bool installTranslator(const QString& language); static bool installTranslator(const QString& language, const QString& path); - static bool installQtTranslator(const QString& language); + static bool installQtTranslator(const QString& language, const QString& path); }; #endif // KEEPASSX_TRANSLATOR_H diff --git a/src/main.cpp b/src/main.cpp index 354c8a3b..7977435f 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -99,7 +99,7 @@ int main(int argc, char** argv) Config::createConfigFromFile(parser.value(configOption)); } - Translator::installTranslator(); + Translator::installTranslators(); #ifdef Q_OS_MAC // Don't show menu icons on OSX From c57973615837c3d0c1a8574a204d3a1943bd1e48 Mon Sep 17 00:00:00 2001 From: Janek Bevendorff Date: Wed, 20 Dec 2017 00:19:04 +0100 Subject: [PATCH 2/4] Bundle qtbase translations on Windows --- share/translations/CMakeLists.txt | 6 ++++++ src/CMakeLists.txt | 4 ++-- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/share/translations/CMakeLists.txt b/share/translations/CMakeLists.txt index 7380750e..a5d8882b 100644 --- a/share/translations/CMakeLists.txt +++ b/share/translations/CMakeLists.txt @@ -1,3 +1,4 @@ +# Copyright (C) 2017 KeePassXC Team # Copyright (C) 2014 Felix Geyer # # This program is free software: you can redistribute it and/or modify @@ -21,6 +22,11 @@ message(STATUS "${TRANSLATION_FILES}") qt5_add_translation(QM_FILES ${TRANSLATION_FILES}) +if(MINGW) + file(GLOB QTBASE_TRANSLATIONS ${Qt5_DIR}/../../../share/qt5/translations/qtbase_*.qm) +endif() +set(QM_FILES ${QM_FILES} ${QTBASE_TRANSLATIONS}) + install(FILES ${QM_FILES} DESTINATION ${DATA_INSTALL_DIR}/translations) add_custom_target(translations DEPENDS ${QM_FILES}) add_dependencies(${PROGNAME} translations) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 42e1bdbd..afa30056 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1,5 +1,5 @@ -# Copyright (C) 2010 Felix Geyer # Copyright (C) 2017 KeePassXC Team +# Copyright (C) 2010 Felix Geyer # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by @@ -352,7 +352,7 @@ if(MINGW) include(DeployQt4) install_qt4_executable(${PROGNAME}.exe) add_custom_command(TARGET ${PROGNAME} POST_BUILD - COMMAND ${CMAKE_COMMAND} -E copy_if_different ${Qt5Core_DIR}/../../../share/qt5/plugins/platforms/qwindows$<$:d>.dll + COMMAND ${CMAKE_COMMAND} -E copy_if_different ${Qt5_DIR}/../../../share/qt5/plugins/platforms/qwindows$<$:d>.dll $) install(FILES $/qwindows$<$:d>.dll DESTINATION "platforms") endif() From a4cf32dce0eed6e0dd326a88f464712512482962 Mon Sep 17 00:00:00 2001 From: Janek Bevendorff Date: Thu, 21 Dec 2017 19:12:51 +0100 Subject: [PATCH 3/4] Bundle qtbase translations with macOS and AppImage releases --- Dockerfile | 1 + release-tool | 3 ++- share/translations/CMakeLists.txt | 5 +++++ 3 files changed, 8 insertions(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index a5966be3..66ecb4c0 100644 --- a/Dockerfile +++ b/Dockerfile @@ -40,6 +40,7 @@ RUN set -x \ qt${QT5_VERSION}base \ qt${QT5_VERSION}tools \ qt${QT5_VERSION}x11extras \ + qt${QT5_VERSION}translations \ zlib1g-dev \ libxi-dev \ libxtst-dev \ diff --git a/release-tool b/release-tool index a3813fd9..93e964bc 100755 --- a/release-tool +++ b/release-tool @@ -678,7 +678,8 @@ build() { "$DOCKER_IMAGE" \ bash -c "cd /keepassxc/out/build-release && \ cmake -DCMAKE_BUILD_TYPE=Release -DWITH_TESTS=Off $CMAKE_OPTIONS \ - -DCMAKE_INSTALL_PREFIX=\"${INSTALL_PREFIX}\" /keepassxc/src && \ + -DCMAKE_INSTALL_PREFIX=\"${INSTALL_PREFIX}\" \ + -DKEEPASSXC_DIST_TYPE=AppImage /keepassxc/src && \ make $MAKE_OPTIONS && make DESTDIR=/keepassxc/out/bin-release install/strip && \ /keepassxc/src/AppImage-Recipe.sh "$APP_NAME" "$RELEASE_NAME"" diff --git a/share/translations/CMakeLists.txt b/share/translations/CMakeLists.txt index a5d8882b..c0b1a49b 100644 --- a/share/translations/CMakeLists.txt +++ b/share/translations/CMakeLists.txt @@ -24,6 +24,11 @@ qt5_add_translation(QM_FILES ${TRANSLATION_FILES}) if(MINGW) file(GLOB QTBASE_TRANSLATIONS ${Qt5_DIR}/../../../share/qt5/translations/qtbase_*.qm) +elseif(APPLE OR KEEPASSXC_DIST_APPIMAGE) + file(GLOB QTBASE_TRANSLATIONS + /usr/share/qt/translations/qtbase_*.qm + /usr/share/qt5/translations/qtbase_*.qm + ${Qt5_DIR}/../../../translations/qtbase_*.qm) endif() set(QM_FILES ${QM_FILES} ${QTBASE_TRANSLATIONS}) From 6c2ccada1383379a47035431b5f46d1038c21881 Mon Sep 17 00:00:00 2001 From: Jonathan White Date: Thu, 21 Dec 2017 23:25:24 -0500 Subject: [PATCH 4/4] Support built-in translations in Snap --- snapcraft.yaml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/snapcraft.yaml b/snapcraft.yaml index fd2ca7b8..97a4bc25 100644 --- a/snapcraft.yaml +++ b/snapcraft.yaml @@ -43,8 +43,11 @@ parts: - libykpers-1-dev stage-packages: - dbus + - qttranslations5-l10n # common translations install: | sed -i 's|Icon=keepassxc|Icon=${SNAP}/usr/share/icons/hicolor/256x256/apps/keepassxc.png|g' $SNAPCRAFT_PART_INSTALL/usr/share/applications/org.keepassxc.KeePassXC.desktop + organize: + usr/share/qt5/translations/*.qm: usr/share/keepassxc/translations/ after: [desktop-qt5] # Redefine desktop-qt5 stage packages to work with Ubuntu 17.04