gnucash master: Fix translations using boost::locale::translate

Geert Janssens gjanssens at code.gnucash.org
Tue Jun 9 17:07:16 EDT 2020


Updated	 via  https://github.com/Gnucash/gnucash/commit/69a04be3 (commit)
	from  https://github.com/Gnucash/gnucash/commit/b311cc86 (commit)



commit 69a04be353c3fe5d58c1ec29bc2cdf1fd02410a9
Author: Geert Janssens <geert at kobaltwit.be>
Date:   Tue Jun 9 22:58:01 2020 +0200

    Fix translations using boost::locale::translate
    
    This requires a std::locale generated from a boost::locale::generator
    The examples already in our code base used the wrong message_path while
    creating the generator and as a result our message catalogs weren't found.
    
    As with the std::locale I have added code to create a locale via
    boost::locale only once instead of having each c++ file redo the work.
    
    This code expects a message_path to set for the boost generator.
    An earlier attempt queried for this path directly from within
    gnc-locale-utils using gnc_get_locale_dir (from gnc-path.h).
    
    That however broke several c++ tests depending on gnc_locale_utils as those
    then also needed to be linked against gnc-path.o. I couldn't get the linker
    to do this properly so I worked around it for now by splitting the boost_locale
    functionality in two steps:
    - an initializer step that takes the messages_path as a string and will
      generate the locale
    - a getter to get the locale.
    
    The initializer should only be run once, and before the getter is called.
    It won't hurt though if the initializer is called more often.
    If the getter is called before the initializer it will still
    generate a std::locale but without setting a messages_path. It will then
    also log a warning explaining translations may not be properly found.

diff --git a/gnucash/gnucash-core-app.cpp b/gnucash/gnucash-core-app.cpp
index a101e107b..a10d56abe 100644
--- a/gnucash/gnucash-core-app.cpp
+++ b/gnucash/gnucash-core-app.cpp
@@ -80,8 +80,6 @@ static int is_development_version = FALSE;
 #define GNC_VCS ""
 #endif
 
-
-
 static gchar *userdata_migration_msg = NULL;
 
 static void
@@ -503,6 +501,9 @@ Gnucash::CoreApp::CoreApp ()
     bind_textdomain_codeset("iso_4217", "UTF-8");
     textdomain(PROJECT_NAME);
     bind_textdomain_codeset(PROJECT_NAME, "UTF-8");
+
+    gnc_init_boost_locale (localedir);
+    std::cerr.imbue (gnc_get_boost_locale());
     g_free(localedir);
 }
 
@@ -514,7 +515,7 @@ Gnucash::CoreApp::CoreApp (const char* app_name)
     m_app_name = std::string(app_name);
 
     // Now that gettext is properly initialized, set our help tagline.
-    m_tagline = bl::translate("- GnuCash, accounting for personal and small business finance").str(gnc_get_locale());
+    m_tagline = bl::translate("- GnuCash, accounting for personal and small business finance").str(gnc_get_boost_locale());
     m_opt_desc = std::make_unique<bpo::options_description>
         ((bl::format (bl::gettext ("{1} [options] [datafile]")) % m_app_name).str() + std::string(" ") + m_tagline);
     add_common_program_options();
