diff options
-rw-r--r-- | .reuse/dep5 | 4 | ||||
-rw-r--r-- | NEWS | 3 | ||||
-rw-r--r-- | meson.build | 16 | ||||
-rw-r--r-- | meson/suppressions/meson.build | 1 | ||||
-rw-r--r-- | po/LINGUAS | 2 | ||||
-rw-r--r-- | po/POTFILES | 60 | ||||
-rw-r--r-- | po/meson.build | 27 | ||||
-rw-r--r-- | po/patchage.pot | 155 | ||||
-rw-r--r-- | src/CanvasModule.cpp | 6 | ||||
-rw-r--r-- | src/CanvasPort.hpp | 3 | ||||
-rw-r--r-- | src/Legend.cpp | 3 | ||||
-rw-r--r-- | src/Patchage.cpp | 37 | ||||
-rw-r--r-- | src/i18n.hpp | 15 | ||||
-rw-r--r-- | src/main.cpp | 11 | ||||
-rw-r--r-- | src/patchage.ui.in | 6 | ||||
-rw-r--r-- | src/patchage_config.h | 19 |
16 files changed, 344 insertions, 24 deletions
diff --git a/.reuse/dep5 b/.reuse/dep5 index 7749513..5bfac99 100644 --- a/.reuse/dep5 +++ b/.reuse/dep5 @@ -30,3 +30,7 @@ License: CC-BY-SA-4.0 OR GPL-3.0-or-later Files: icons/*.png icons/*.svg Copyright: 2007-2011 David Robillard <d@drobilla.net> License: CC-BY-SA-4.0 OR GPL-3.0-or-later + +Files: po/patchage.pot +Copyright: 2022 David Robillard <d@drobilla.net> +License: GPL-3.0-or-later @@ -1,9 +1,10 @@ patchage (1.0.9) unstable; urgency=medium + * Add i18n support * Replace boost with standard C++17 facilities * Upgrade to fmt 9.0.0 - -- David Robillard <d@drobilla.net> Mon, 22 Aug 2022 17:07:17 +0000 + -- David Robillard <d@drobilla.net> Tue, 23 Aug 2022 02:49:17 +0000 patchage (1.0.8) stable; urgency=medium diff --git a/meson.build b/meson.build index b49a56b..e5a5969 100644 --- a/meson.build +++ b/meson.build @@ -37,10 +37,12 @@ add_project_arguments(['-DFMT_HEADER_ONLY'], language: ['cpp']) ########################## patchage_datadir = get_option('prefix') / get_option('datadir') / 'patchage' +patchage_localedir = get_option('prefix') / get_option('localedir') platform_defines = [ '-DPATCHAGE_VERSION="@0@"'.format(meson.project_version()), '-DPATCHAGE_DATA_DIR="@0@"'.format(patchage_datadir), + '-DPATCHAGE_LOCALE_DIR="@0@"'.format(patchage_localedir), ] if host_machine.system() in ['gnu', 'linux'] @@ -53,6 +55,9 @@ if get_option('checks') dladdr_code = '''#include <dlfcn.h> int main(void) { Dl_info info; return dladdr(&info, &info); }''' + gettext_code = '''#include <libintl.h> +int main(void) { return !!gettext("hello"); }''' + jack_metadata_code = '''#include <jack/metadata.h> int main(void) { return !!&jack_set_property; }''' @@ -65,6 +70,11 @@ int main(void) { return !!&jack_set_property; }''' platform_defines += ['-DHAVE_DLADDR=0'] endif + platform_defines += '-DHAVE_GETTEXT=@0@'.format( + cpp.compiles(gettext_code, + args: platform_defines, + name: 'gettext').to_int()) + platform_defines += '-DHAVE_JACK_METADATA=@0@'.format( cpp.compiles(jack_metadata_code, args: platform_defines, @@ -160,6 +170,12 @@ if jack_dep.found() and dbus_dep.found() and dbus_glib_dep.found() message('Both libjack and D-Bus available, defaulting to libjack') endif +####################### +# Translations (i18n) # +####################### + +subdir('po') + ########### # Program # ########### diff --git a/meson/suppressions/meson.build b/meson/suppressions/meson.build index 8292d77..0875ccd 100644 --- a/meson/suppressions/meson.build +++ b/meson/suppressions/meson.build @@ -18,6 +18,7 @@ if is_variable('cpp') if cpp.get_id() == 'clang' cpp_suppressions += [ '-Wno-alloca', + '-Wno-c++20-compat', '-Wno-cast-qual', '-Wno-double-promotion', '-Wno-float-conversion', diff --git a/po/LINGUAS b/po/LINGUAS new file mode 100644 index 0000000..ebf3dcb --- /dev/null +++ b/po/LINGUAS @@ -0,0 +1,2 @@ +# Copyright 2022 David Robillard <d@drobilla.net> +# SPDX-License-Identifier: CC0-1.0 OR GPL-3.0-or-later diff --git a/po/POTFILES b/po/POTFILES new file mode 100644 index 0000000..0f392b7 --- /dev/null +++ b/po/POTFILES @@ -0,0 +1,60 @@ +# Copyright 2022 David Robillard <d@drobilla.net> +# SPDX-License-Identifier: CC0-1.0 OR GPL-3.0-or-later + +src/Action.hpp +src/ActionSink.hpp +src/AlsaDriver.cpp +src/AlsaStubDriver.cpp +src/AudioDriver.hpp +src/Canvas.cpp +src/Canvas.hpp +src/CanvasModule.cpp +src/CanvasModule.hpp +src/CanvasPort.hpp +src/ClientID.hpp +src/ClientInfo.hpp +src/ClientType.hpp +src/Configuration.cpp +src/Configuration.hpp +src/Coord.hpp +src/Driver.hpp +src/Drivers.cpp +src/Drivers.hpp +src/Event.hpp +src/ILog.hpp +src/JackDbusDriver.cpp +src/JackLibDriver.cpp +src/JackStubDriver.cpp +src/Legend.cpp +src/Legend.hpp +src/Metadata.cpp +src/Metadata.hpp +src/Options.hpp +src/Patchage.cpp +src/Patchage.hpp +src/PortID.hpp +src/PortInfo.hpp +src/PortNames.hpp +src/PortType.hpp +src/Reactor.cpp +src/Reactor.hpp +src/Setting.hpp +src/SignalDirection.hpp +src/TextViewLog.cpp +src/TextViewLog.hpp +src/UIFile.hpp +src/Widget.hpp +src/binary_location.h +src/event_to_string.cpp +src/event_to_string.hpp +src/handle_event.cpp +src/handle_event.hpp +src/jackey.h +src/main.cpp +src/make_alsa_driver.hpp +src/make_jack_driver.hpp +# src/patchage.gladep +# src/patchage.svg +src/patchage.ui.in +src/patchage_config.h +src/warnings.hpp diff --git a/po/meson.build b/po/meson.build new file mode 100644 index 0000000..689ed1b --- /dev/null +++ b/po/meson.build @@ -0,0 +1,27 @@ +# Copyright 2020-2022 David Robillard <d@drobilla.net> +# SPDX-License-Identifier: CC0-1.0 OR GPL-3.0-or-later + +i18n = import('i18n') + +add_project_arguments( + ['-DGETTEXT_PACKAGE="@0@"'.format(meson.project_name())], + language: 'cpp', +) + +i18n.gettext( + meson.project_name(), + args: [ + '--add-comments', + '--check=bullet-unicode', + '--check=ellipsis-unicode', + '--check=quote-unicode', + '--check=space-ellipsis', + '--copyright-holder=FULL NAME <EMAIL@ADDRESS>', + '--from-code=UTF-8', + '--msgid-bugs-address=https://gitlab.com/drobilla/patchage/issues/new', + '--package-version=@0@'.format(meson.project_version()), + '--sentence-end=double-space', + '--sort-by-file', + '--width=80', + ], +) diff --git a/po/patchage.pot b/po/patchage.pot new file mode 100644 index 0000000..e12cf8f --- /dev/null +++ b/po/patchage.pot @@ -0,0 +1,155 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR FULL NAME <EMAIL@ADDRESS> +# This file is distributed under the same license as the patchage package. +# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR. +# +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: patchage 1.0.9\n" +"Report-Msgid-Bugs-To: https://gitlab.com/drobilla/patchage/issues/new\n" +"POT-Creation-Date: 2022-08-23 00:52-0400\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" +"Language-Team: LANGUAGE <LL@li.org>\n" +"Language: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" + +#: src/CanvasModule.cpp:93 +msgid "_Split" +msgstr "" + +#: src/CanvasModule.cpp:97 +msgid "_Join" +msgstr "" + +#: src/CanvasModule.cpp:101 +msgid "_Disconnect" +msgstr "" + +#: src/CanvasPort.hpp:86 +msgid "Disconnect" +msgstr "" + +#: src/Legend.cpp:27 +msgid "Audio" +msgstr "" + +#: src/Patchage.cpp:453 +msgid "frames at {} kHz ({:0.2f} ms)" +msgstr "" + +#: src/Patchage.cpp:475 src/Patchage.cpp:510 src/patchage.ui.in:391 +msgid "Dropouts: {}" +msgstr "" + +#: src/Patchage.cpp:838 +msgid "Export Image" +msgstr "" + +#: src/Patchage.cpp:860 +msgid "Draw _Background" +msgstr "" + +#: src/Patchage.cpp:871 +msgid "File exists! Overwrite {}?" +msgstr "" + +#: src/patchage.ui.in:21 +msgid "_File" +msgstr "" + +#: src/patchage.ui.in:30 +msgid "_Export Image…" +msgstr "" + +#: src/patchage.ui.in:60 +msgid "_System" +msgstr "" + +#: src/patchage.ui.in:67 +msgid "Connect to _JACK" +msgstr "" + +#: src/patchage.ui.in:78 +msgid "Disconnect from JACK" +msgstr "" + +#: src/patchage.ui.in:95 +msgid "Connect to _ALSA" +msgstr "" + +#: src/patchage.ui.in:106 +msgid "Disconnect from ALSA" +msgstr "" + +#: src/patchage.ui.in:123 +msgid "_View" +msgstr "" + +#: src/patchage.ui.in:132 +msgid "_Messages" +msgstr "" + +#: src/patchage.ui.in:141 +msgid "Tool_bar" +msgstr "" + +#: src/patchage.ui.in:157 +msgid "_Human Names" +msgstr "" + +#: src/patchage.ui.in:167 +msgid "_Sort Ports by Name" +msgstr "" + +#: src/patchage.ui.in:230 +msgid "_Increase Font Size" +msgstr "" + +#: src/patchage.ui.in:239 +msgid "_Decrease Font Size" +msgstr "" + +#: src/patchage.ui.in:248 +msgid "_Normal Font Size" +msgstr "" + +#: src/patchage.ui.in:272 +msgid "_Arrange" +msgstr "" + +#: src/patchage.ui.in:285 +msgid "Sprung Layou_t" +msgstr "" + +#: src/patchage.ui.in:298 +msgid "_Help" +msgstr "" + +#: src/patchage.ui.in:341 +msgid "JACK buffer size and sample rate." +msgstr "" + +#: src/patchage.ui.in:353 +msgid "JACK buffer length in frames." +msgstr "" + +#: src/patchage.ui.in:365 +msgid "frames at ? kHz (? ms)" +msgstr "" + +#: src/patchage.ui.in:405 +msgid "Clear dropout indicator." +msgstr "" + +#: src/patchage.ui.in:505 +msgid "A modular patchbay for JACK and ALSA applications." +msgstr "" + +#. TRANSLATORS: Replace this string with your names, one name per line. +#: src/patchage.ui.in:1183 +msgid "translator-credits" +msgstr "" diff --git a/src/CanvasModule.cpp b/src/CanvasModule.cpp index d3908df..e93cefe 100644 --- a/src/CanvasModule.cpp +++ b/src/CanvasModule.cpp @@ -90,15 +90,15 @@ CanvasModule::show_menu(GdkEventButton* ev) if (_type == SignalDirection::duplex) { items.push_back(Gtk::Menu_Helpers::MenuElem( - "_Split", sigc::mem_fun(this, &CanvasModule::on_split))); + _("_Split"), sigc::mem_fun(this, &CanvasModule::on_split))); update_menu(); } else { items.push_back(Gtk::Menu_Helpers::MenuElem( - "_Join", sigc::mem_fun(this, &CanvasModule::on_join))); + _("_Join"), sigc::mem_fun(this, &CanvasModule::on_join))); } items.push_back(Gtk::Menu_Helpers::MenuElem( - "_Disconnect", sigc::mem_fun(this, &CanvasModule::on_disconnect))); + _("_Disconnect"), sigc::mem_fun(this, &CanvasModule::on_disconnect))); _menu->popup(ev->button, ev->time); return true; diff --git a/src/CanvasPort.hpp b/src/CanvasPort.hpp index 548c9e5..c3195a9 100644 --- a/src/CanvasPort.hpp +++ b/src/CanvasPort.hpp @@ -6,6 +6,7 @@ #include "PortID.hpp" #include "PortType.hpp" +#include "i18n.hpp" #include "warnings.hpp" PATCHAGE_DISABLE_GANV_WARNINGS @@ -82,7 +83,7 @@ public: Gtk::Menu* menu = Gtk::manage(new Gtk::Menu()); menu->items().push_back(Gtk::Menu_Helpers::MenuElem( - "Disconnect", sigc::mem_fun(this, &Port::disconnect))); + _("Disconnect"), sigc::mem_fun(this, &Port::disconnect))); menu->popup(ev->button.button, ev->button.time); return true; diff --git a/src/Legend.cpp b/src/Legend.cpp index bdf51bc..a4e8705 100644 --- a/src/Legend.cpp +++ b/src/Legend.cpp @@ -5,6 +5,7 @@ #include "Configuration.hpp" #include "PortType.hpp" +#include "i18n.hpp" #include "patchage_config.h" #include <gdkmm/color.h> @@ -23,7 +24,7 @@ namespace patchage { Legend::Legend(const Configuration& configuration) { add_button(PortType::jack_audio, - "Audio", + _("Audio"), configuration.get_port_color(PortType::jack_audio)); #if USE_JACK_METADATA diff --git a/src/Patchage.cpp b/src/Patchage.cpp index 1f3d706..c3166c2 100644 --- a/src/Patchage.cpp +++ b/src/Patchage.cpp @@ -23,6 +23,7 @@ #include "Widget.hpp" #include "event_to_string.hpp" #include "handle_event.hpp" +#include "i18n.hpp" #include "patchage_config.h" // IWYU pragma: keep #include "warnings.hpp" @@ -445,11 +446,14 @@ Patchage::update_toolbar() const auto buffer_size = _drivers.jack()->buffer_size(); const auto sample_rate = _drivers.jack()->sample_rate(); if (sample_rate != 0) { - const auto latency_ms = - buffer_size * 1000 / static_cast<float>(sample_rate); + const auto sample_rate_khz = sample_rate / 1000.0; + const auto latency_ms = buffer_size / sample_rate_khz; + + _latency_label->set_label(" " + + fmt::format(_("frames at {} kHz ({:0.2f} ms)"), + sample_rate_khz, + latency_ms)); - _latency_label->set_label(fmt::format( - " frames @ {} kHz ({:0.2f} ms)", sample_rate / 1000, latency_ms)); _latency_label->set_visible(true); _buf_size_combo->set_active( static_cast<int>(log2f(_drivers.jack()->buffer_size()) - 5)); @@ -467,12 +471,13 @@ Patchage::update_load() { if (_drivers.jack() && _drivers.jack()->is_attached()) { const auto xruns = _drivers.jack()->xruns(); + + _dropouts_label->set_text(" " + fmt::format(_("Dropouts: {}"), xruns)); + if (xruns > 0u) { - _dropouts_label->set_text(fmt::format(" Dropouts: {}", xruns)); _dropouts_label->show(); _clear_load_but->show(); } else { - _dropouts_label->set_text(" Dropouts: 0"); _dropouts_label->hide(); _clear_load_but->hide(); } @@ -502,7 +507,7 @@ Patchage::store_window_location() void Patchage::clear_load() { - _dropouts_label->set_text(" Dropouts: 0"); + _dropouts_label->set_text(" " + fmt::format(_("Dropouts: {}"), 0U)); _dropouts_label->hide(); _clear_load_but->hide(); if (_drivers.jack()) { @@ -830,7 +835,9 @@ Patchage::on_quit() void Patchage::on_export_image() { - Gtk::FileChooserDialog dialog("Export Image", Gtk::FILE_CHOOSER_ACTION_SAVE); + Gtk::FileChooserDialog dialog(_("Export Image"), + Gtk::FILE_CHOOSER_ACTION_SAVE); + dialog.add_button(Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL); dialog.add_button(Gtk::Stock::SAVE, Gtk::RESPONSE_OK); dialog.set_default_response(Gtk::RESPONSE_OK); @@ -850,7 +857,7 @@ Patchage::on_export_image() dialog.add_filter(filt); } - auto* bg_but = new Gtk::CheckButton("Draw _Background", true); + auto* bg_but = new Gtk::CheckButton(_("Draw _Background"), true); auto* extra = new Gtk::Alignment(1.0, 0.5, 0.0, 0.0); bg_but->set_active(true); extra->add(*Gtk::manage(bg_but)); @@ -860,12 +867,12 @@ Patchage::on_export_image() if (dialog.run() == Gtk::RESPONSE_OK) { const std::string filename = dialog.get_filename(); if (Glib::file_test(filename, Glib::FILE_TEST_EXISTS)) { - Gtk::MessageDialog confirm(std::string("File exists! Overwrite ") + - filename + "?", - true, - Gtk::MESSAGE_WARNING, - Gtk::BUTTONS_YES_NO, - true); + Gtk::MessageDialog confirm( + fmt::format(_("File exists! Overwrite {}?"), filename), + true, + Gtk::MESSAGE_WARNING, + Gtk::BUTTONS_YES_NO, + true); confirm.set_transient_for(dialog); if (confirm.run() != Gtk::RESPONSE_YES) { return; diff --git a/src/i18n.hpp b/src/i18n.hpp new file mode 100644 index 0000000..4cf082d --- /dev/null +++ b/src/i18n.hpp @@ -0,0 +1,15 @@ +// Copyright 2022 David Robillard <d@drobilla.net> +// SPDX-License-Identifier: GPL-3.0-or-later + +#ifndef PATCHAGE_I18N_HPP +#define PATCHAGE_I18N_HPP + +#include <libintl.h> + +/// Mark a string literal as translatable +#define _(msgid) gettext(msgid) + +/// Mark a string literal as non-translatable +// #define N_(msgid) (msgid) + +#endif // PATCHAGE_I18N_HPP diff --git a/src/main.cpp b/src/main.cpp index 4466e15..d76413f 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -21,6 +21,10 @@ #include <glibmm/ustring.h> #include <gtkmm/main.h> +#if USE_GETTEXT +# include <libintl.h> +#endif + #include <cstring> #include <exception> #include <iostream> @@ -94,6 +98,13 @@ main(int argc, char** argv) set_bundle_environment(); #endif +#if USE_GETTEXT + setlocale(LC_ALL, ""); + bindtextdomain("patchage", PATCHAGE_LOCALE_DIR); + bind_textdomain_codeset("patchage", "UTF-8"); + textdomain("patchage"); +#endif + try { Glib::thread_init(); diff --git a/src/patchage.ui.in b/src/patchage.ui.in index c63566a..89d749d 100644 --- a/src/patchage.ui.in +++ b/src/patchage.ui.in @@ -362,7 +362,7 @@ <child> <object class="GtkLabel" id="latency_label"> <property name="can_focus">False</property> - <property name="label" translatable="yes">frames @ ? kHz (? ms)</property> + <property name="label" translatable="yes">frames at ? kHz (? ms)</property> </object> <packing> <property name="expand">False</property> @@ -388,7 +388,7 @@ <object class="GtkLabel" id="dropouts_label"> <property name="can_focus">False</property> <property name="visible">False</property> - <property name="label" translatable="yes"> Dropouts: 0</property> + <property name="label" translatable="yes">Dropouts: {}</property> </object> </child> </object> @@ -502,7 +502,7 @@ <property name="version">@PATCHAGE_VERSION@</property> <property name="copyright" translatable="no">© 2005-2022 David Robillard © 2008 Nedko Arnaudov</property> - <property name="comments" translatable="yes">A JACK and ALSA front-end.</property> + <property name="comments" translatable="yes">A modular patchbay for JACK and ALSA applications.</property> <property name="website">http://drobilla.net/software/patchage</property> <property name="license" translatable="no"> GNU GENERAL PUBLIC LICENSE Version 3, 29 June 2007 diff --git a/src/patchage_config.h b/src/patchage_config.h index e5f56df..6c3ad90 100644 --- a/src/patchage_config.h +++ b/src/patchage_config.h @@ -46,6 +46,19 @@ # endif # endif +// GNU gettext() +# ifndef HAVE_GETTEXT +# ifdef __has_include +# if __has_include(<libintl.h>) +# define HAVE_GETTEXT 1 +# else +# define HAVE_GETTEXT 0 +# endif +# else +# define HAVE_GETTEXT 0 +# endif +# endif + // JACK metadata API # ifndef HAVE_JACK_METADATA # ifdef __has_include @@ -75,6 +88,12 @@ # define USE_DLADDR 0 #endif +#if HAVE_GETTEXT +# define USE_GETTEXT 1 +#else +# define USE_GETTEXT 0 +#endif + #if HAVE_JACK_METADATA # define USE_JACK_METADATA 1 #else |