diff --git a/docker/appimage/build-appimage.sh b/docker/appimage/build-appimage.sh index 62ca7ebd..09f304fc 100644 --- a/docker/appimage/build-appimage.sh +++ b/docker/appimage/build-appimage.sh @@ -1,82 +1,70 @@ #!/bin/sh # Build an AppImage of Kleopatra # Copyright (C) 2021 g10 Code GmbH # # Software engineering by Ingo Klöcker # # This file is part of GnuPG. # # GnuPG is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 3 of the License, or # (at your option) any later version. # # GnuPG is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, see . # # SPDX-License-Identifier: GPL-3.0+ set -e source /opt/rh/devtoolset-7/enable cd /src/packages ./download.sh cd /src ./configure --enable-appimage --enable-maintainer-mode --disable-manuals cd /src make echo 'rootdir = $APPDIR/usr' >/build/AppDir/usr/bin/gpgconf.ctl export PATH=/opt/linuxdeploy/usr/bin:$PATH export LD_LIBRARY_PATH=/build/install/lib # tell the linuxdeploy qt-plugin where to find qmake export QMAKE=/build/install/bin/qmake # create plugin directories expected by linuxdeploy qt-plugin # workaround for # [qt/stdout] Deploy[qt/stderr] terminate called after throwing an instance of 'boost::filesystem::filesystem_error' # [qt/stderr] what(): boost::filesystem::directory_iterator::construct: No such file or directory: "/build/AppDir/usr/plugins/printsupport" # ERROR: Failed to run plugin: qt (exit code: 6) mkdir -p /build/install/plugins/{printsupport,sqldrivers} # copy KDE plugins for d in iconengines kf5 pim; do mkdir -p /build/AppDir/usr/plugins/${d}/ rsync -av --delete --omit-dir-times /build/install/lib64/plugins/${d}/ /build/AppDir/usr/plugins/${d}/ done cd /build # remove existing AppRun and wrapped AppRun, that may be left over from a previous run of # linuxdeploy, to ensure that our custom AppRun is deployed rm -f /build/AppDir/AppRun /build/AppDir/AppRun.wrapped -# copy the translations of qtscript, qtmultimedia and qtxmlpatterns; we do not use those -# Qt modules, but Kleopatra (via ki18n) loads the qt_ meta catalog which depends on -# the catalogs of qtbase and the above three modules for most languages; loading the -# Qt translations fails if any of those catalogs are missing; linuxdeploy automatically -# includes the catalogs of the modules we use, but as we do not use the other three -# we have to copy them ourselves -# as a side effect linuxdeploy will create bogus symlinks from -# /build/AppDir/usr/share/locale/*/LC_MESSAGES/kfoo5_qt.qm to -# /build/AppDir/usr/translations/kfoo5_qt.qm -# (note the missing language id in the symlinks) which obviously makes no sense; -# luckily, this does not seem to cause problems -rsync -av /build/install/translations/qtscript_* /build/AppDir/usr/translations/ -rsync -av /build/install/translations/qtmultimedia_* /build/AppDir/usr/translations/ -rsync -av /build/install/translations/qtxmlpatterns_*.qm /build/AppDir/usr/translations/ +# remove existing translations that may be left over from a previous run of linuxdeploy +rm -rf /build/AppDir/usr/translations linuxdeploy --appdir /build/AppDir \ --desktop-file /build/AppDir/usr/share/applications/org.kde.kleopatra.desktop \ --icon-file /build/AppDir/usr/share/icons/hicolor/256x256/apps/kleopatra.png \ --custom-apprun /src/src/appimage/AppRun \ --plugin qt \ --output appimage \ 2>&1 | tee /build/logs/linuxdeploy-kleopatra.log diff --git a/patches-appimage/ki18n/0001-Load-Qt-translations-even-if-some-catalogs-are-missi.patch b/patches-appimage/ki18n/0001-Load-Qt-translations-even-if-some-catalogs-are-missi.patch new file mode 100755 index 00000000..38f59b26 --- /dev/null +++ b/patches-appimage/ki18n/0001-Load-Qt-translations-even-if-some-catalogs-are-missi.patch @@ -0,0 +1,92 @@ +#! /bin/sh +patch -p1 -l -f $* < $0 +exit $? + +diff --git a/src/main.cpp b/src/main.cpp +index 1d654b8..58dab0b 100644 +--- a/src/main.cpp ++++ b/src/main.cpp +@@ -1,19 +1,22 @@ + /* This file is part of the KDE libraries + SPDX-FileCopyrightText: 2015 Lukáš Tinkl ++ SPDX-FileCopyrightText: 2021 Ingo Klöcker + + SPDX-License-Identifier: LGPL-2.0-or-later + */ + ++#include "ki18n_logging.h" ++ + #include + #include + #include + #include + +-// load global Qt translation, needed in KDE e.g. by lots of builtin dialogs (QColorDialog, QFontDialog) that we use +-static bool loadTranslation(const QString &localeName) ++static bool loadCatalog(const QString &catalog, const QLocale &locale) + { + QTranslator *translator = new QTranslator(QCoreApplication::instance()); +- if (!translator->load(QLocale(localeName), QStringLiteral("qt_"), QString(), QLibraryInfo::location(QLibraryInfo::TranslationsPath))) { ++ if (!translator->load(locale, catalog, QString(), QLibraryInfo::location(QLibraryInfo::TranslationsPath))) { ++ qCDebug(KI18N) << "Loading the" << catalog << "catalog failed for locale" << locale; + delete translator; + return false; + } +@@ -21,19 +24,52 @@ static bool loadTranslation(const QString &localeName) + return true; + } + ++static bool loadCatalog(const QString &catalog, const QLocale &locale, const QLocale &fallbackLocale) ++{ ++ // try to load the catalog for locale ++ if (loadCatalog(catalog, locale)) { ++ return true; ++ } ++ // if this fails, then try the fallback locale (if it's different from locale) ++ if (fallbackLocale != locale) { ++ return loadCatalog(catalog, fallbackLocale); ++ } ++ return false; ++} ++ ++// load global Qt translation, needed in KDE e.g. by lots of builtin dialogs (QColorDialog, QFontDialog) that we use ++static void loadTranslation(const QString &localeName, const QString &fallbackLocaleName) ++{ ++ const QLocale locale{localeName}; ++ const QLocale fallbackLocale{fallbackLocaleName}; ++ // first, try to load the qt_ meta catalog ++ if (loadCatalog(QStringLiteral("qt_"), locale, fallbackLocale)) { ++ return; ++ } ++ // if loading the meta catalog failed, then try loading the four catalogs ++ // it depends on, i.e. qtbase, qtscript, qtmultimedia, qtxmlpatterns, separately ++ const auto catalogs = { ++ QStringLiteral("qtbase_"), ++ QStringLiteral("qtscript_"), ++ QStringLiteral("qtmultimedia_"), ++ QStringLiteral("qtxmlpatterns_"), ++ }; ++ for (const auto &catalog : catalogs) { ++ loadCatalog(catalog, locale, fallbackLocale); ++ } ++} ++ + static void load() + { + // The way Qt translation system handles plural forms makes it necessary to + // have a translation file which contains only plural forms for `en`. That's + // why we load the `en` translation unconditionally, then load the + // translation for the current locale to overload it. +- loadTranslation(QStringLiteral("en")); ++ loadCatalog(QStringLiteral("qt_"), QLocale{QStringLiteral("en")}); + +- QLocale locale = QLocale::system(); ++ const QLocale locale = QLocale::system(); + if (locale.name() != QStringLiteral("en")) { +- if (!loadTranslation(locale.name())) { +- loadTranslation(locale.bcp47Name()); +- } ++ loadTranslation(locale.name(), locale.bcp47Name()); + } + } +