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)
endif ()
find_package (Boost 1.63 REQUIRED)
if (Boost_FOUND)
include_directories (${Boost_INCLUDE_DIRS})
endif ()
#
# OpenMP
@ -889,10 +886,7 @@ message (STATUS "hamlib_LIBRARY_DIRS: ${hamlib_LIBRARY_DIRS}")
#
# Widgets finds its own dependencies.
find_package (Qt5Widgets 5 REQUIRED)
find_package (Qt5Multimedia 5 REQUIRED)
find_package (Qt5PrintSupport 5 REQUIRED)
find_package (Qt5Sql 5 REQUIRED)
find_package (Qt5 REQUIRED Widgets Multimedia PrintSupport Sql LinguistTools)
if (WIN32)
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})
# 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
function (add_resources resources path)
foreach (resource_file_ ${ARGN})
get_filename_component (name_ ${resource_file_} NAME)
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_)
set (resources_ "${resources_}\n <file alias=\"${dest_}\">${source_}</file>")
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 /Palettes ${PALETTE_FILES})
add_resources (wsjtx_RESOURCES /Translations ${QM_FILES})
configure_file (wsjtx.qrc.in wsjtx.qrc @ONLY)
@ -1131,7 +1156,6 @@ if (WIN32)
wrap_ax_server (GENAXSRCS ${AXSERVERSRCS})
endif (WIN32)
#
# targets
#

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -10,6 +10,7 @@
#include <QTemporaryFile>
#include <QDateTime>
#include <QApplication>
#include <QTranslator>
#include <QRegularExpression>
#include <QObject>
#include <QSettings>
@ -106,6 +107,34 @@ int main(int argc, char *argv[])
ExceptionCatchingApplication a(argc, argv);
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
// consistent format, do this after
// instantiating QApplication so

View File

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

View File

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

View File

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

View File

@ -7,8 +7,6 @@
#include <QModelIndex>
#include <QMetaType>
#include "moc_IARURegions.cpp"
namespace
{
// 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]);
}
#include "moc_IARURegions.cpp"
IARURegions::IARURegions (QObject * parent)
: QAbstractListModel {parent}
{

View File

@ -29,6 +29,7 @@ class IARURegions final
: public QAbstractListModel
{
Q_OBJECT
public:
//
// 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
: public QAbstractTableModel
{
Q_OBJECT
public:
impl (Bands const * bands, Stations stations, QObject * parent)
: QAbstractTableModel {parent}
@ -97,6 +99,9 @@ public:
Stations stations_;
};
#include "StationList.moc"
#include "moc_StationList.cpp"
StationList::StationList (Bands const * bands, QObject * parent)
: StationList {bands, {}, parent}
{

View File

@ -40,6 +40,8 @@ class Bands;
class StationList final
: public QSortFilterProxyModel
{
Q_OBJECT
public:
using Frequency = Radio::Frequency;
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 <QSettings>
#include <QObject>
#include <QString>
#include <QTableView>
#include <QHeaderView>
@ -16,7 +17,10 @@
#include "pimpl_impl.hpp"
class AbstractLogWindow::impl final
: public QObject
{
Q_OBJECT
public:
impl (AbstractLogWindow * self, QString const& settings_key, QSettings * settings
, Configuration const * configuration)
@ -38,6 +42,9 @@ public:
FontOverrideModel model_;
};
#include "moc_AbstractLogWindow.cpp"
#include "AbstractLogWindow.moc"
namespace
{
bool row_is_higher (QModelIndex const& lhs, QModelIndex const& rhs)

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -9,6 +9,8 @@ class QString;
class HelpTextWindow final
: public QLabel
{
Q_OBJECT
public:
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 "ui_messageaveraging.h"
#include "moc_messageaveraging.cpp"
MessageAveraging::MessageAveraging(QSettings * settings, QFont const& font, QWidget *parent) :
QWidget(parent),
settings_ {settings},

View File

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