Preparation for UI i18n

Re-enabling the WSJT-X i18n  facilities. This allows translation files
to  be created  for languages  that are  automatically used  to lookup
translatable strings. To enable a  new language the language name must
be added to the CMakeLists.txt LANGUAGES list variable in BCP47 format
(i.e. en_US,  en_GB, pt_PT, ...). Do  one build with the  CMake option
UPDATE_TRANSLATIONS enabled  (do not  leave it enabled  as there  is a
danger of loosing existing translated texts), that will create a fresh
translations/wsjtx_<lang>.ts file which  should be immediately checked
in with the  CMakeLists.txt change. The .ts should then  be updated by
the translator using  the Qt Linguist tool to  add translations. Check
in the  updated .ts file  to complete the initial  translation process
for that language.

To  aid translators  their WIP  .ts file  may be  tested by  releasing
(using the  lrelease tool or  from the Linguist  menu) a .qm  file and
placing  that  .qm  file  in the  current  directory  before  starting
WSJT-X. The translations will be used if the system locale matches the
file name.   If the system  locale does not  match the file  name; the
language may be  overridden by setting the  LANG environment variable.
For  example if  a wsjtx_pt_PT.qm  file  is in  the current  directory
WSJT-X will use it for  translation lookups, regardless of the current
system locale setting, if the LANG variable is set to pt_PT or pt-PT.

On MS Windows from a command prompt:

 set LANG=pt_PT
 C:\WSJT\wsjtx\bin\wsjtx

elsewhere:

 LANG=pt_PT wsjtx
This commit is contained in:
Bill Somerville 2019-06-06 12:56:25 +01:00
parent b985d41591
commit 45b12e6028
No known key found for this signature in database
GPG Key ID: D864B06D1E81618F
30 changed files with 12142 additions and 14 deletions

View File

