]> git.lizzy.rs Git - minetest.git/blob - src/gettext.cpp
Fix use of unitialized variable in gettext.cpp
[minetest.git] / src / gettext.cpp
1 /*
2 Minetest
3 Copyright (C) 2013 celeron55, Perttu Ahola <celeron55@gmail.com>
4
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU Lesser General Public License as published by
7 the Free Software Foundation; either version 2.1 of the License, or
8 (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 GNU Lesser General Public License for more details.
14
15 You should have received a copy of the GNU Lesser General Public License along
16 with this program; if not, write to the Free Software Foundation, Inc.,
17 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 */
19
20 #include <string>
21 #include <string.h>
22 #include <iostream>
23 #include <stdlib.h>
24 #include "gettext.h"
25 #include "util/string.h"
26 #include "log.h"
27
28 #if USE_GETTEXT && defined(_MSC_VER)
29 #include <windows.h>
30 #include <map>
31 #include <direct.h>
32 #include "filesys.h"
33
34 #define setlocale(category, localename) \
35         setlocale(category, MSVC_LocaleLookup(localename))
36
37 static std::map<std::wstring, std::wstring> glb_supported_locales;
38
39 /******************************************************************************/
40 BOOL CALLBACK UpdateLocaleCallback(LPTSTR pStr)
41 {
42         char* endptr = 0;
43         int LOCALEID = strtol(pStr, &endptr,16);
44
45         wchar_t buffer[LOCALE_NAME_MAX_LENGTH];
46         memset(buffer, 0, sizeof(buffer));
47         if (GetLocaleInfoW(
48                 LOCALEID,
49                 LOCALE_SISO639LANGNAME,
50                 buffer,
51                 LOCALE_NAME_MAX_LENGTH)) {
52
53                 std::wstring name = buffer;
54
55                 memset(buffer, 0, sizeof(buffer));
56                 GetLocaleInfoW(
57                 LOCALEID,
58                 LOCALE_SISO3166CTRYNAME,
59                 buffer,
60                 LOCALE_NAME_MAX_LENGTH);
61
62                 std::wstring country = buffer;
63
64                 memset(buffer, 0, sizeof(buffer));
65                 GetLocaleInfoW(
66                 LOCALEID,
67                 LOCALE_SENGLISHLANGUAGENAME,
68                 buffer,
69                 LOCALE_NAME_MAX_LENGTH);
70
71                 std::wstring languagename = buffer;
72
73                 /* set both short and long variant */
74                 glb_supported_locales[name] = languagename;
75                 glb_supported_locales[name + L"_" + country] = languagename;
76         }
77         return true;
78 }
79
80 /******************************************************************************/
81 const char* MSVC_LocaleLookup(const char* raw_shortname) {
82
83         /* NULL is used to read locale only so we need to return it too */
84         if (raw_shortname == NULL) return NULL;
85
86         std::string shortname(raw_shortname);
87         if (shortname == "C") return "C";
88         if (shortname == "") return "";
89
90         static std::string last_raw_value = "";
91         static std::string last_full_name = "";
92         static bool first_use = true;
93
94         if (last_raw_value == shortname) {
95                 return last_full_name.c_str();
96         }
97
98         if (first_use) {
99                 EnumSystemLocalesA(UpdateLocaleCallback, LCID_SUPPORTED | LCID_ALTERNATE_SORTS);
100                 first_use = false;
101         }
102
103         last_raw_value = shortname;
104
105         if (glb_supported_locales.find(narrow_to_wide(shortname)) != glb_supported_locales.end()) {
106                 last_full_name = wide_to_narrow(glb_supported_locales[narrow_to_wide(shortname)]);
107                 return last_full_name.c_str();
108         }
109
110         /* empty string is system default */
111         errorstream << "MSVC_LocaleLookup: unsupported locale: \"" << shortname
112                                 << "\" switching to system default!" << std::endl;
113         return "";
114 }
115
116 #endif
117
118 /******************************************************************************/
119 #ifdef _MSC_VER
120 void init_gettext(const char *path, const std::string &configured_language, int argc, char** argv) {
121 #else
122 void init_gettext(const char *path, const std::string &configured_language) {
123 #endif
124 #if USE_GETTEXT
125         /** first try to set user override environment **/
126         if (configured_language.length() != 0) {
127 #ifndef _WIN32
128                 /* add user specified locale to environment */
129                 setenv("LANGUAGE", configured_language.c_str(), 1);
130
131                 /* reload locale with changed environment */
132                 setlocale(LC_ALL, "");
133 #elif defined(_MSC_VER)
134                 std::string current_language_var("");
135                 if (getenv("LANGUAGE") != 0) {
136                         current_language_var = std::string(getenv("LANGUAGE"));
137                 }
138
139                 char *lang_str = (char*)calloc(10 + configured_language.length(), sizeof(char));
140                 strcat(lang_str, "LANGUAGE=");
141                 strcat(lang_str, configured_language.c_str());
142                 putenv(lang_str);
143
144                 SetEnvironmentVariableA("LANGUAGE",configured_language.c_str());
145
146 #ifndef SERVER
147                 //very very dirty workaround to force gettext to see the right environment
148                 if (current_language_var != configured_language) {
149                         STARTUPINFO startupinfo;
150                         PROCESS_INFORMATION processinfo;
151                         memset(&startupinfo, 0, sizeof(startupinfo));
152                         memset(&processinfo, 0, sizeof(processinfo));
153                         errorstream << "MSVC localization workaround active restating minetest in new environment!" << std::endl;
154
155                         std::string parameters = "";
156
157                         for (unsigned int i=1;i < argc; i++) {
158                                 if (parameters != "") {
159                                         parameters += " ";
160                                 }
161                                 parameters += argv[i];
162                         }
163
164                         const char* ptr_parameters = 0;
165
166                         if (parameters != "") {
167                                 ptr_parameters = parameters.c_str();
168                         }
169                         
170                         /** users may start by short name in commandline without extention **/
171                         std::string appname = argv[0];
172                         if (appname.substr(appname.length() - 4) != ".exe") {
173                                 appname += ".exe";
174                         }
175
176                         if (!CreateProcess(appname.c_str(),
177                                         (char*) ptr_parameters,
178                                         NULL,
179                                         NULL,
180                                         false,
181                                         DETACHED_PROCESS | CREATE_UNICODE_ENVIRONMENT,
182                                         NULL,
183                                         NULL,
184                                         &startupinfo,
185                                         &processinfo)) {
186                                 char buffer[1024];              
187                                 FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM,
188                                         NULL,
189                                         GetLastError(),
190                                         MAKELANGID(LANG_NEUTRAL,SUBLANG_DEFAULT),
191                                         buffer,
192                                         sizeof(buffer)-1,
193                                         NULL);
194                                 errorstream << "*******************************************************" << std::endl;
195                                 errorstream << "CMD: " << appname << std::endl;
196                                 errorstream << "Failed to restart with current locale: " << std::endl;
197                                 errorstream << buffer;
198                                 errorstream << "Expect language to be broken!" << std::endl;
199                                 errorstream << "*******************************************************" << std::endl;
200                         }
201                         else {
202                                 exit(0);
203                         }
204 #else
205                         errorstream << "*******************************************************" << std::endl;
206                         errorstream << "Can't apply locale workaround for server!" << std::endl;
207                         errorstream << "Expect language to be broken!" << std::endl;
208                         errorstream << "*******************************************************" << std::endl;
209
210 #endif
211                 }
212
213                 setlocale(LC_ALL,configured_language.c_str());
214 #else // Mingw
215                 char *lang_str = (char*)calloc(10 + configured_language.length(), sizeof(char));
216                 strcat(lang_str, "LANGUAGE=");
217                 strcat(lang_str, configured_language.c_str());
218                 putenv(lang_str);
219
220                 setlocale(LC_ALL, "");
221 #endif // ifndef _WIN32
222         }
223         else {
224                  /* set current system default locale */
225                 setlocale(LC_ALL, "");
226         }
227
228 #if defined(_WIN32)
229         if (getenv("LANGUAGE") != 0) {
230                 setlocale(LC_ALL, getenv("LANGUAGE"));
231         }
232 #ifdef _MSC_VER
233         else if (getenv("LANG") != 0) {
234                 setlocale(LC_ALL, getenv("LANG"));
235         }
236 #endif
237 #endif
238
239         static std::string name = lowercase(PROJECT_NAME);
240         bindtextdomain(name.c_str(), path);
241         textdomain(name.c_str());
242
243 #if defined(_WIN32)
244         // Set character encoding for Win32
245         char *tdomain = textdomain( (char *) NULL );
246         if( tdomain == NULL )
247         {
248                 errorstream << "Warning: domainname parameter is the null pointer" <<
249                                 ", default domain is not set" << std::endl;
250                 tdomain = (char *) "messages";
251         }
252         /* char *codeset = */bind_textdomain_codeset( tdomain, "UTF-8" );
253         //errorstream << "Gettext debug: domainname = " << tdomain << "; codeset = "<< codeset << std::endl;
254 #endif // defined(_WIN32)
255
256 #else
257         /* set current system default locale */
258         setlocale(LC_ALL, "");
259 #endif // if USE_GETTEXT
260
261         /* no matter what locale is used we need number format to be "C" */
262         /* to ensure formspec parameters are evaluated correct!          */
263
264         setlocale(LC_NUMERIC, "C");
265         infostream << "Message locale is now set to: "
266                         << setlocale(LC_ALL, 0) << std::endl;
267 }
268