Browse Source

Automated the ingestion of localization from Crowdin

Automated the generation of language resources into the application
Added all languages that come from Crowdin, even if empty.
Allow dynamic language changes
QGC4.4
Gus Grubba 6 years ago
parent
commit
78d2525b8f
  1. 1
      .gitignore
  2. 4
      ChangeLog.md
  3. 26
      localization/README.md
  4. 5
      localization/build.sh
  5. 15
      localization/from-crowdin.py
  6. 1
      localization/qgc.qm
  7. BIN
      localization/qgc_bg.qm
  8. 13832
      localization/qgc_bg.ts
  9. BIN
      localization/qgc_de-DE.qm
  10. 13830
      localization/qgc_de.ts
  11. 13832
      localization/qgc_el.ts
  12. 0
      localization/qgc_en.ts
  13. 13832
      localization/qgc_es_ES.ts
  14. 13832
      localization/qgc_fi.ts
  15. 13828
      localization/qgc_fr.ts
  16. BIN
      localization/qgc_fr_FR.qm
  17. 13832
      localization/qgc_he.ts
  18. BIN
      localization/qgc_it.qm
  19. 13832
      localization/qgc_it.ts
  20. 13832
      localization/qgc_ja.ts
  21. BIN
      localization/qgc_ko.qm
  22. 13835
      localization/qgc_ko.ts
  23. 13832
      localization/qgc_nl.ts
  24. 13832
      localization/qgc_no.ts
  25. 13832
      localization/qgc_pl.ts
  26. 13832
      localization/qgc_pt_PT.ts
  27. BIN
      localization/qgc_ru.qm
  28. 13830
      localization/qgc_ru.ts
  29. 13832
      localization/qgc_sv_SE.ts
  30. BIN
      localization/qgc_tr.qm
  31. 13813
      localization/qgc_tr.ts
  32. BIN
      localization/qgc_zh-CN.qm
  33. 2
      localization/qgc_zh_CN.ts
  34. 2
      localization/to-crowdin.sh
  35. 10
      qgcresources.qrc
  36. 8
      qgroundcontrol.pro
  37. 95
      src/QGCApplication.cc
  38. 1
      src/QGCApplication.h
  39. 4
      src/Settings/App.SettingsGroup.json
  40. 8
      src/Settings/UnitsSettings.cc

1
.gitignore vendored

@ -55,6 +55,7 @@ libs/thirdParty/libxbee/lib/ @@ -55,6 +55,7 @@ libs/thirdParty/libxbee/lib/
GeneratedFiles/
gstreamer-1.0-android*
src/Airmap/Airmap_api_key.h
localization/qgroundcontrol/
*.autosave
.settings/

4
ChangeLog.md

@ -6,6 +6,10 @@ Note: This file only contains high level features or important fixes. @@ -6,6 +6,10 @@ Note: This file only contains high level features or important fixes.
### 3.6.0 - Daily Build
* Automated the ingestion of localization from Crowdin
* Automated the generation of language resources into the application
* Added all languages that come from Crowdin, even if empty.
* Allow dynamic language changes
* Check and respect camera storage status
* QGC now requires Qt 5.11 or greater. The idea is to standardize on Qt 5.12 (LTS). Just waiting for a solution for Windows as Qt dropped support for 32-bit.
* New, QtQuick MAVLink Inspector. The basics are already there but it still needs the ability to filter compID.

26
localization/README.md

@ -1,25 +1,5 @@ @@ -1,25 +1,5 @@
To generate (or update) a source translation file, use the "lupdate" command line tool. It can be found in the Qt distribution.
To generate (or update) a source translation file, use the `to-crowdin.sh` script in this directory. You will need to update the path to Qt within it.
(Easiest to just run the `gen_translation_source.sh` script, or get the commands from within the script and run them manually)
This will parse all the source files and generate a language translation file called qgc.ts, which should be uploaded to crowdin.
This will parse all the source files and generate a language translation file called qgc.ts. This file should be copied into whatever language it is to be translated to and sent to translation. The translation can either be done directly within the (XML) file, using Qt's "Linguist" tool, or uploaded to crowdin.
For instance, to localize to Germany German as an example you first copy the original source:
```
cp qgc.ts qgc_de-DE.ts
```
The German localization is then performed in qgc_de-DE.ts
Once localization is complete, you "compile" it using the "lrelease" command line tool.
```
lrelease qgc_de-DE.ts
```
This will generate the ("compiled") localization file `qgc_de-DE.qm`, which should be shipped with QGroundControl.
Further documentation can be found at:
http://doc.qt.io/qt-5/qtlinguist-index.html
Note about crowdin:
If you build the project and download the resulting ZIP file, the translated (.ts) files all come with the same name "qgc.ts". They each reside in a different directory named after the language for which it was translated into. Care must be taken to rename these files before moving them to the locale directory so you don't override the original, English source file.
Once translations have been done/updated, within Crowdin "Build and Download". Extract the resulting qgroundcontro.zip here and run `from-crowdin.py`.

