The Battle for Wesnoth  1.13.4+dev
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
gettext.cpp
Go to the documentation of this file.
1 /*
2  Copyright (C) 2003 - 2016 by David White <[email protected]>
3  Part of the Battle for Wesnoth Project http://www.wesnoth.org/
4 
5  This program is free software; you can redistribute it and/or modify
6  it under the terms of the GNU General Public License as published by
7  the Free Software Foundation; either version 2 of the License, or
8  (at your option) any later version.
9  This program is distributed in the hope that it will be useful,
10  but WITHOUT ANY WARRANTY.
11 
12  See the COPYING file for more details.
13 */
14 
15 #include "global.hpp"
16 #include "gettext.hpp"
17 #include "log.hpp"
18 #include <stdlib.h>
19 
20 #include <libintl.h>
21 #include <cstring>
22 
23 #ifdef _WIN32
24 #include <windows.h>
25 #endif
26 
27 #ifdef setlocale
28 // Someone in libintl world decided it was a good idea to define a "setlocale" macro.
29 // Note: This is necessary to compile on OS X, it fixes bug #16649
30 #undef setlocale
31 #endif
32 
33 #define DBG_G LOG_STREAM(debug, lg::general)
34 #define LOG_G LOG_STREAM(info, lg::general)
35 #define WRN_G LOG_STREAM(warn, lg::general)
36 #define ERR_G LOG_STREAM(err, lg::general)
37 namespace translation
38 {
39 std::string dgettext(const char* domain, const char* msgid)
40 {
41  return ::dgettext(domain, msgid);
42 }
43 std::string egettext(char const *msgid)
44 {
45  return msgid[0] == '\0' ? msgid : (::gettext)(msgid);
46 }
47 
48 std::string dsgettext (const char * domainname, const char *msgid)
49 {
50  bind_textdomain_codeset(domainname, "UTF-8");
51  const char *msgval = ::dgettext (domainname, msgid);
52  if (msgval == msgid) {
53  msgval = std::strrchr (msgid, '^');
54  if (msgval == nullptr)
55  msgval = msgid;
56  else
57  msgval++;
58  }
59  return msgval;
60 }
61 
62 #if 0
63 
64 const char* sgettext (const char *msgid)
65 {
66  const char *msgval = gettext (msgid);
67  if (msgval == msgid) {
68  msgval = std::strrchr (msgid, '^');
69  if (msgval == nullptr)
70  msgval = msgid;
71  else
72  msgval++;
73  }
74  return msgval;
75 }
76 
77 const char* sngettext (const char *singular, const char *plural, int n)
78 {
79  const char *msgval = ngettext (singular, plural, n);
80  if (msgval == singular) {
81  msgval = std::strrchr (singular, '^');
82  if (msgval == nullptr)
83  msgval = singular;
84  else
85  msgval++;
86  }
87  return msgval;
88 }
89 
90 #endif
91 std::string dsngettext (const char * domainname, const char *singular, const char *plural, int n)
92 {
93  bind_textdomain_codeset(domainname, "UTF-8");
94  const char *msgval = ::dngettext (domainname, singular, plural, n);
95  if (msgval == singular) {
96  msgval = std::strrchr (singular, '^');
97  if (msgval == nullptr)
98  msgval = singular;
99  else
100  msgval++;
101  }
102  return msgval;
103 }
104 
105 void bind_textdomain(const char* domain, const char* directory, const char* encoding)
106 {
107  if(domain != nullptr && strchr(domain, '/') != nullptr) {
108  // For compatibility with Boost.Locale implementation, which interprets
109  // slashes in domain names in a special fashion.
110  ERR_G << "illegal textdomain name '" << domain
111  << "', skipping textdomain\n";
112  return;
113  }
114 
115  if(directory != nullptr)
116  bindtextdomain(domain, directory);
117  if(encoding != nullptr)
118  bind_textdomain_codeset(domain, encoding);
119 }
120 
121 void set_default_textdomain(const char* domain)
122 {
123  textdomain(domain);
124 }
125 
126 void set_language(const std::string& slocale, const std::vector<std::string>* alternates)
127 {
128 
129  //Code copied from language.cpp::wesnoth_setlocale()
130  std::string locale = slocale;
131  // FIXME: ideally we should check LANGUAGE and on first invocation
132  // use that value, so someone with es would get the game in Spanish
133  // instead of en_US the first time round
134  // LANGUAGE overrides other settings, so for now just get rid of it
135 
136 #ifdef _WIN32
137  (void)alternates;
138  std::string win_locale(locale, 0, 2);
139  #include "language_win32.ii"
140  SetEnvironmentVariableA("LANG", win_locale.c_str());
141  std::string env = "LANGUAGE=" + locale;
142  _putenv(env.c_str());
143  return;
144 #else
145  // FIXME: add configure check for unsetenv
146  unsetenv ("LANGUAGE"); // void so no return value to check
147 #ifdef __APPLE__
148  if (setenv("LANG", locale.c_str(), 1) == -1) {
149  ERR_G << "setenv LANG failed: " << strerror(errno);
150  }
151 #endif
152 
153  char *res = nullptr;
154  std::vector<std::string>::const_iterator i;
155  if (alternates) i = alternates->begin();
156 
157  for (;;)
158  {
159  std::string lang = locale, extra;
160  std::string::size_type pos = locale.find('@');
161  if (pos != std::string::npos) {
162  lang.erase(pos);
163  extra = locale.substr(pos);
164  }
165 
166  /*
167  * The "" is the last item to work-around a problem in glibc picking
168  * the non utf8 locale instead an utf8 version if available.
169  */
170  char const *encoding[] = { ".utf-8", ".UTF-8", "" };
171  for (int j = 0; j != 3; ++j)
172  {
173  locale = lang + encoding[j] + extra;
174  res = std::setlocale(LC_MESSAGES, locale.c_str());
175  if (res) {
176  LOG_G << "Set locale to '" << locale << "' result: '" << res << "'.\n";
177  return;
178  }
179  }
180 
181  if (!alternates || i == alternates->end()) break;
182  locale = *i;
183  ++i;
184  }
185  WRN_G << "setlocale() failed for '" << slocale << "'." << std::endl;
186 #endif //win32
187 }
188 
189 void init()
190 {
191 #ifndef _WIN32
192  std::setlocale(LC_MESSAGES, "");
193 #endif
194 }
195 
196 }
GLvoid **typedef void(GLAPIENTRY *PFNGLGETVERTEXATTRIBDVPROC)(GLuint
Definition: glew.h:1806
int pos
Definition: formula.cpp:800
std::string dsngettext(const char *domainname, const char *singular, const char *plural, int n)
Definition: gettext.cpp:91
std::string dgettext(const char *domain, const char *msgid)
Definition: gettext.cpp:39
void init()
Definition: gettext.cpp:189
void set_language(const std::string &slocale, const std::vector< std::string > *alternates)
Definition: gettext.cpp:126
std::string dsgettext(const char *domainname, const char *msgid)
Definition: gettext.cpp:48
void bind_textdomain(const char *domain, const char *directory, const char *encoding)
Definition: gettext.cpp:105
#define LOG_G
Definition: gettext.cpp:34
#define WRN_G
Definition: gettext.cpp:35
void set_default_textdomain(const char *domain)
Definition: gettext.cpp:121
static UNUSEDNOWARN std::string gettext(const char *str)
Definition: gettext.hpp:64
std::string egettext(char const *msgid)
Definition: gettext.cpp:43
GLuint res
Definition: glew.h:9258
#define ERR_G
Definition: gettext.cpp:36
size_t i
Definition: function.cpp:1057
GLclampd n
Definition: glew.h:5903
static UNUSEDNOWARN std::string sgettext(const char *str)
Definition: gettext.hpp:66
Standard logging facilities (interface).
static UNUSEDNOWARN std::string sngettext(const char *str1, const char *str2, int n)
Definition: gettext.hpp:68
GLsizei const GLcharARB ** string
Definition: glew.h:4503