1 | /* This file is part of the KDE libraries |
2 | SPDX-FileCopyrightText: 2015 Lukáš Tinkl <ltinkl@redhat.com> |
3 | SPDX-FileCopyrightText: 2021,2023 Ingo Klöcker <kloecker@kde.org> |
4 | |
5 | SPDX-License-Identifier: LGPL-2.0-or-later |
6 | */ |
7 | |
8 | #include "ki18n_logging.h" |
9 | |
10 | #include <QCoreApplication> |
11 | #include <QLibraryInfo> |
12 | #include <QLocale> |
13 | #include <QThread> |
14 | #include <QTranslator> |
15 | |
16 | #include <memory> |
17 | |
18 | static bool loadCatalog(const QString &catalog, const QLocale &locale) |
19 | { |
20 | Q_ASSERT(QThread::currentThread() == QCoreApplication::instance()->thread()); |
21 | auto translator = std::make_unique<QTranslator>(args: QCoreApplication::instance()); |
22 | if (!translator->load(locale, filename: catalog, prefix: QString(), directory: QLibraryInfo::path(p: QLibraryInfo::TranslationsPath))) { |
23 | qCDebug(KI18N) << "Loading the" << catalog << "catalog failed for locale" << locale; |
24 | return false; |
25 | } |
26 | QCoreApplication::instance()->installTranslator(messageFile: translator.release()); |
27 | return true; |
28 | } |
29 | |
30 | static bool loadCatalog(const QString &catalog, const QLocale &locale, const QLocale &fallbackLocale) |
31 | { |
32 | // try to load the catalog for locale |
33 | if (loadCatalog(catalog, locale)) { |
34 | return true; |
35 | } |
36 | // if this fails, then try the fallback locale (if it's different from locale) |
37 | if (fallbackLocale != locale) { |
38 | return loadCatalog(catalog, locale: fallbackLocale); |
39 | } |
40 | return false; |
41 | } |
42 | |
43 | // load global Qt translation, needed in KDE e.g. by lots of builtin dialogs (QColorDialog, QFontDialog) that we use |
44 | static void loadTranslation(const QString &localeName, const QString &fallbackLocaleName) |
45 | { |
46 | const QLocale locale{localeName}; |
47 | const QLocale fallbackLocale{fallbackLocaleName}; |
48 | // first, try to load the qt_ meta catalog |
49 | if (loadCatalog(QStringLiteral("qt_" ), locale, fallbackLocale)) { |
50 | return; |
51 | } |
52 | // if loading the meta catalog failed, then try loading the four catalogs |
53 | // it depends on, i.e. qtbase, qtscript, qtmultimedia, qtxmlpatterns, separately |
54 | const auto catalogs = { |
55 | QStringLiteral("qtbase_" ), |
56 | QStringLiteral("qtscript_" ), |
57 | QStringLiteral("qtmultimedia_" ), |
58 | QStringLiteral("qtxmlpatterns_" ), |
59 | }; |
60 | for (const auto &catalog : catalogs) { |
61 | loadCatalog(catalog, locale, fallbackLocale); |
62 | } |
63 | } |
64 | |
65 | static QLocale getSystemLocale() |
66 | { |
67 | #if defined(Q_OS_WIN) || defined(Q_OS_MAC) |
68 | // On Windows and Apple OSs, we cannot use QLocale::system() if an application-specific |
69 | // language was set by kxmlgui because Qt ignores LANGUAGE on Windows and Apple OSs. |
70 | // The following code is a simplified variant of QSystemLocale::fallbackUiLocale() |
71 | // (in qlocale_unix.cpp) ignoring LC_ALL, LC_MESSAGES, and LANG. |
72 | QString language = qEnvironmentVariable("LANGUAGE" ); |
73 | if (!language.isEmpty()) { |
74 | language = language.split(QLatin1Char{':'}).constFirst(); |
75 | if (!language.isEmpty()) { |
76 | return QLocale{language}; |
77 | } |
78 | } |
79 | #endif |
80 | return QLocale::system(); |
81 | } |
82 | |
83 | static void load() |
84 | { |
85 | // The way Qt translation system handles plural forms makes it necessary to |
86 | // have a translation file which contains only plural forms for `en`. That's |
87 | // why we load the `en` translation unconditionally, then load the |
88 | // translation for the current locale to overload it. |
89 | QMetaObject::invokeMethod(object: QCoreApplication::instance(), function: [] { |
90 | loadCatalog(QStringLiteral("qt_" ), locale: QLocale{QStringLiteral("en" )}); |
91 | |
92 | const QLocale locale = getSystemLocale(); |
93 | if (locale.name() != QStringLiteral("en" )) { |
94 | loadTranslation(localeName: locale.name(), fallbackLocaleName: locale.bcp47Name()); |
95 | } |
96 | }); |
97 | } |
98 | |
99 | Q_COREAPP_STARTUP_FUNCTION(load) |
100 | |