@ -856,9 +856,6 @@ if (Boost_NO_SYSTEM_PATHS)
set (BOOST_ROOT ${PROJECT_SOURCE_DIR}/boost) set (BOOST_ROOT ${PROJECT_SOURCE_DIR}/boost)
endif () endif ()
find_package (Boost 1.63 REQUIRED) find_package (Boost 1.63 REQUIRED)
if (Boost_FOUND)
include_directories (${Boost_INCLUDE_DIRS})
endif ()
# #
# OpenMP # OpenMP
@ -889,10 +886,7 @@ message (STATUS "hamlib_LIBRARY_DIRS: ${hamlib_LIBRARY_DIRS}")
# #
# Widgets finds its own dependencies. # Widgets finds its own dependencies.
find_package (Qt5Widgets 5 REQUIRED) find_package (Qt5 REQUIRED Widgets Multimedia PrintSupport Sql LinguistTools)
find_package (Qt5Multimedia 5 REQUIRED)
find_package (Qt5PrintSupport 5 REQUIRED)
find_package (Qt5Sql 5 REQUIRED)
if (WIN32) if (WIN32)
add_definitions (-DQT_NEEDS_QTMAIN) add_definitions (-DQT_NEEDS_QTMAIN)
@ -1098,11 +1092,41 @@ add_custom_target (ctags COMMAND ${CTAGS} -o ${CMAKE_SOURCE_DIR}/tags -R ${sourc
add_custom_target (etags COMMAND ${ETAGS} -o ${CMAKE_SOURCE_DIR}/TAGS -R ${sources}) add_custom_target (etags COMMAND ${ETAGS} -o ${CMAKE_SOURCE_DIR}/TAGS -R ${sources})
# Qt i18n
set (LANGUAGES
en_GB
pt_PT
)
foreach (lang_ ${LANGUAGES})
file (TO_NATIVE_PATH translations/wsjtx_${lang_}.ts ts_)
list (APPEND TS_FILES ${ts_})
endforeach ()
if (UPDATE_TRANSLATIONS)
message (STATUS "UPDATE_TRANSLATIONS option is set.")
qt5_create_translation (
QM_FILES ${wsjt_qt_UISRCS} ${wsjtx_UISRCS} ${wsjt_qt_CXXSRCS} ${wsjtx_CXXSRCS}
${TS_FILES}
)
else ()
qt5_add_translation (QM_FILES ${TS_FILES})
endif ()
add_custom_target (translations DEPENDS ${QM_FILES})
set_property (DIRECTORY PROPERTY CLEAN_NO_CUSTOM TRUE)
# do this after i18n to stop lupdate walking the boost tree which it
# chokes on
if (Boost_FOUND)
include_directories (${Boost_INCLUDE_DIRS})
endif ()
# embedded resources # embedded resources
function (add_resources resources path) function (add_resources resources path)
foreach (resource_file_ ${ARGN}) foreach (resource_file_ ${ARGN})
get_filename_component (name_ ${resource_file_} NAME) get_filename_component (name_ ${resource_file_} NAME)
file (TO_NATIVE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/${resource_file_} source_) if (IS_ABSOLUTE "${resource_file_}")
file (TO_NATIVE_PATH ${resource_file_} source_)
else ()
file (TO_NATIVE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/${resource_file_} source_)
endif ()
file (TO_NATIVE_PATH ${path}/${name_} dest_) file (TO_NATIVE_PATH ${path}/${name_} dest_)
set (resources_ "${resources_}\n <file alias=\"${dest_}\">${source_}</file>") set (resources_ "${resources_}\n <file alias=\"${dest_}\">${source_}</file>")
set (${resources} ${${resources}}${resources_} PARENT_SCOPE) set (${resources} ${${resources}}${resources_} PARENT_SCOPE)
@ -1111,6 +1135,7 @@ endfunction (add_resources resources path)
add_resources (wsjtx_RESOURCES "" ${TOP_LEVEL_RESOURCES}) add_resources (wsjtx_RESOURCES "" ${TOP_LEVEL_RESOURCES})
add_resources (wsjtx_RESOURCES /Palettes ${PALETTE_FILES}) add_resources (wsjtx_RESOURCES /Palettes ${PALETTE_FILES})
add_resources (wsjtx_RESOURCES /Translations ${QM_FILES})
configure_file (wsjtx.qrc.in wsjtx.qrc @ONLY) configure_file (wsjtx.qrc.in wsjtx.qrc @ONLY)
@ -1131,7 +1156,6 @@ if (WIN32)
wrap_ax_server (GENAXSRCS ${AXSERVERSRCS}) wrap_ax_server (GENAXSRCS ${AXSERVERSRCS})
endif (WIN32) endif (WIN32)
# #
# targets # targets
# #

View File

@ -251,6 +251,8 @@ namespace
class FrequencyDialog final class FrequencyDialog final
: public QDialog : public QDialog
{ {
Q_OBJECT
public: public:
using Item = FrequencyList_v2::Item; using Item = FrequencyList_v2::Item;
@ -297,6 +299,8 @@ private:
class StationDialog final class StationDialog final
: public QDialog : public QDialog
{ {
Q_OBJECT
public: public:
explicit StationDialog (StationList const * stations, Bands * bands, QWidget * parent = nullptr) explicit StationDialog (StationList const * stations, Bands * bands, QWidget * parent = nullptr)
: QDialog {parent} : QDialog {parent}

View File

@ -1,5 +1,7 @@
#include "EmulateSplitTransceiver.hpp" #include "EmulateSplitTransceiver.hpp"
#include "moc_EmulateSplitTransceiver.cpp"
EmulateSplitTransceiver::EmulateSplitTransceiver (std::unique_ptr<Transceiver> wrapped, QObject * parent) EmulateSplitTransceiver::EmulateSplitTransceiver (std::unique_ptr<Transceiver> wrapped, QObject * parent)
: Transceiver {parent} : Transceiver {parent}
, wrapped_ {std::move (wrapped)} , wrapped_ {std::move (wrapped)}

View File

@ -27,6 +27,8 @@
class EmulateSplitTransceiver final class EmulateSplitTransceiver final
: public Transceiver : public Transceiver
{ {
Q_OBJECT
public: public:
// takes ownership of wrapped Transceiver // takes ownership of wrapped Transceiver
explicit EmulateSplitTransceiver (std::unique_ptr<Transceiver> wrapped, explicit EmulateSplitTransceiver (std::unique_ptr<Transceiver> wrapped,

View File

@ -19,6 +19,8 @@ namespace
int constexpr yaesu_delay {250}; int constexpr yaesu_delay {250};
} }
#include "moc_HRDTransceiver.cpp"
void HRDTransceiver::register_transceivers (TransceiverFactory::Transceivers * registry, int id) void HRDTransceiver::register_transceivers (TransceiverFactory::Transceivers * registry, int id)
{ {
(*registry)[HRD_transceiver_name] = TransceiverFactory::Capabilities (id, TransceiverFactory::Capabilities::network, true, true /* maybe */); (*registry)[HRD_transceiver_name] = TransceiverFactory::Capabilities (id, TransceiverFactory::Capabilities::network, true, true /* maybe */);

View File

@ -27,6 +27,8 @@ class QByteArray;
class HRDTransceiver final class HRDTransceiver final
: public PollingTransceiver : public PollingTransceiver
{ {
Q_OBJECT
public: public:
static void register_transceivers (TransceiverFactory::Transceivers *, int id); static void register_transceivers (TransceiverFactory::Transceivers *, int id);

View File

@ -21,9 +21,9 @@ extern "C"
class HamlibTransceiver final class HamlibTransceiver final
: public PollingTransceiver : public PollingTransceiver
{ {
Q_OBJECT; // for translation context Q_OBJECT // for translation context
public: public:
static void register_transceivers (TransceiverFactory::Transceivers *); static void register_transceivers (TransceiverFactory::Transceivers *);
static void unregister_transceivers (); static void unregister_transceivers ();

View File

@ -65,6 +65,8 @@ namespace
class NameDialog final class NameDialog final
: public QDialog : public QDialog
{ {
Q_OBJECT
public: public:
explicit NameDialog (QString const& current_name, explicit NameDialog (QString const& current_name,
QStringList const& current_names, QStringList const& current_names,
@ -112,6 +114,8 @@ namespace
class ExistingNameDialog final class ExistingNameDialog final
: public QDialog : public QDialog
{ {
Q_OBJECT
public: public:
explicit ExistingNameDialog (QStringList const& current_names, QWidget * parent = nullptr) explicit ExistingNameDialog (QStringList const& current_names, QWidget * parent = nullptr)
: QDialog {parent} : QDialog {parent}

View File

@ -44,6 +44,8 @@ namespace
class Dialog class Dialog
: public QDialog : public QDialog
{ {
Q_OBJECT
public: public:
using BandList = QList<QString>; using BandList = QList<QString>;
@ -69,6 +71,8 @@ private:
static int constexpr band_index_role {Qt::UserRole}; static int constexpr band_index_role {Qt::UserRole};
}; };
#include "WSPRBandHopping.moc"
Dialog::Dialog (QSettings * settings, Configuration const * configuration, BandList const * WSPR_bands Dialog::Dialog (QSettings * settings, Configuration const * configuration, BandList const * WSPR_bands
, QBitArray * bands, int * gray_line_duration, QWidget * parent) , QBitArray * bands, int * gray_line_duration, QWidget * parent)
: QDialog {parent, Qt::Window | Qt::WindowTitleHint | Qt::WindowCloseButtonHint | Qt::WindowMinimizeButtonHint} : QDialog {parent, Qt::Window | Qt::WindowTitleHint | Qt::WindowCloseButtonHint | Qt::WindowMinimizeButtonHint}

View File

@ -8,7 +8,8 @@
#ifdef __cplusplus #ifdef __cplusplus
#include <cstdbool> #include <cstdbool>
extern "C" { extern "C" {
#else #endif
#ifndef __cplusplus
#include <stdbool.h> #include <stdbool.h>
#endif #endif

View File

@ -10,6 +10,7 @@
#include <QTemporaryFile> #include <QTemporaryFile>
#include <QDateTime> #include <QDateTime>
#include <QApplication> #include <QApplication>
#include <QTranslator>
#include <QRegularExpression> #include <QRegularExpression>
#include <QObject> #include <QObject>
#include <QSettings> #include <QSettings>
@ -106,6 +107,34 @@ int main(int argc, char *argv[])
ExceptionCatchingApplication a(argc, argv); ExceptionCatchingApplication a(argc, argv);
try try
{ {
//
// Enable i18n
//
QTranslator translator_from_resources;
// Default translations for releases use translations stored in
// the resources file system under the Translations
// directory. These are built by the CMake build system from .ts
// files in the translations source directory. New languages are
// added by enabling the UPDATE_TRANSLATIONS CMake option and
// building with the new language added to the LANGUAGES CMake
// list variable. UPDATE_TRANSLATIONS will preserve existing
// translations but should only be set when adding new
// languages. The resulting .ts files should be checked info
// source control for translators to access and update.
translator_from_resources.load (QLocale::system (), "wsjtx", "_", ":/Translations");
a.installTranslator (&translator_from_resources);
QTranslator translator_from_files;
// Load any matching translation from the current directory
// using the locale name. This allows translators to easily test
// their translations by releasing (lrelease) a .qm file into
// the current directory with a suitable name
// (e.g. wsjtx_en_GB.qm), then running wsjtx to view the
// results. Either the system locale setting or the environment
// variable LANG can be used to select the target language.
translator_from_files.load (QString {"wsjtx_"} + QLocale::system ().name ());
a.installTranslator (&translator_from_files);
setlocale (LC_NUMERIC, "C"); // ensure number forms are in setlocale (LC_NUMERIC, "C"); // ensure number forms are in
// consistent format, do this after // consistent format, do this after
// instantiating QApplication so // instantiating QApplication so

View File

@ -55,6 +55,8 @@ namespace
} }
} }
#include "moc_Bands.cpp"
Bands::Bands (QObject * parent) Bands::Bands (QObject * parent)
: QAbstractTableModel {parent} : QAbstractTableModel {parent}
{ {

View File

@ -29,6 +29,8 @@
class Bands final class Bands final
: public QAbstractTableModel : public QAbstractTableModel
{ {
Q_OBJECT
public: public:
using Frequency = Radio::Frequency; using Frequency = Radio::Frequency;

View File

@ -18,6 +18,8 @@
class FoxLog::impl final class FoxLog::impl final
: public QSqlTableModel : public QSqlTableModel
{ {
Q_OBJECT
public: public:
impl (Configuration const * configuration); impl (Configuration const * configuration);
@ -43,6 +45,8 @@ public:
QSqlQuery mutable export_query_; QSqlQuery mutable export_query_;
}; };
#include "FoxLog.moc"
FoxLog::impl::impl (Configuration const * configuration) FoxLog::impl::impl (Configuration const * configuration)
: configuration_ {configuration} : configuration_ {configuration}
{ {

View File

@ -7,8 +7,6 @@
#include <QModelIndex> #include <QModelIndex>
#include <QMetaType> #include <QMetaType>
#include "moc_IARURegions.cpp"
namespace namespace
{ {
// human readable strings for each Region enumeration value // human readable strings for each Region enumeration value
@ -22,6 +20,8 @@ namespace
std::size_t constexpr region_names_size = sizeof (region_names) / sizeof (region_names[0]); std::size_t constexpr region_names_size = sizeof (region_names) / sizeof (region_names[0]);
} }
#include "moc_IARURegions.cpp"
IARURegions::IARURegions (QObject * parent) IARURegions::IARURegions (QObject * parent)
: QAbstractListModel {parent} : QAbstractListModel {parent}
{ {

View File

@ -29,6 +29,7 @@ class IARURegions final
: public QAbstractListModel : public QAbstractListModel
{ {
Q_OBJECT Q_OBJECT
public: public:
// //
// This enumeration contains the supported regions, to complement // This enumeration contains the supported regions, to complement

View File

@ -52,6 +52,8 @@ QDataStream& operator >> (QDataStream& is, StationList::Station& station)
class StationList::impl final class StationList::impl final
: public QAbstractTableModel : public QAbstractTableModel
{ {
Q_OBJECT
public: public:
impl (Bands const * bands, Stations stations, QObject * parent) impl (Bands const * bands, Stations stations, QObject * parent)
: QAbstractTableModel {parent} : QAbstractTableModel {parent}
@ -97,6 +99,9 @@ public:
Stations stations_; Stations stations_;
}; };
#include "StationList.moc"
#include "moc_StationList.cpp"
StationList::StationList (Bands const * bands, QObject * parent) StationList::StationList (Bands const * bands, QObject * parent)
: StationList {bands, {}, parent} : StationList {bands, {}, parent}
{ {

View File

@ -40,6 +40,8 @@ class Bands;
class StationList final class StationList final
: public QSortFilterProxyModel : public QSortFilterProxyModel
{ {
Q_OBJECT
public: public:
using Frequency = Radio::Frequency; using Frequency = Radio::Frequency;
using FrequencyDelta = Radio::FrequencyDelta; using FrequencyDelta = Radio::FrequencyDelta;

6007
translations/wsjtx_en_GB.ts Normal file

File diff suppressed because it is too large Load Diff

6007
translations/wsjtx_pt_PT.ts Normal file

File diff suppressed because it is too large Load Diff

View File

@ -2,6 +2,7 @@
#include <algorithm> #include <algorithm>
#include <QSettings> #include <QSettings>
#include <QObject>
#include <QString> #include <QString>
#include <QTableView> #include <QTableView>
#include <QHeaderView> #include <QHeaderView>
@ -16,7 +17,10 @@
#include "pimpl_impl.hpp" #include "pimpl_impl.hpp"
class AbstractLogWindow::impl final class AbstractLogWindow::impl final
: public QObject
{ {
Q_OBJECT
public: public:
impl (AbstractLogWindow * self, QString const& settings_key, QSettings * settings impl (AbstractLogWindow * self, QString const& settings_key, QSettings * settings
, Configuration const * configuration) , Configuration const * configuration)
@ -38,6 +42,9 @@ public:
FontOverrideModel model_; FontOverrideModel model_;
}; };
#include "moc_AbstractLogWindow.cpp"
#include "AbstractLogWindow.moc"
namespace namespace
{ {
bool row_is_higher (QModelIndex const& lhs, QModelIndex const& rhs) bool row_is_higher (QModelIndex const& lhs, QModelIndex const& rhs)

View File

@ -19,6 +19,8 @@ class QFont;
class AbstractLogWindow class AbstractLogWindow
: public QWidget : public QWidget
{ {
Q_OBJECT
public: public:
AbstractLogWindow (QString const& settings_key, QSettings * settings AbstractLogWindow (QString const& settings_key, QSettings * settings
, Configuration const * configuration , Configuration const * configuration

View File

@ -6,6 +6,8 @@
#include "models/DecodeHighlightingModel.hpp" #include "models/DecodeHighlightingModel.hpp"
#include "MessageBox.hpp" #include "MessageBox.hpp"
#include "moc_DecodeHighlightingListView.cpp"
DecodeHighlightingListView::DecodeHighlightingListView (QWidget * parent) DecodeHighlightingListView::DecodeHighlightingListView (QWidget * parent)
: QListView {parent} : QListView {parent}
{ {

View File

@ -16,6 +16,8 @@ class QWidget;
class DecodeHighlightingListView final class DecodeHighlightingListView final
: public QListView : public QListView
{ {
Q_OBJECT
public: public:
explicit DecodeHighlightingListView (QWidget * parent = nullptr); explicit DecodeHighlightingListView (QWidget * parent = nullptr);

View File

@ -11,6 +11,7 @@
#include "models/CabrilloLog.hpp" #include "models/CabrilloLog.hpp"
#include "ui_ExportCabrillo.h" #include "ui_ExportCabrillo.h"
#include "moc_ExportCabrillo.cpp"
ExportCabrillo::ExportCabrillo (QSettings * settings, Configuration const * configuration ExportCabrillo::ExportCabrillo (QSettings * settings, Configuration const * configuration
, CabrilloLog const * log, QWidget * parent) , CabrilloLog const * log, QWidget * parent)

View File

@ -15,6 +15,8 @@ namespace Ui {
class ExportCabrillo final class ExportCabrillo final
: public QDialog : public QDialog
{ {
Q_OBJECT
public: public:
explicit ExportCabrillo (QSettings *, Configuration const * explicit ExportCabrillo (QSettings *, Configuration const *
, CabrilloLog const *, QWidget * parent = nullptr); , CabrilloLog const *, QWidget * parent = nullptr);

View File

@ -9,6 +9,8 @@
#include "qt_helpers.hpp" #include "qt_helpers.hpp"
#include "widgets/MessageBox.hpp" #include "widgets/MessageBox.hpp"
#include "moc_HelpTextWindow.cpp"
HelpTextWindow::HelpTextWindow (QString const& title, QString const& file_name, QFont const& font, QWidget * parent) HelpTextWindow::HelpTextWindow (QString const& title, QString const& file_name, QFont const& font, QWidget * parent)
: QLabel {parent, Qt::WindowCloseButtonHint | Qt::WindowMinimizeButtonHint} : QLabel {parent, Qt::WindowCloseButtonHint | Qt::WindowMinimizeButtonHint}
{ {

View File

@ -9,6 +9,8 @@ class QString;
class HelpTextWindow final class HelpTextWindow final
: public QLabel : public QLabel
{ {
Q_OBJECT
public: public:
HelpTextWindow (QString const& title, QString const& file_name, QFont const& = QFont {}, QWidget * parent = nullptr); HelpTextWindow (QString const& title, QString const& file_name, QFont const& = QFont {}, QWidget * parent = nullptr);
}; };

View File

@ -8,6 +8,8 @@
#include "qt_helpers.hpp" #include "qt_helpers.hpp"
#include "ui_messageaveraging.h" #include "ui_messageaveraging.h"
#include "moc_messageaveraging.cpp"
MessageAveraging::MessageAveraging(QSettings * settings, QFont const& font, QWidget *parent) : MessageAveraging::MessageAveraging(QSettings * settings, QFont const& font, QWidget *parent) :
QWidget(parent), QWidget(parent),
settings_ {settings}, settings_ {settings},

View File

@ -14,6 +14,8 @@ namespace Ui {
class MessageAveraging class MessageAveraging
: public QWidget : public QWidget
{ {
Q_OBJECT
public: public:
explicit MessageAveraging(QSettings *, QFont const&, QWidget * parent = 0); explicit MessageAveraging(QSettings *, QFont const&, QWidget * parent = 0);
~MessageAveraging(); ~MessageAveraging();