diff --git a/gnucash/gnucash-core-app.cpp b/gnucash/gnucash-core-app.cpp index a101e107ba..a10d56abe1 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 ((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 c0e06fff9f..6b3bfdf8db 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 aff80c8419..2ba5cc3693 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 += ""; } 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 d052976191..1089f09ed3 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 b7928e6188..c55ac61f35 100644 --- a/libgnucash/core-utils/gnc-locale-utils.cpp +++ b/libgnucash/core-utils/gnc-locale-utils.cpp @@ -26,6 +26,7 @@ extern "C" #include #include #include "gnc-locale-utils.hpp" +#include /** 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 c16467eb46..1ef8d1d687 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 +#include /** 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 */