Skip to content

Commit

Permalink
Merge pull request #311 from gfgtdf/gettext_reorder
Browse files Browse the repository at this point in the history
new boost gettext implementation that can handle utf8 paths on windows.
  • Loading branch information
gfgtdf committed Oct 25, 2014
2 parents 807f4ea + fed433d commit e723de7
Show file tree
Hide file tree
Showing 27 changed files with 360 additions and 114 deletions.
5 changes: 2 additions & 3 deletions src/about.cpp
Expand Up @@ -38,7 +38,6 @@
#include "video.hpp" // for update_rect, CVideo
#include "widgets/button.hpp" // for button

#include <libintl.h> // for gettext
#include <algorithm> // for max
#include <boost/foreach.hpp> // for auto_any_base, etc
#include <boost/scoped_ptr.hpp> // for scoped_ptr
Expand Down Expand Up @@ -105,7 +104,7 @@ static void add_lines(std::vector<std::string> &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);
}
}
Expand Down Expand Up @@ -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';
Expand Down
4 changes: 2 additions & 2 deletions src/addon/manager_ui.cpp
Expand Up @@ -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.
Expand Down
7 changes: 4 additions & 3 deletions src/editor/map/context_manager.cpp
Expand Up @@ -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) {
Expand All @@ -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));
}
}
}
Expand Down
6 changes: 3 additions & 3 deletions src/format_time_summary.cpp
Expand Up @@ -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;
Expand Down Expand Up @@ -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;
}
Expand Down
2 changes: 1 addition & 1 deletion src/formula_string_utils.cpp
Expand Up @@ -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;
}
Expand Down
2 changes: 1 addition & 1 deletion src/game_launcher.cpp
Expand Up @@ -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;
}
Expand Down
10 changes: 5 additions & 5 deletions src/game_preferences_display.cpp
Expand Up @@ -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 {
Expand Down
2 changes: 1 addition & 1 deletion src/generators/default_map_generator.cpp
Expand Up @@ -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);

Expand Down
124 changes: 114 additions & 10 deletions src/gettext.cpp
Expand Up @@ -13,19 +13,36 @@
*/

#include "global.hpp"

#include "gettext.hpp"
#include "log.hpp"
#include <stdlib.h>

#include <libintl.h>
#include <cstring>

char const *egettext(char const *msgid)
#ifdef _WIN32
#include <windows.h>
#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)
Expand All @@ -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)
Expand All @@ -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)
Expand All @@ -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<std::string>* 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<std::string>::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
}

}
64 changes: 41 additions & 23 deletions src/gettext.hpp
Expand Up @@ -34,39 +34,57 @@
*/

// gettext-related declarations
#include "wesconfig.h"
#include <string>
#include <vector>

#include <libintl.h>

#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<std::string>* 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)

Expand Down

0 comments on commit e723de7

Please sign in to comment.