[Companion] Translation system improvements. (#4676)
* [Companion] I18N:
* Introduce new Translations class to centralize all related functionality;
* Add ability to search multiple locations for .qm translation binaries (local folders, resources, system paths);
* Add ability to reload translations dynamically w/out application restart;
* Improve support for loading Qt translations (if available);
* [build][i18n] Look for and include pre-built Qt translations with other translation resources; Generate translations.qrc dynamically with rest of build files; Add EN "translation" file (simpler UI string edits and possible abstractions); Rename ZH translation file to be country-specific.
* [build] Centralize finding all the Qt bits into root CMakeLists; Make sure QT_QMAKE_EXECUTABLE is defined; Disable dysfunctional simulator installer script generation.
* Cosmetics (unused includes).
* [Companion] Make language options menu dynamic based on available translations, and always show native language name; Allow changing language of some elements w/out restarting (esp. menus/toolbar buttons); Simplify menus/actions/handlers for themes and icon sizes.
* [build] Better way to generate translations.qrc using input file again (previous method was generating new qrc for each reconfig); Make sure common library is linked to other modules which may need it; Remove unused script.
This commit is contained in:
committed by
Bertrand Songis
parent
d5560d68f4
commit
dcdbff74b0
@@ -0,0 +1,168 @@
|
||||
/*
|
||||
* Copyright (C) OpenTX
|
||||
*
|
||||
* Based on code named
|
||||
* th9x - http://code.google.com/p/th9x
|
||||
* er9x - http://code.google.com/p/er9x
|
||||
* gruvin9x - http://code.google.com/p/gruvin9x
|
||||
*
|
||||
* License GPLv2: http://www.gnu.org/licenses/gpl-2.0.html
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program 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.
|
||||
*/
|
||||
|
||||
#include "translations.h"
|
||||
#include "appdata.h"
|
||||
|
||||
#include <QCoreApplication>
|
||||
#include <QDir>
|
||||
#include <QLibraryInfo>
|
||||
#include <QTranslator>
|
||||
|
||||
// List of available Companion translations
|
||||
// todo: make dynamic eg. from directory listing
|
||||
// todo: make locale name country-agnostic unless translation is specifically for a country (like zh_CN)
|
||||
QStringList const Translations::getAvailableTranslations()
|
||||
{
|
||||
static QStringList locales;
|
||||
|
||||
if (!locales.size()) {
|
||||
locales << "cs_CZ"
|
||||
<< "de_DE"
|
||||
<< "en"
|
||||
<< "es_ES"
|
||||
<< "fi_FI"
|
||||
<< "fr_FR"
|
||||
//<< "he_IL"
|
||||
<< "it_IT"
|
||||
//<< "nl_NL"
|
||||
<< "pl_PL"
|
||||
//<< "pt_PT"
|
||||
//<< "ru_RU"
|
||||
<< "sv_SE"
|
||||
<< "zh_CN" ;
|
||||
}
|
||||
return locales;
|
||||
}
|
||||
|
||||
QStringList const Translations::getAvailableLanguages()
|
||||
{
|
||||
static QStringList languages;
|
||||
if (!languages.size()) {
|
||||
foreach (const QString & loc, getAvailableTranslations())
|
||||
languages.append(loc.left(2));
|
||||
}
|
||||
return languages;
|
||||
}
|
||||
|
||||
QStringList const Translations::getTranslationPaths()
|
||||
{
|
||||
// Look for translation files in the following locations, in order of priority
|
||||
QStringList paths;
|
||||
|
||||
// Prefer path set in environment variable, makes it possible to test/replace translations w/out rebuilding.
|
||||
if (qEnvironmentVariableIsSet("OPENTX_APP_TRANSLATIONS_PATH") && QDir(qgetenv("OPENTX_APP_TRANSLATIONS_PATH").constData()).exists()) {
|
||||
paths << qgetenv("OPENTX_APP_TRANSLATIONS_PATH").constData();
|
||||
}
|
||||
// Try application subfolder first, also eg. to test/replace translations quickly.
|
||||
paths << APP_TRANSLATIONS_FILE_PATH;
|
||||
// Then the resource file
|
||||
paths << APP_TRANSLATIONS_RESOURCE_PATH;
|
||||
// Finally the system folder (more likely for Qt translations than Companion ones)
|
||||
paths << QLibraryInfo::location(QLibraryInfo::TranslationsPath);
|
||||
|
||||
return paths;
|
||||
}
|
||||
|
||||
void Translations::installTranslators()
|
||||
{
|
||||
Q_INIT_RESOURCE(translations);
|
||||
|
||||
static QList<QTranslator *> appTranslators;
|
||||
|
||||
// Determine the locale
|
||||
|
||||
QLocale locale; // defaults to system locale
|
||||
if (!g.locale().isEmpty()) {
|
||||
locale = QLocale(g.locale()); // reverts to "C" locale if invalid
|
||||
if (locale.language() == QLocale::C) {
|
||||
// reset
|
||||
locale = QLocale::system();
|
||||
g.locale("");
|
||||
}
|
||||
}
|
||||
qDebug() << "Locale name:" << locale.name() << "language:" << locale.nativeLanguageName() << "country:" << locale.nativeCountryName();
|
||||
|
||||
// Remove any existing translators, this lets us re-translate w/out restart.
|
||||
foreach (QTranslator * t, appTranslators) {
|
||||
if (t) {
|
||||
QCoreApplication::removeTranslator(t);
|
||||
delete t;
|
||||
}
|
||||
}
|
||||
appTranslators.clear();
|
||||
|
||||
/* Multiple translation files can be installed.
|
||||
* Translations are searched for in the reverse order from which they were installed (last added is searched first).
|
||||
* The search stops as soon as a translation containing a matching string is found.
|
||||
*/
|
||||
|
||||
// Look for translation files in several locations
|
||||
QStringList tryPaths = getTranslationPaths();
|
||||
|
||||
// First try to install Qt translations for common GUI elements.
|
||||
|
||||
QStringList qtFiles = QStringList() << "qt";
|
||||
// After Qt5.3 some translation files are broken up into modules. We only need "qtbase" for now.
|
||||
#if (QT_VERSION >= QT_VERSION_CHECK(5, 3, 0))
|
||||
qtFiles << "qtbase";
|
||||
#endif
|
||||
|
||||
foreach (const QString & qtfile, qtFiles) {
|
||||
QTranslator * translator = new QTranslator(qApp);
|
||||
if (tryLoadTranslator(translator, locale, qtfile, tryPaths)) {
|
||||
appTranslators.append(translator);
|
||||
}
|
||||
else {
|
||||
delete translator;
|
||||
//qDebug() << "Could not find Qt translations for:" << locale.name() << "In file:" << qtfile << "Using paths:" << tryPaths;
|
||||
}
|
||||
}
|
||||
|
||||
// Now try to install our custom translations if we support the current locale/language.
|
||||
if (!getAvailableTranslations().contains(locale.name()) && !getAvailableLanguages().contains(locale.name().left(2)))
|
||||
return;
|
||||
|
||||
QTranslator * translator = new QTranslator(qApp);
|
||||
if (tryLoadTranslator(translator, locale, "companion", tryPaths)) {
|
||||
appTranslators.append(translator);
|
||||
}
|
||||
else {
|
||||
delete translator;
|
||||
qWarning() << "Could not find Companion translations for:" << locale.name() << "Using paths:" << tryPaths;
|
||||
}
|
||||
}
|
||||
|
||||
bool Translations::tryLoadTranslator(QTranslator * t, const QLocale & locale, const QString & baseFile, const QStringList & paths)
|
||||
{
|
||||
foreach (const QString & path, paths) {
|
||||
if (t->load(locale, baseFile, "_", path)) {
|
||||
if (QCoreApplication::installTranslator(t)) {
|
||||
qDebug() << "Installed translation file" << baseFile << "from" << path << "for" << locale.name();
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
qWarning() << "Error installing translation file" << baseFile << "for:" << locale.name() << "from:" << path;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
Reference in New Issue
Block a user