5
localization/build.sh

@ -1,5 +0,0 @@ @@ -1,5 +0,0 @@
#!/bin/bash
for f in *.ts
do
/Users/gus/Applications/Qt/5.11.2/clang_64/bin/lrelease $f
done

15
localization/from-crowdin.py

@ -0,0 +1,15 @@ @@ -0,0 +1,15 @@
#!/usr/bin/env python
import os
from shutil import copyfile
# When you "Build and Download" from Crowdin, you endup with a qgroundcontro.zip file.
# It is assumed this zip file has been extracted into ./qgroundcontrol
for lang in os.listdir("./qgroundcontrol"):
srcFile = os.path.join("./qgroundcontrol", lang, "qgc.ts")
if(os.path.exists(srcFile)):
lang = lang.replace("-","_")
dstFile = "./qgc" + "_" + lang + ".ts"
print("qgc" + "_" + lang + ".ts")
copyfile(srcFile, dstFile)

1
localization/qgc.qm

@ -1 +0,0 @@ @@ -1 +0,0 @@
<クd<EFBFBD>箆!ソ`。スン

BIN
localization/qgc_bg.qm

Binary file not shown.

13832
localization/qgc_bg.ts

File diff suppressed because it is too large Load Diff

BIN
localization/qgc_de-DE.qm

Binary file not shown.

13830
localization/qgc_de.ts

File diff suppressed because it is too large Load Diff

13832
localization/qgc_el.ts

File diff suppressed because it is too large Load Diff

0
localization/qgc.ts → localization/qgc_en.ts

13832
localization/qgc_es_ES.ts

File diff suppressed because it is too large Load Diff

13832
localization/qgc_fi.ts

File diff suppressed because it is too large Load Diff

13828
localization/qgc_fr.ts

File diff suppressed because it is too large Load Diff

BIN
localization/qgc_fr_FR.qm

Binary file not shown.

13832
localization/qgc_he.ts

File diff suppressed because it is too large Load Diff

BIN
localization/qgc_it.qm

Binary file not shown.

13832
localization/qgc_it.ts

File diff suppressed because it is too large Load Diff

13832
localization/qgc_ja.ts

File diff suppressed because it is too large Load Diff

BIN
localization/qgc_ko.qm

Binary file not shown.

13835
localization/qgc_ko.ts

File diff suppressed because it is too large Load Diff

13832
localization/qgc_nl.ts

File diff suppressed because it is too large Load Diff

13832
localization/qgc_no.ts

File diff suppressed because it is too large Load Diff

13832
localization/qgc_pl.ts

File diff suppressed because it is too large Load Diff

13832
localization/qgc_pt_PT.ts

File diff suppressed because it is too large Load Diff

BIN
localization/qgc_ru.qm

Binary file not shown.

13830
localization/qgc_ru.ts

File diff suppressed because it is too large Load Diff

13832
localization/qgc_sv_SE.ts

File diff suppressed because it is too large Load Diff

BIN
localization/qgc_tr.qm

Binary file not shown.

13813
localization/qgc_tr.ts

File diff suppressed because it is too large Load Diff

BIN
localization/qgc_zh-CN.qm

Binary file not shown.

2
localization/qgc_zh-CN.ts → localization/qgc_zh_CN.ts

@ -4796,7 +4796,7 @@ propellers on the green thrusters and counter-clockwise propellers on the blue t @@ -4796,7 +4796,7 @@ propellers on the green thrusters and counter-clockwise propellers on the blue t
<message>
<location filename="../src/VehicleSetup/FirmwareUpgradeController.cc" line="512"/>
<source>Firmware Files (*.px4 *.bin *.ihx)</source>
<translation>*.px4 *.bin *.ihx</translation>
<translation> (*.px4 *.bin *.ihx)</translation>
</message>
<message>
<location filename="../src/VehicleSetup/FirmwareUpgradeController.cc" line="517"/>

2
localization/gen_translation_source.sh → localization/to-crowdin.sh

@ -1,5 +1,5 @@ @@ -1,5 +1,5 @@
#!/bin/bash
# This is set to find lupdate in my particular installation. You will need to set the path
# where you have Qt installed.
QT_PATH=~/Applications/Qt/5.11.0/clang_64/bin
QT_PATH=~/Applications/Qt/5.12.3/clang_64/bin
$QT_PATH/lupdate ../src -ts qgc.ts

10
qgcresources.qrc

@ -1,14 +1,4 @@ @@ -1,14 +1,4 @@
<RCC>
<qresource prefix="/localization">
<file alias="qgc_bg.qm">localization/qgc_bg.qm</file>
<file alias="qgc_de_DE.qm">localization/qgc_de-DE.qm</file>
<file alias="qgc_fr_FR.qm">localization/qgc_fr_FR.qm</file>
<file alias="qgc_it.qm">localization/qgc_it.qm</file>
<file alias="qgc_ko.qm">localization/qgc_ko.qm</file>
<file alias="qgc_ru.qm">localization/qgc_ru.qm</file>
<file alias="qgc_tr.qm">localization/qgc_tr.qm</file>
<file alias="qgc_zh_CN.qm">localization/qgc_zh-CN.qm</file>
</qresource>
<qresource prefix="/fonts">
<file alias="opensans">resources/fonts/OpenSans-Regular.ttf</file>
<file alias="opensans-demibold">resources/fonts/OpenSans-Semibold.ttf</file>

8
qgroundcontrol.pro

@ -1218,6 +1218,14 @@ AndroidBuild { @@ -1218,6 +1218,14 @@ AndroidBuild {
#-------------------------------------------------------------------------------------
#
# Localization
#
TRANSLATIONS += $$files($$PWD/localization/qgc_*.ts)
CONFIG+=lrelease embed_translations
#-------------------------------------------------------------------------------------
#
# Post link configuration
#

95
src/QGCApplication.cc

@ -357,37 +357,86 @@ void QGCApplication::setLanguage() @@ -357,37 +357,86 @@ void QGCApplication::setLanguage()
if(langID) {
switch(langID) {
case 1:
locale = QLocale(QLocale::English);
locale = QLocale(QLocale::Bulgarian);
break;
case 2:
locale = QLocale(QLocale::Bulgarian);
locale = QLocale(QLocale::Chinese);
break;
case 3:
locale = QLocale(QLocale::German);
locale = QLocale(QLocale::Dutch);
break;
case 4:
locale = QLocale(QLocale::French);
locale = QLocale(QLocale::English);
break;
case 5:
locale = QLocale(QLocale::Italian);
locale = QLocale(QLocale::Finnish);
break;
case 6:
locale = QLocale(QLocale::Korean);
locale = QLocale(QLocale::French);
break;
case 7:
locale = QLocale(QLocale::Russian);
locale = QLocale(QLocale::German);
break;
case 8:
locale = QLocale(QLocale::Turkish);
locale = QLocale(QLocale::Greek);
break;
case 9:
locale = QLocale(QLocale::Chinese);
locale = QLocale(QLocale::Hebrew);
break;
case 10:
locale = QLocale(QLocale::Italian);
break;
case 11:
locale = QLocale(QLocale::Japanese);
break;
case 12:
locale = QLocale(QLocale::Korean);
if(QFontDatabase::addApplicationFont(":/fonts/NanumGothic-Regular") < 0) {
qWarning() << "Could not load /fonts/NanumGothic-Regular font";
}
if(QFontDatabase::addApplicationFont(":/fonts/NanumGothic-Bold") < 0) {
qWarning() << "Could not load /fonts/NanumGothic-Bold font";
}
break;
case 13:
locale = QLocale(QLocale::Norwegian);
break;
case 14:
locale = QLocale(QLocale::Polish);
break;
case 15:
locale = QLocale(QLocale::Portuguese);
break;
case 16:
locale = QLocale(QLocale::Russian);
break;
case 17:
locale = QLocale(QLocale::Spanish);
break;
case 18:
locale = QLocale(QLocale::Swedish);
break;
case 19:
locale = QLocale(QLocale::Turkish);
break;
}
}
//-- Our localization
if(_QGCTranslator.load(locale, "qgc_", "", ":/localization"))
qDebug() << "Loading localization for" << locale.name();
_app->removeTranslator(&_QGCTranslator);
_app->removeTranslator(&_QGCTranslatorQt);
if(_QGCTranslatorQt.load("qt_" + locale.name(), QLibraryInfo::location(QLibraryInfo::TranslationsPath))) {
_app->installTranslator(&_QGCTranslatorQt);
} else {
qDebug() << "Error loading Qt localization for" << locale.name();
}
if(_QGCTranslator.load(locale, QLatin1String("qgc_"), "", ":/i18n")) {
QLocale::setDefault(locale);
_app->installTranslator(&_QGCTranslator);
} else {
qDebug() << "Error loading application localization for" << locale.name();
}
if(_qmlAppEngine)
_qmlAppEngine->retranslate();
}
void QGCApplication::_shutdown()
@ -476,23 +525,11 @@ void QGCApplication::_initCommon() @@ -476,23 +525,11 @@ void QGCApplication::_initCommon()
bool QGCApplication::_initForNormalAppBoot()
{
//-- See App.SettinsGroup.json for index
int langID = toolbox()->settingsManager()->appSettings()->language()->rawValue().toInt();
//-- Load font appropriate for the language
if(langID == 6 /*Korean*/) {
if(QFontDatabase::addApplicationFont(":/fonts/NanumGothic-Regular") < 0) {
qWarning() << "Could not load /fonts/NanumGothic-Regular font";
}
if(QFontDatabase::addApplicationFont(":/fonts/NanumGothic-Bold") < 0) {
qWarning() << "Could not load /fonts/NanumGothic-Bold font";
}
} else {
if(QFontDatabase::addApplicationFont(":/fonts/opensans") < 0) {
qWarning() << "Could not load /fonts/opensans font";
}
if(QFontDatabase::addApplicationFont(":/fonts/opensans-demibold") < 0) {
qWarning() << "Could not load /fonts/opensans-demibold font";
}
if(QFontDatabase::addApplicationFont(":/fonts/opensans") < 0) {
qWarning() << "Could not load /fonts/opensans font";
}
if(QFontDatabase::addApplicationFont(":/fonts/opensans-demibold") < 0) {
qWarning() << "Could not load /fonts/opensans-demibold font";
}
QSettings settings;
@ -782,7 +819,7 @@ void QGCApplication::_onGPSDisconnect() @@ -782,7 +819,7 @@ void QGCApplication::_onGPSDisconnect()
void QGCApplication::_gpsSurveyInStatus(float duration, float accuracyMM, double latitude, double longitude, float altitude, bool valid, bool active)
{
_gpsRtkFactGroup->currentDuration()->setRawValue(duration);
_gpsRtkFactGroup->currentAccuracy()->setRawValue(accuracyMM/1000.0);
_gpsRtkFactGroup->currentAccuracy()->setRawValue(static_cast<double>(accuracyMM) / 1000.0);
_gpsRtkFactGroup->currentLatitude()->setRawValue(latitude);
_gpsRtkFactGroup->currentLongitude()->setRawValue(longitude);
_gpsRtkFactGroup->currentAltitude()->setRawValue(altitude);

1
src/QGCApplication.h

@ -183,6 +183,7 @@ private: @@ -183,6 +183,7 @@ private:
QQuickItem* _mainRootWindow = nullptr;
bool _bluetoothAvailable = false;
QTranslator _QGCTranslator;
QTranslator _QGCTranslatorQt;
static const char* _settingsVersionKey; ///< Settings key which hold settings version
static const char* _deleteAllSettingsKey; ///< If this settings key is set on boot, all settings will be deleted

4
src/Settings/App.SettingsGroup.json

@ -239,8 +239,8 @@ @@ -239,8 +239,8 @@
"name": "language",
"shortDescription": "Language",
"type": "uint32",
"enumStrings": "System,English,български (Bulgarian),Deutsche (German),Français (French),Italiano (Italian),한국어 (Korean),Pусский (Russian),Türk (Turkish),中文 (Chinese)",
"enumValues": "0,1,2,3,4,5,6,7,8,9",
"enumStrings": "System,български (Bulgarian),中文 (Chinese),Nederlands (Dutch),English,Suomi (Finnish),Français (French),Deutsche (German),Ελληνικά (Greek), עברית (Hebrew),Italiano (Italian),日本人 (Japanese),한국어 (Korean),Norsk (Norwegian),Polskie (Polish),Português (Portuguese),Pусский (Russian),Español (Spanish),Svenska (Swedish),Türk (Turkish)",
"enumValues": "0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19",
"defaultValue": 0
},
{

8
src/Settings/UnitsSettings.cc

@ -27,7 +27,7 @@ DECLARE_SETTINGSFACT_NO_FUNC(UnitsSettings, distanceUnits) @@ -27,7 +27,7 @@ DECLARE_SETTINGSFACT_NO_FUNC(UnitsSettings, distanceUnits)
enumValues << QVariant::fromValue(static_cast<uint32_t>(DistanceUnitsFeet)) << QVariant::fromValue(static_cast<uint32_t>(DistanceUnitsMeters));
FactMetaData* metaData = new FactMetaData(FactMetaData::valueTypeUint32, this);
metaData->setName(distanceUnitsName);
metaData->setShortDescription(tr("Distance units"));
metaData->setShortDescription("Distance units");
metaData->setEnumInfo(enumStrings, enumValues);
metaData->setRawDefaultValue(DistanceUnitsMeters);
metaData->setQGCRebootRequired(true);
@ -52,7 +52,7 @@ DECLARE_SETTINGSFACT_NO_FUNC(UnitsSettings, areaUnits) @@ -52,7 +52,7 @@ DECLARE_SETTINGSFACT_NO_FUNC(UnitsSettings, areaUnits)
QVariant::fromValue(static_cast<uint32_t>(AreaUnitsSquareMiles));
FactMetaData* metaData = new FactMetaData(FactMetaData::valueTypeUint32, this);
metaData->setName(areaUnitsName);
metaData->setShortDescription(tr("Area units"));
metaData->setShortDescription("Area units");
metaData->setEnumInfo(enumStrings, enumValues);
metaData->setRawDefaultValue(AreaUnitsSquareMeters);
metaData->setQGCRebootRequired(true);
@ -76,7 +76,7 @@ DECLARE_SETTINGSFACT_NO_FUNC(UnitsSettings, speedUnits) @@ -76,7 +76,7 @@ DECLARE_SETTINGSFACT_NO_FUNC(UnitsSettings, speedUnits)
QVariant::fromValue(static_cast<uint32_t>(SpeedUnitsKnots));
FactMetaData* metaData = new FactMetaData(FactMetaData::valueTypeUint32, this);
metaData->setName(speedUnitsName);
metaData->setShortDescription(tr("Speed units"));
metaData->setShortDescription("Speed units");
metaData->setEnumInfo(enumStrings, enumValues);
metaData->setRawDefaultValue(SpeedUnitsMetersPerSecond);
metaData->setQGCRebootRequired(true);
@ -95,7 +95,7 @@ DECLARE_SETTINGSFACT_NO_FUNC(UnitsSettings, temperatureUnits) @@ -95,7 +95,7 @@ DECLARE_SETTINGSFACT_NO_FUNC(UnitsSettings, temperatureUnits)
enumValues << QVariant::fromValue(static_cast<uint32_t>(TemperatureUnitsCelsius)) << QVariant::fromValue(static_cast<uint32_t>(TemperatureUnitsFarenheit));
FactMetaData* metaData = new FactMetaData(FactMetaData::valueTypeUint32, this);
metaData->setName(temperatureUnitsName);
metaData->setShortDescription(tr("Temperature units"));
metaData->setShortDescription("Temperature units");
metaData->setEnumInfo(enumStrings, enumValues);
metaData->setRawDefaultValue(TemperatureUnitsCelsius);
metaData->setQGCRebootRequired(true);

Loading…
Cancel
Save