diff --git a/gnucash/gnucash.cpp b/gnucash/gnucash.cpp
index c0e06fff9..6b3bfdf8d 100644
--- a/gnucash/gnucash.cpp
+++ b/gnucash/gnucash.cpp
@@ -221,7 +221,7 @@ scm_run_gnucash (void *data, [[maybe_unused]] int argc, [[maybe_unused]] char **
     gnc_hook_add_dangler(HOOK_UI_SHUTDOWN, (GFunc)gnc_file_quit, NULL, NULL);
 
     /* Install Price Quote Sources */
-    auto msg = bl::translate ("Checking Finance::Quote...").str(gnc_get_locale());
+    auto msg = bl::translate ("Checking Finance::Quote...").str(gnc_get_boost_locale());
     gnc_update_splash_screen (msg.c_str(), GNC_SPLASH_PERCENTAGE_UNKNOWN);
     scm_c_use_module("gnucash price-quotes");
     scm_c_eval_string("(gnc:price-quotes-install-sources)");
@@ -230,7 +230,7 @@ scm_run_gnucash (void *data, [[maybe_unused]] int argc, [[maybe_unused]] char **
 
     if (!user_file_spec->nofile && (fn = get_file_to_load (user_file_spec->file_to_load)) && *fn )
     {
-        auto msg = bl::translate ("Loading data...").str(gnc_get_locale());
+        auto msg = bl::translate ("Loading data...").str(gnc_get_boost_locale());
         gnc_update_splash_screen (msg.c_str(), GNC_SPLASH_PERCENTAGE_UNKNOWN);
         gnc_file_open_file(gnc_get_splash_screen(), fn, /*open_readonly*/ FALSE);
         g_free(fn);
diff --git a/gnucash/import-export/csv-imp/assistant-csv-trans-import.cpp b/gnucash/import-export/csv-imp/assistant-csv-trans-import.cpp
index aff80c841..2ba5cc369 100644
--- a/gnucash/import-export/csv-imp/assistant-csv-trans-import.cpp
+++ b/gnucash/import-export/csv-imp/assistant-csv-trans-import.cpp
@@ -2103,7 +2103,7 @@ CsvImpTransAssist::assist_summary_page_prepare ()
     try
     {
     /* Translators: {1} will be replaced with a filename */
-      text += (bl::format (bl::translate ("The transactions were imported from file '{1}'.")) % m_file_name).str(gnc_get_locale());
+      text += (bl::format (bl::translate ("The transactions were imported from file '{1}'.")) % m_file_name).str(gnc_get_boost_locale());
         text += "</b></span>";
     }
     catch (const bl::conv::conversion_error& err)
diff --git a/libgnucash/core-utils/gnc-filepath-utils.cpp b/libgnucash/core-utils/gnc-filepath-utils.cpp
index d05297619..1089f09ed 100644
--- a/libgnucash/core-utils/gnc-filepath-utils.cpp
+++ b/libgnucash/core-utils/gnc-filepath-utils.cpp
@@ -594,7 +594,7 @@ static std::string migrate_gnc_datahome()
     gen.add_messages_domain(PROJECT_NAME);
 
     std::stringstream migration_msg;
-    migration_msg.imbue(gnc_get_locale());
+    migration_msg.imbue(gnc_get_boost_locale());
 
     /* Step 1: copy directory $HOME/.gnucash to $GNC_DATA_HOME */
     auto full_copy = copy_recursive (old_dir, gnc_userdata_home);
diff --git a/libgnucash/core-utils/gnc-locale-utils.cpp b/libgnucash/core-utils/gnc-locale-utils.cpp
index b7928e618..c55ac61f3 100644
--- a/libgnucash/core-utils/gnc-locale-utils.cpp
+++ b/libgnucash/core-utils/gnc-locale-utils.cpp
@@ -26,6 +26,7 @@ extern "C"
 #include <clocale>
 #include <boost/locale.hpp>
 #include "gnc-locale-utils.hpp"
+#include <config.h>
 
 /** Cache the UI locale
  *
@@ -72,3 +73,48 @@ gnc_get_locale()
 }
 
 
+static std::locale boost_cached;
+static bool tried_boost_already = false;
+
+void
+gnc_init_boost_locale (const std::string& messages_path)
+{
+    if (!tried_boost_already)
+    {
+        tried_boost_already = true;
+
+        try
+        {
+            boost::locale::generator gen;
+            if (!messages_path.empty())
+                gen.add_messages_path(messages_path);
+            else
+                g_log(G_LOG_DOMAIN, G_LOG_LEVEL_WARNING,
+                      "Attempt to initialize boost_locale without a message_path. "
+                      "If message catalogs are not installed in the system's default locations "
+                      "user interface strings will not be translated.");
+            gen.add_messages_domain(PROJECT_NAME);
+            boost_cached = gen ("");
+        }
+        catch (const std::runtime_error& err)
+        {
+            char* locale = g_strdup(setlocale(LC_ALL, ""));
+
+            g_log(G_LOG_DOMAIN, G_LOG_LEVEL_WARNING,
+                  "Failed to create C++ default locale from"
+                  "%s because %s. Using the 'C' locale for C++.",
+                  locale, err.what());
+            boost_cached = std::locale::classic();
+        }
+    }
+}
+
+
+
+const std::locale&
+gnc_get_boost_locale()
+{
+    return boost_cached;
+}
+
+
diff --git a/libgnucash/core-utils/gnc-locale-utils.hpp b/libgnucash/core-utils/gnc-locale-utils.hpp
index c16467eb4..1ef8d1d68 100644
--- a/libgnucash/core-utils/gnc-locale-utils.hpp
+++ b/libgnucash/core-utils/gnc-locale-utils.hpp
@@ -23,6 +23,7 @@
 #define GNC_LOCALE_UTILS_HPP
 
 #include <locale>
+#include <string>
 
 /** Get the default application locale.
  *
@@ -36,4 +37,30 @@
  */
 const std::locale& gnc_get_locale();
 
+
+
+/** Create  default boost locale.
+ *
+ *  std::locale has very limited used on Windows so for translation work we rely
+ *  on boost::locale instead.  Calling boost::locale("") is expensive,
+ *  so call gnc_get_boost_locale instead.
+ *
+ * However before that funcation can be called the locale should be initialized
+ * with gnc_init_boost_locale.
+ */
+void gnc_init_boost_locale(const std::string& messages_path);
+
+
+
+/** Get the default boost locale.
+ *
+ *  std::locale has very limited used on Windows so for translation work we rely
+ *  on boost::locale instead.  Calling boost::locale("") is expensive,
+ *  so call this instead.
+ *
+ *  @returns A static std::locale representing the one set with
+ *  setlocale() in main(), but generated from boost::locale.
+ */
+const std::locale& gnc_get_boost_locale();
+
 #endif /* GNC_LOCALE_UTILS_HPP */



Summary of changes:
 gnucash/gnucash-core-app.cpp                       |  7 ++--
 gnucash/gnucash.cpp                                |  4 +-
 .../csv-imp/assistant-csv-trans-import.cpp         |  2 +-
 libgnucash/core-utils/gnc-filepath-utils.cpp       |  2 +-
 libgnucash/core-utils/gnc-locale-utils.cpp         | 46 ++++++++++++++++++++++
 libgnucash/core-utils/gnc-locale-utils.hpp         | 27 +++++++++++++
 6 files changed, 81 insertions(+), 7 deletions(-)



More information about the gnucash-changes mailing list