1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139
|
/* This file was generated by ecm_create_qm_loader(). DO NOT EDIT!
*
* Building this file in a library ensures translations are automatically loaded
* when an application makes use of the library.
*
*
* SPDX-FileCopyrightText: 2014 Aurélien Gâteau <agateau@kde.org>
* SPDX-FileCopyrightText: 2015 Alex Merry <alex.merry@kde.org>
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <QCoreApplication>
#include <QLocale>
#include <QStandardPaths>
#include <QThread>
#include <QTranslator>
#include <QDir>
namespace {
enum class LoadOptions { CreateWatcher, DoNotCreateWatcher };
void load(LoadOptions options);
class LanguageChangeWatcher : public QObject
{
public:
LanguageChangeWatcher(QObject *parent) : QObject(parent)
{
m_loadedLocale = QLocale::system().name();
QCoreApplication::instance()->installEventFilter(this);
}
private:
bool eventFilter(QObject *obj, QEvent *event) override
{
if (event->type() == QEvent::LanguageChange) {
if (m_loadedLocale != QLocale::system().name()) {
m_loadedLocale = QLocale::system().name();
load(LoadOptions::DoNotCreateWatcher);
}
}
return QObject::eventFilter(obj, event);
}
QString m_loadedLocale;
};
bool loadTranslation(const QString &localeDirName)
{
QString subPath = QStringLiteral("locale/") + localeDirName + QStringLiteral("/LC_MESSAGES/@QM_LOADER_CATALOG_NAME@.qm");
#if defined(Q_OS_ANDROID)
const QString fullPath = QStringLiteral("assets:/share/") + subPath;
if (!QFile::exists(fullPath)) {
return false;
}
#else
const QString fullPath = QStandardPaths::locate(QStandardPaths::GenericDataLocation, subPath);
if (fullPath.isEmpty()) {
return false;
}
#endif
QTranslator *translator = new QTranslator(QCoreApplication::instance());
if (!translator->load(fullPath)) {
delete translator;
return false;
}
QCoreApplication::instance()->installTranslator(translator);
return true;
}
void load(LoadOptions options)
{
// 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"));
QLocale locale = QLocale::system();
if (locale.name() != QStringLiteral("en")) {
if (!loadTranslation(locale.name())) {
if (!loadTranslation(locale.bcp47Name())) {
const int i = locale.name().indexOf(QLatin1Char('_'));
if (i > 0) {
loadTranslation(locale.name().left(i));
}
}
}
}
if (options == LoadOptions::CreateWatcher) {
new LanguageChangeWatcher(QCoreApplication::instance());
}
}
// Helper to call load() on the main thread.
//
// Calling functions on another thread without using moc is non-trivial in
// Qt until 5.4 (when some useful QTimer::singleShot overloads were added).
//
// Instead, we have to use QEvents. Ideally, we'd use a custom QEvent, but
// there's a chance this could cause trouble with applications that claim
// QEvent codes themselves, but don't register them with Qt (and we also
// want to avoid registering a new QEvent code for every plugin that might
// be loaded). We use QTimer because it's unlikely to be filtered by
// applications, and is also unlikely to cause Qt to do something it
// shouldn't.
class Loader : public QObject
{
protected:
void timerEvent(QTimerEvent *) Q_DECL_OVERRIDE
{
load(LoadOptions::CreateWatcher);
this->deleteLater();
}
};
void loadOnMainThread()
{
// If this library is loaded after the QCoreApplication instance is
// created (eg: because it is brought in by a plugin), there is no
// guarantee this function will be called on the main thread.
// QCoreApplication::installTranslator needs to be called on the main
// thread, because it uses QCoreApplication::sendEvent.
if (QThread::currentThread() == QCoreApplication::instance()->thread()) {
load(LoadOptions::CreateWatcher);
} else {
// QObjects inherit their parent object's thread
Loader *loader = new Loader();
loader->moveToThread(QCoreApplication::instance()->thread());
QCoreApplication::instance()->postEvent(loader, new QTimerEvent(0), Qt::HighEventPriority);
}
}
}
Q_COREAPP_STARTUP_FUNCTION(loadOnMainThread)
|