diff --git a/src/about.cpp b/src/about.cpp index f97d852d4e5a..050e4bcf1727 100644 --- a/src/about.cpp +++ b/src/about.cpp @@ -38,7 +38,6 @@ #include "video.hpp" // for update_rect, CVideo #include "widgets/button.hpp" // for button -#include // for gettext #include // for max #include // for auto_any_base, etc #include // for scoped_ptr @@ -105,7 +104,7 @@ static void add_lines(std::vector &res, config const &c, bool split if (!line.empty()) { if (line[0] == '_') - line = gettext(line.substr(1).c_str()); + line = translation::gettext(line.substr(1).c_str()); res.push_back(line); } } @@ -176,7 +175,7 @@ void set_about(const config &cfg) { text << '+'; if (subtitle[0] == '_') - text << gettext(subtitle.substr(1, subtitle.size() - 1).c_str()); + text << translation::gettext(subtitle.substr(1, subtitle.size() - 1).c_str()); else text << subtitle; text << '\n'; diff --git a/src/addon/manager_ui.cpp b/src/addon/manager_ui.cpp index c21a28aa26db..416bc492027e 100644 --- a/src/addon/manager_ui.cpp +++ b/src/addon/manager_ui.cpp @@ -890,8 +890,8 @@ void show_addons_manager_dialog(display& disp, addons_client& client, addons_lis } } - const char* msg_title = NULL; - const char* msg_text = NULL; + std::string msg_title; + std::string msg_text; // Use the Update terminology when using Update All or working with the // Upgradable add-ons view. diff --git a/src/editor/map/context_manager.cpp b/src/editor/map/context_manager.cpp index 8e6877b44958..35da608b4b6e 100644 --- a/src/editor/map/context_manager.cpp +++ b/src/editor/map/context_manager.cpp @@ -870,7 +870,7 @@ void context_manager::load_map(const std::string& filename, bool new_context) replace_map_context(mc.release()); } if (get_map_context().is_embedded()) { - const char* msg = _("Loaded embedded map data"); + std::string msg = _("Loaded embedded map data"); gui2::show_transient_message(gui_.video(), _("Map loaded from scenario"), msg); } else { if (get_map_context().get_filename() != filename) { @@ -881,12 +881,13 @@ void context_manager::load_map(const std::string& filename, bool new_context) } else { utils::string_map symbols; symbols["old"] = filename; - const char* msg = _("Loaded referenced map file:\n" + std::string msg = _("Loaded referenced map file:\n" "$new"); symbols["new"] = get_map_context().get_filename(); symbols["map_data"] = get_map_context().get_map_data_key(); gui2::show_transient_message(gui_.video(), _("Map loaded from scenario"), - vgettext(msg, symbols)); + //TODO: msg is already translated does vgettext make sense ? + vgettext(msg.c_str(), symbols)); } } } diff --git a/src/format_time_summary.cpp b/src/format_time_summary.cpp index a1f001db64d1..6bf2a4dcc060 100644 --- a/src/format_time_summary.cpp +++ b/src/format_time_summary.cpp @@ -37,7 +37,7 @@ std::string format_time_summary(time_t t) { const struct tm save_time = *timeptr; - const char* format_string = NULL; + std::string format_string; if(current_time.tm_year == save_time.tm_year) { const int days_apart = current_time.tm_yday - save_time.tm_yday; @@ -65,10 +65,10 @@ std::string format_time_summary(time_t t) { // save is from a different year format_string = _("%b %d %Y"); } - assert(format_string); + assert(!format_string.empty()); char buf[40]; - const size_t res = util::strftime(buf,sizeof(buf),format_string,&save_time); + const size_t res = util::strftime(buf, sizeof(buf), format_string, &save_time); if(res == 0) { buf[0] = 0; } diff --git a/src/formula_string_utils.cpp b/src/formula_string_utils.cpp index 2884d5557061..11045e5b117d 100644 --- a/src/formula_string_utils.cpp +++ b/src/formula_string_utils.cpp @@ -226,7 +226,7 @@ std::string vgettext(const char *domain , const char *msgid , const utils::string_map& symbols) { - const std::string orig(dgettext(domain, msgid)); + const std::string orig(translation::dgettext(domain, msgid)); const std::string msg = utils::interpolate_variables_into_string(orig, &symbols); return msg; } diff --git a/src/game_launcher.cpp b/src/game_launcher.cpp index f781ea634197..af58a60caa43 100644 --- a/src/game_launcher.cpp +++ b/src/game_launcher.cpp @@ -910,7 +910,7 @@ bool game_launcher::play_multiplayer() ERR_NET << "caught network::error: " << e.message << std::endl; gui2::show_transient_message(disp().video() , "" - , gettext(e.message.c_str())); + , translation::gettext(e.message.c_str())); } else { ERR_NET << "caught network::error" << std::endl; } diff --git a/src/game_preferences_display.cpp b/src/game_preferences_display.cpp index ae9357bb32c2..30d811bf953d 100644 --- a/src/game_preferences_display.cpp +++ b/src/game_preferences_display.cpp @@ -1701,11 +1701,11 @@ void show_preferences_dialog(display& disp, const config& game_cfg) std::string const pre = IMAGE_PREFIX + std::string("icons/icon-"); char const sep = COLUMN_SEPARATOR; - items.push_back(pre + "general.png" + sep + sgettext("Prefs section^General")); - items.push_back(pre + "display.png" + sep + sgettext("Prefs section^Display")); - items.push_back(pre + "music.png" + sep + sgettext("Prefs section^Sound")); - items.push_back(pre + "multiplayer.png" + sep + sgettext("Prefs section^Multiplayer")); - items.push_back(pre + "advanced.png" + sep + sgettext("Advanced section^Advanced")); + items.push_back(pre + "general.png" + sep + translation::sgettext("Prefs section^General")); + items.push_back(pre + "display.png" + sep + translation::sgettext("Prefs section^Display")); + items.push_back(pre + "music.png" + sep + translation::sgettext("Prefs section^Sound")); + items.push_back(pre + "multiplayer.png" + sep + translation::sgettext("Prefs section^Multiplayer")); + items.push_back(pre + "advanced.png" + sep + translation::sgettext("Advanced section^Advanced")); for(;;) { try { diff --git a/src/generators/default_map_generator.cpp b/src/generators/default_map_generator.cpp index cc5dd5f41a12..7746a9dae1ff 100644 --- a/src/generators/default_map_generator.cpp +++ b/src/generators/default_map_generator.cpp @@ -320,7 +320,7 @@ void default_map_generator::user_config(display& disp) slider_right + horz_margin, castlesize_rect.y); std::stringstream landform_str; - landform_str << gettext(island_size_ == 0 ? N_("Inland") : (island_size_ < max_coastal ? N_("Coastal") : N_("Island"))); + landform_str << translation::gettext(island_size_ == 0 ? N_("Inland") : (island_size_ < max_coastal ? N_("Coastal") : N_("Island"))); font::draw_text(&screen,screen_area(),font::SIZE_NORMAL,font::NORMAL_COLOR,landform_str.str(), slider_right+horz_margin,landform_rect.y); diff --git a/src/gettext.cpp b/src/gettext.cpp index 4df5c7b0e52c..93988f2d43ed 100644 --- a/src/gettext.cpp +++ b/src/gettext.cpp @@ -13,19 +13,36 @@ */ #include "global.hpp" - #include "gettext.hpp" +#include "log.hpp" +#include +#include #include -char const *egettext(char const *msgid) +#ifdef _WIN32 +#include +#endif + +#define DBG_G LOG_STREAM(debug, lg::general) +#define LOG_G LOG_STREAM(info, lg::general) +#define WRN_G LOG_STREAM(warn, lg::general) +#define ERR_G LOG_STREAM(err, lg::general) +namespace translation +{ +std::string dgettext(const char* domain, const char* msgid) +{ + return ::dgettext(domain, msgid); +} +std::string egettext(char const *msgid) { - return msgid[0] == '\0' ? msgid : gettext(msgid); + return msgid[0] == '\0' ? msgid : (::gettext)(msgid); } -const char* sgettext (const char *msgid) +std::string dsgettext (const char * domainname, const char *msgid) { - const char *msgval = gettext (msgid); + bind_textdomain_codeset(domainname, "UTF-8"); + const char *msgval = ::dgettext (domainname, msgid); if (msgval == msgid) { msgval = std::strrchr (msgid, '^'); if (msgval == NULL) @@ -36,10 +53,11 @@ const char* sgettext (const char *msgid) return msgval; } -const char* dsgettext (const char * domainname, const char *msgid) +#if 0 + +const char* sgettext (const char *msgid) { - bind_textdomain_codeset(domainname, "UTF-8"); - const char *msgval = dgettext (domainname, msgid); + const char *msgval = gettext (msgid); if (msgval == msgid) { msgval = std::strrchr (msgid, '^'); if (msgval == NULL) @@ -63,10 +81,11 @@ const char* sngettext (const char *singular, const char *plural, int n) return msgval; } -const char* dsngettext (const char * domainname, const char *singular, const char *plural, int n) +#endif +std::string dsngettext (const char * domainname, const char *singular, const char *plural, int n) { bind_textdomain_codeset(domainname, "UTF-8"); - const char *msgval = dngettext (domainname, singular, plural, n); + const char *msgval = ::dngettext (domainname, singular, plural, n); if (msgval == singular) { msgval = std::strrchr (singular, '^'); if (msgval == NULL) @@ -76,3 +95,88 @@ const char* dsngettext (const char * domainname, const char *singular, const cha } return msgval; } + +void bind_textdomain(const char* domain, const char* direcory, const char* encoding) +{ + if(direcory != NULL) + bindtextdomain(domain, direcory); + if(encoding != NULL) + bind_textdomain_codeset(domain, encoding); +} + +void set_default_textdomain(const char* domain) +{ + textdomain(domain); +} + +void set_language(const std::string& slocale, const std::vector* alternates) +{ + + //Code copied from language.cpp::wesnoth_setlocale() + std::string locale = slocale; + // FIXME: ideally we should check LANGUAGE and on first invocation + // use that value, so someone with es would get the game in Spanish + // instead of en_US the first time round + // LANGUAGE overrides other settings, so for now just get rid of it + +#ifdef _WIN32 + (void)alternates; + std::string win_locale(locale, 0, 2); + #include "language_win32.ii" + SetEnvironmentVariableA("LANG", win_locale.c_str()); + std::string env = "LANGUAGE=" + locale; + _putenv(env.c_str()); + return; +#else + // FIXME: add configure check for unsetenv + unsetenv ("LANGUAGE"); // void so no return value to check +#ifdef __APPLE__ + if (setenv("LANG", locale.c_str(), 1) == -1) { + ERR_G << "setenv LANG failed: " << strerror(errno); + } +#endif + + char *res = NULL; + std::vector::const_iterator i; + if (alternates) i = alternates->begin(); + + for (;;) + { + std::string lang = locale, extra; + std::string::size_type pos = locale.find('@'); + if (pos != std::string::npos) { + lang.erase(pos); + extra = locale.substr(pos); + } + + /* + * The "" is the last item to work-around a problem in glibc picking + * the non utf8 locale instead an utf8 version if available. + */ + char const *encoding[] = { ".utf-8", ".UTF-8", "" }; + for (int j = 0; j != 3; ++j) + { + locale = lang + encoding[j] + extra; + res = std::setlocale(LC_MESSAGES, locale.c_str()); + if (res) { + LOG_G << "Set locale to '" << locale << "' result: '" << res << "'.\n"; + return; + } + } + + if (!alternates || i == alternates->end()) break; + locale = *i; + ++i; + } + WRN_G << "setlocale() failed for '" << slocale << "'." << std::endl; +#endif //win32 +} + +void init() +{ +#ifndef _WIN32 + std::setlocale(LC_MESSAGES, ""); +#endif +} + +} diff --git a/src/gettext.hpp b/src/gettext.hpp index db54adf2ca96..c13189568c61 100644 --- a/src/gettext.hpp +++ b/src/gettext.hpp @@ -34,39 +34,57 @@ */ // gettext-related declarations +#include "wesconfig.h" +#include +#include -#include - -#ifdef setlocale -// Someone in libintl world decided it was a good idea to define a "setlocale" macro. -#undef setlocale +#ifndef GETTEXT_DOMAIN +# define GETTEXT_DOMAIN PACKAGE #endif -const char* egettext(const char*); -const char* sgettext(const char*); -const char* dsgettext(const char * domainname, const char *msgid); -const char* sngettext(const char *singular, const char *plural, int n); -const char* dsngettext(const char * domainname, const char *singular, const char *plural, int n); - //A Hack to make the eclipse-cdt parser happy. #ifdef __CDT_PARSER__ -#define GETTEXT_DOMAIN "" +# define GETTEXT_DOMAIN "" #endif -#ifdef GETTEXT_DOMAIN -# define _(String) dsgettext(GETTEXT_DOMAIN,String) -# define _n(String1,String2,Int) dsngettext(String1,String2,Int) -# ifdef gettext -# undef gettext -# endif -# define gettext(String) dgettext(GETTEXT_DOMAIN,String) -# define sgettext(String) dsgettext(GETTEXT_DOMAIN,String) -# define sngettext(String1,String2,Int) dsngettext(GETTEXT_DOMAIN,String1,String2,Int) +#if defined(__GNUCC__) || defined(__clang__) || defined(__MINGW32__) +#define UNUSEDNOWARN __attribute__((unused)) #else -# define _(String) sgettext(String) -# define _n(String1,String2,Int) sngettext(String1,String2,Int) +#define UNUSEDNOWARN #endif +namespace translation +{ + std::string dgettext(const char* domain, const char* msgid); + std::string egettext(const char*); + std::string dsgettext(const char * domainname, const char *msgid); + //const char* sngettext(const char *singular, const char *plural, int n); + std::string dsngettext(const char * domainname, const char *singular, const char *plural, int n); + + inline UNUSEDNOWARN static std::string gettext(const char* str) + { return translation::dgettext(GETTEXT_DOMAIN, str); } + inline UNUSEDNOWARN static std::string sgettext(const char* str) + { return translation::dsgettext(GETTEXT_DOMAIN, str); } + inline UNUSEDNOWARN static std::string sngettext(const char* str1, const char* str2, int n) + { return translation::dsngettext(GETTEXT_DOMAIN, str1, str2 , n); } + + + void bind_textdomain(const char* domain, const char* direcory, const char* encoding); + void set_default_textdomain(const char* domain); + + void set_language(const std::string& language, const std::vector* alternates); + + void init(); +} + +//#define _(String) translation::dsgettext(GETTEXT_DOMAIN,String) +inline static UNUSEDNOWARN std::string _(const char* str) +{ return translation::dsgettext(GETTEXT_DOMAIN, str); } + +//#define _n(String1, String2, Int) translation::dsngettext(GETTEXT_DOMAIN, String1,String2,Int) +inline UNUSEDNOWARN static std::string _n(const char* str1, const char* str2, int n) +{ return translation::dsngettext(GETTEXT_DOMAIN, str1, str2, n); } + #define gettext_noop(String) String #define N_(String) gettext_noop (String) diff --git a/src/gettext_boost.cpp b/src/gettext_boost.cpp new file mode 100644 index 000000000000..3ff064c8efca --- /dev/null +++ b/src/gettext_boost.cpp @@ -0,0 +1,127 @@ +/* + Copyright (C) 2003 - 2014 by David White + Part of the Battle for Wesnoth Project http://www.wesnoth.org/ + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY. + + See the COPYING file for more details. +*/ + +#include "global.hpp" +#include "gettext.hpp" +#include +#include +#include +#include + +namespace +{ + struct translation_manager + { + translation_manager() + : loaded_paths_() + , loaded_domains_() + , current_language_() + , generator_() + , current_locale_() + { + generator_.use_ansi_encoding(false); + update_locale(); + } + void update_locale() { current_locale_ = generator_.generate(current_language_); } + + std::set loaded_paths_; + std::set loaded_domains_; + std::string current_language_; + boost::locale::generator generator_; + std::locale current_locale_; + }; + + translation_manager& get_manager() + { + static translation_manager* mng = new translation_manager(); + return *mng; + } + +} + +namespace translation +{ + +std::string dgettext(const char* domain, const char* msgid) +{ + return boost::locale::dgettext(domain, msgid, get_manager().current_locale_); +} +std::string egettext(char const *msgid) +{ + return msgid[0] == '\0' ? msgid : boost::locale::gettext(msgid, get_manager().current_locale_); +} + +std::string dsgettext (const char * domainname, const char *msgid) +{ + std::string msgval = dgettext (domainname, msgid); + if (msgval == msgid) { + const char* firsthat = std::strrchr (msgid, '^'); + if (firsthat == NULL) + msgval = msgid; + else + msgval = firsthat + 1; + } + return msgval; +} + +std::string dsngettext (const char * domainname, const char *singular, const char *plural, int n) +{ + std::string msgval = boost::locale::dngettext(domainname, singular, plural, n, get_manager().current_locale_); + if (msgval == singular) { + const char* firsthat = std::strrchr (singular, '^'); + if (firsthat == NULL) + msgval = singular; + else + msgval = firsthat + 1; + } + return msgval; +} + +void bind_textdomain(const char* domain, const char* direcory, const char* encoding) +{ + std::cerr << "adding textdomain '" << domain << "' in directory '" << direcory << "'\n"; + get_manager().generator_.add_messages_domain(domain); + get_manager().generator_.add_messages_path(direcory); + get_manager().update_locale(); +} + +void set_default_textdomain(const char* domain) +{ + get_manager().generator_.set_default_messages_domain(domain); + get_manager().update_locale(); +} + + +void set_language(const std::string& language, const std::vector* /*alternates*/) +{ + // why shoudl we need alternates? which languages we support shoudl only be related + // to which languages we ship with and not which the os supports + std::cerr << "setting language to '" << language << "' \n"; + std::string::size_type at_pos = language.rfind('@'); + if(at_pos != std::string::npos) + { + get_manager().current_language_ = language.substr(0, at_pos) + ".UTF-8" + language.substr(at_pos); + } + else + { + get_manager().current_language_ = language + ".UTF-8"; + } + get_manager().update_locale(); +} + +void init() +{ + +} +} diff --git a/src/gui/dialogs/addon/description.cpp b/src/gui/dialogs/addon/description.cpp index 5b8ff7ae3293..c16e55902a15 100644 --- a/src/gui/dialogs/addon/description.cpp +++ b/src/gui/dialogs/addon/description.cpp @@ -128,7 +128,7 @@ std::string describe_addon_state_info(const addon_tracking_info& state) } break; case ADDON_INSTALLED_UPGRADABLE: { - const char* const vstr + const std::string vstr = !state.can_publish ? _("addon_state^Installed ($local_version|), " "upgradable") @@ -137,7 +137,7 @@ std::string describe_addon_state_info(const addon_tracking_info& state) s = utils::interpolate_variables_into_string(vstr, &i18n_symbols); } break; case ADDON_INSTALLED_OUTDATED: { - const char* const vstr + const std::string vstr = !state.can_publish ? _("addon_state^Installed ($local_version|), " "outdated on server") diff --git a/src/help.cpp b/src/help.cpp index 1fa540e71d37..ff7b9751b56f 100644 --- a/src/help.cpp +++ b/src/help.cpp @@ -1621,7 +1621,7 @@ class unit_topic_generator: public topic_generator const unit_type& type_; const std::string variation_; typedef std::pair< std::string, unsigned > item; - void push_header(std::vector< item > &row, char const *name) const { + void push_header(std::vector< item > &row, const std::string& name) const { row.push_back(item(bold(name), font::line_width(name, normal_font_size, TTF_STYLE_BOLD))); } public: @@ -1773,7 +1773,7 @@ class unit_topic_generator: public topic_generator BOOST_FOREACH(const config & trait, traits) { const std::string trait_name = trait["male_name"]; - std::string lang_trait_name = gettext(trait_name.c_str()); + std::string lang_trait_name = translation::gettext(trait_name.c_str()); const std::string ref_id = "traits_"+trait["id"].str(); ((trait["availability"].str() == "musthave") ? must_have_traits : random_traits).push_back(std::make_pair(lang_trait_name, ref_id)); } @@ -1818,7 +1818,7 @@ class unit_topic_generator: public topic_generator ability_end = type_.abilities().end(); ability_it != ability_end; ++ability_it) { const std::string ref_id = "ability_" + ability_it->base_str(); - std::string lang_ability = gettext(ability_it->c_str()); + std::string lang_ability = translation::gettext(ability_it->c_str()); ss << make_link(lang_ability, ref_id); if (ability_it + 1 != ability_end) ss << ", "; @@ -1834,7 +1834,7 @@ class unit_topic_generator: public topic_generator ability_end = type_.adv_abilities().end(); ability_it != ability_end; ++ability_it) { const std::string ref_id = "ability_" + ability_it->base_str(); - std::string lang_ability = gettext(ability_it->c_str()); + std::string lang_ability = translation::gettext(ability_it->c_str()); ss << make_link(lang_ability, ref_id); if (ability_it + 1 != ability_end) ss << ", "; diff --git a/src/hotkey/hotkey_preferences_display.cpp b/src/hotkey/hotkey_preferences_display.cpp index 4e4790af251e..ee962472cc47 100644 --- a/src/hotkey/hotkey_preferences_display.cpp +++ b/src/hotkey/hotkey_preferences_display.cpp @@ -214,13 +214,13 @@ void show_hotkeys_preferences_dialog(display& disp) { // tab names and icons items.push_back(pre + "titlescreen.png" + sep - + sgettext("Prefs section^Title Screen")); + + translation::sgettext("Prefs section^Title Screen")); items.push_back(pre + "game.png" + sep - + sgettext("Prefs section^Game")); + + translation::sgettext("Prefs section^Game")); items.push_back(pre + "editor.png" + sep - + sgettext("Prefs section^Editor")); + + translation::sgettext("Prefs section^Editor")); items.push_back(pre + "general.png" + sep - + sgettext("Prefs section^General")); + + translation::sgettext("Prefs section^General")); // determine the current scope, but skip general == 0 int scope; diff --git a/src/image.cpp b/src/image.cpp index e1695e5add38..fb5174bf0339 100644 --- a/src/image.cpp +++ b/src/image.cpp @@ -439,7 +439,7 @@ static std::string get_localized_path (const std::string& file, const std::strin // not have it when translated. langs.push_back("en_US"); BOOST_FOREACH(const std::string &lang, langs) { - std::string loc_file = dir + "l10n" + "/" + lang + "/" + loc_base; + std::string loc_file = dir + "/" + "l10n" + "/" + lang + "/" + loc_base; if (filesystem::file_exists(loc_file) && localized_file_uptodate(loc_file)) { return loc_file; } diff --git a/src/language.cpp b/src/language.cpp index 1651812e30d2..653fef289154 100644 --- a/src/language.cpp +++ b/src/language.cpp @@ -133,25 +133,27 @@ static void wesnoth_setlocale(int category, std::string const &slocale, // instead of en_US the first time round // LANGUAGE overrides other settings, so for now just get rid of it // FIXME: add configure check for unsetenv + + //category is never LC_MESSAGES since that case was moved to gettext.cpp to remove teh dependency to libintl.h in this file + //that why code like if (category == LC_MESSAGES) is outcommented here. #ifndef _WIN32 unsetenv ("LANGUAGE"); // void so no return value to check #endif - #ifdef __APPLE__ - if (category == LC_MESSAGES && setenv("LANG", locale.c_str(), 1) == -1) { - ERR_G << "setenv LANG failed: " << strerror(errno); - } + //if (category == LC_MESSAGES && setenv("LANG", locale.c_str(), 1) == -1) { + // ERR_G << "setenv LANG failed: " << strerror(errno); + //} #endif #ifdef _WIN32 std::string win_locale(locale, 0, 2); #include "language_win32.ii" - if(category == LC_MESSAGES) { - SetEnvironmentVariableA("LANG", win_locale.c_str()); - std::string env = "LANGUAGE=" + locale; - _putenv(env.c_str()); - return; - } + //if(category == LC_MESSAGES) { + // SetEnvironmentVariableA("LANG", win_locale.c_str()); + // std::string env = "LANGUAGE=" + locale; + // _putenv(env.c_str()); + // return; + //} locale = win_locale; #endif @@ -195,11 +197,11 @@ static void wesnoth_setlocale(int category, std::string const &slocale, } #ifndef _WIN32 - if(category == LC_MESSAGES) { - WRN_G << "Setting LANGUAGE to '" << slocale << "'." << std::endl; - setenv("LANGUAGE", slocale.c_str(), 1); - std::setlocale(LC_MESSAGES, ""); - } + //if(category == LC_MESSAGES) { + // WRN_G << "Setting LANGUAGE to '" << slocale << "'." << std::endl; + // setenv("LANGUAGE", slocale.c_str(), 1); + // std::setlocale(LC_MESSAGES, ""); + //} #endif done: @@ -220,8 +222,7 @@ void set_language(const language_def& locale) wesnoth_setlocale(LC_COLLATE, locale.localename, &locale.alternates); wesnoth_setlocale(LC_TIME, locale.localename, &locale.alternates); - wesnoth_setlocale(LC_MESSAGES, locale.localename, &locale.alternates); - + translation::set_language(locale.localename, &locale.alternates); load_strings(false); } @@ -258,7 +259,7 @@ const language_def& get_locale() const std::string& prefs_locale = preferences::language(); if(prefs_locale.empty() == false) { - wesnoth_setlocale(LC_MESSAGES, prefs_locale, NULL); + translation::set_language(prefs_locale, NULL); for(language_list::const_iterator i = known_languages.begin(); i != known_languages.end(); ++i) { if (prefs_locale == i->localename) diff --git a/src/loadscreen.cpp b/src/loadscreen.cpp index 0997c7e4bd8c..86d63e270a77 100644 --- a/src/loadscreen.cpp +++ b/src/loadscreen.cpp @@ -361,7 +361,7 @@ void loadscreen::start_stage(char const *id) const load_stage &cs = stages[s]; global_loadscreen->prcnt_ = cs.start_pos; - global_loadscreen->draw_screen(gettext(cs.name)); + global_loadscreen->draw_screen(translation::gettext(cs.name)); stage_counter[s] = 0; stage_time[s] = SDL_GetTicks(); current_stage = s; diff --git a/src/menu_events.cpp b/src/menu_events.cpp index 1fc3b7c04472..94f4bcdec03d 100644 --- a/src/menu_events.cpp +++ b/src/menu_events.cpp @@ -585,7 +585,7 @@ void menu_handler::recruit(int side_num, const map_location &last_hex) << team::get_side_color_index(side_num) << ')'; #endif description << COLUMN_SEPARATOR << font::LARGE_TEXT << prefix << type->type_name() << "\n" - << prefix << type->cost() << " " << sngettext("unit^Gold", "Gold", type->cost()); + << prefix << type->cost() << " " << translation::sngettext("unit^Gold", "Gold", type->cost()); items.push_back(description.str()); sample_units.push_back(type); @@ -3303,7 +3303,7 @@ void menu_handler::do_ai_formula(const std::string& str, void menu_handler::user_command() { - textbox_info_.show(gui::TEXTBOX_COMMAND,sgettext("prompt^Command:"), "", false, *gui_); + textbox_info_.show(gui::TEXTBOX_COMMAND, translation::sgettext("prompt^Command:"), "", false, *gui_); } void menu_handler::request_control_change ( int side_num, const std::string& player ) @@ -3345,7 +3345,7 @@ void menu_handler::custom_command() void menu_handler::ai_formula() { if (network::nconnections() == 0) { - textbox_info_.show(gui::TEXTBOX_AI,sgettext("prompt^Command:"), "", false, *gui_); + textbox_info_.show(gui::TEXTBOX_AI, translation::sgettext("prompt^Command:"), "", false, *gui_); } } diff --git a/src/reports.cpp b/src/reports.cpp index b4d1d2aeedee..1966e1a5b974 100644 --- a/src/reports.cpp +++ b/src/reports.cpp @@ -80,7 +80,7 @@ static void add_status(config &r, char const *path, char const *desc1, char const *desc2) { std::ostringstream s; - s << gettext(desc1) << gettext(desc2); + s << translation::gettext(desc1) << translation::gettext(desc2); add_image(r, path, s.str()); } @@ -431,7 +431,7 @@ static config unit_hp(reports::context& rc, const unit* u) BOOST_FOREACH(const utils::string_map::value_type &resist, u->get_base_resistances()) { std::ostringstream line; - line << gettext(resist.first.c_str()) << ": "; + line << translation::gettext(resist.first.c_str()) << ": "; // Some units have different resistances when attacking or defending. int res_att = 100 - u->resistance_against(resist.first, true, displayed_unit_hex); int res_def = 100 - u->resistance_against(resist.first, false, displayed_unit_hex); diff --git a/src/save_index.cpp b/src/save_index.cpp index 49d90d3e1a11..20423f1d6c38 100644 --- a/src/save_index.cpp +++ b/src/save_index.cpp @@ -265,9 +265,9 @@ std::string save_info::format_time_local() const char time_buf[256] = {0}; tm* tm_l = localtime(&modified()); if (tm_l) { + std::string format = preferences::use_twelve_hour_clock_format() ? _("%a %b %d %I:%M %p %Y") : _("%a %b %d %H:%M %Y"); const size_t res = strftime(time_buf,sizeof(time_buf), - (preferences::use_twelve_hour_clock_format() ? _("%a %b %d %I:%M %p %Y") : _("%a %b %d %H:%M %Y")), - tm_l); + format.c_str(), tm_l); if(res == 0) { time_buf[0] = 0; } diff --git a/src/strftime.cpp b/src/strftime.cpp index 833ad95c6e1d..b0b8f4f0dae8 100644 --- a/src/strftime.cpp +++ b/src/strftime.cpp @@ -54,20 +54,20 @@ static std::string reformat(const std::string& format, const std::tm* time, switch (*it) { case 'a': // abbreviated weekday name new_format += (time->tm_wday < 0 || time->tm_wday > 6) ? - "?" : sgettext(wday_abbr[time->tm_wday]); + "?" : translation::sgettext(wday_abbr[time->tm_wday]); continue; case 'A': // full weekday name new_format += (time->tm_wday < 0 || time->tm_wday > 6) ? - "?" : sgettext(wday_full[time->tm_wday]); + "?" : translation::sgettext(wday_full[time->tm_wday]); continue; case 'b': // abbreviated month name case 'h': new_format += (time->tm_mon < 0 || time->tm_mon > 11) ? - "?" : sgettext(mon_abbr[time->tm_mon]); + "?" : translation::sgettext(mon_abbr[time->tm_mon]); continue; case 'B': // full month name new_format += (time->tm_mon < 0 || time->tm_mon > 11) ? - "?" : sgettext(mon_full[time->tm_mon]); + "?" : translation::sgettext(mon_full[time->tm_mon]); continue; case 'c': // date and time new_format += reformat(_("%a %b %e %H:%M:%S %Y"), time, @@ -124,7 +124,7 @@ static bool locale_supports_ampm(const std::tm* time) namespace util { -size_t strftime(char* str, size_t count, const char* format, +size_t strftime(char* str, size_t count, const std::string& format, const std::tm* time) { bool ampm_supported = locale_supports_ampm(time); diff --git a/src/strftime.hpp b/src/strftime.hpp index c9630da410b2..23b29c029ae2 100644 --- a/src/strftime.hpp +++ b/src/strftime.hpp @@ -24,7 +24,7 @@ namespace util { * std::strftime wrapper to support date translations and * add missing am/pm designations. */ -size_t strftime(char* str, size_t count, const char* format, +size_t strftime(char* str, size_t count, const std::string& format, const std::tm* time); } diff --git a/src/tests/utils/game_config_manager.cpp b/src/tests/utils/game_config_manager.cpp index 414a3cbfd9cb..862e67a79e1a 100644 --- a/src/tests/utils/game_config_manager.cpp +++ b/src/tests/utils/game_config_manager.cpp @@ -13,6 +13,7 @@ */ #define GETTEXT_DOMAIN "wesnoth-test" +//#include #include "tests/utils/game_config_manager.hpp" @@ -65,14 +66,12 @@ namespace test_utils { setlocale(LC_ALL, "English"); #else std::setlocale(LC_ALL, "C"); - std::setlocale(LC_MESSAGES, ""); + translation::init(); #endif const std::string& intl_dir = filesystem::get_intl_dir(); - bindtextdomain ("wesnoth", intl_dir.c_str()); - bind_textdomain_codeset ("wesnoth", "UTF-8"); - bindtextdomain ("wesnoth-lib", intl_dir.c_str()); - bind_textdomain_codeset ("wesnoth-lib", "UTF-8"); - textdomain ("wesnoth"); + translation::bind_textdomain("wesnoth", intl_dir.c_str(), "UTF-8"); + translation::bind_textdomain("wesnoth-lib", intl_dir.c_str(), "UTF-8"); + translation::set_default_textdomain("wesnoth"); font::load_font_config(); diff --git a/src/tstring.cpp b/src/tstring.cpp index 562a413627c2..67f3d04a71aa 100644 --- a/src/tstring.cpp +++ b/src/tstring.cpp @@ -443,7 +443,7 @@ const std::string& t_string_base::str() const std::string part(w.begin(), w.end()); if(w.translatable()) { - translated_value_ += dsgettext(w.textdomain().c_str(), part.c_str()); + translated_value_ += translation::dsgettext(w.textdomain().c_str(), part.c_str()); } else { translated_value_ += part; } @@ -498,8 +498,7 @@ void t_string::add_textdomain(const std::string &name, const std::string &path) LOG_CF << "Binding textdomain " << name << " to path " << path << "\n"; // Register and (re-)bind this textdomain - bindtextdomain(name.c_str(), path.c_str()); - bind_textdomain_codeset(name.c_str(), "UTF-8"); + translation::bind_textdomain(name.c_str(), path.c_str(), "UTF-8"); } void t_string::reset_translations() diff --git a/src/unit_types.cpp b/src/unit_types.cpp index 75a2af04d62b..4f6a067671ce 100644 --- a/src/unit_types.cpp +++ b/src/unit_types.cpp @@ -70,7 +70,7 @@ attack_type::attack_type(const config& cfg) : { if (description_.empty()) - description_ = egettext(id_.c_str()); + description_ = translation::egettext(id_.c_str()); if(icon_.empty()){ if (id_ != "") @@ -841,7 +841,7 @@ const char* unit_type::alignment_description(unit_type::ALIGNMENT align, unit_ra static const char* aligns_female[] = { N_("female^lawful"), N_("female^neutral"), N_("female^chaotic"), N_("female^liminal") }; const char** tlist = (gender == unit_race::MALE ? aligns : aligns_female); - return (sgettext(tlist[align])); + return (translation::sgettext(tlist[align])); }*/ bool unit_type::has_ability_by_id(const std::string& ability) const diff --git a/src/unit_types.hpp b/src/unit_types.hpp index cb856bebc36d..aae3638a204a 100644 --- a/src/unit_types.hpp +++ b/src/unit_types.hpp @@ -252,7 +252,7 @@ class unit_type } else { str = lexical_cast(align); } - return sgettext(str.c_str()); + return translation::sgettext(str.c_str()); } fixed_t alpha() const { return alpha_; } diff --git a/src/wesnoth.cpp b/src/wesnoth.cpp index 23c0e5d41fc5..2722eb61451b 100644 --- a/src/wesnoth.cpp +++ b/src/wesnoth.cpp @@ -27,6 +27,7 @@ #include "game_config.hpp" // for path, debug, debug_lua, etc #include "game_config_manager.hpp" // for game_config_manager, etc #include "game_launcher.hpp" // for game_launcher, etc +#include "gettext.hpp" #include "gui/auxiliary/event/handler.hpp" // for tmanager #include "gui/dialogs/core_selection.hpp" // for tcore_selection #include "gui/dialogs/title_screen.hpp" // for ttitle_screen, etc @@ -57,7 +58,6 @@ #include "wml_exception.hpp" // for twml_exception #include // for SDL_Init, SDL_INIT_TIMER -#include // for bind_textdomain_codeset, etc #include // for auto_any_base, etc #include // for input, output #include // for copy @@ -480,14 +480,12 @@ static void init_locale() { setlocale(LC_ALL, "English"); #else std::setlocale(LC_ALL, "C"); - std::setlocale(LC_MESSAGES, ""); + translation::init(); #endif const std::string& intl_dir = filesystem::get_intl_dir(); - bindtextdomain (PACKAGE, intl_dir.c_str()); - bind_textdomain_codeset (PACKAGE, "UTF-8"); - bindtextdomain (PACKAGE "-lib", intl_dir.c_str()); - bind_textdomain_codeset (PACKAGE "-lib", "UTF-8"); - textdomain (PACKAGE); + translation::bind_textdomain(PACKAGE, intl_dir.c_str(), "UTF-8"); + translation::bind_textdomain(PACKAGE "-lib", intl_dir.c_str(), "UTF-8"); + translation::set_default_textdomain(PACKAGE); } /**