3 Copyright (C) 2013 celeron55, Perttu Ahola <celeron55@gmail.com>
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.
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.
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.
25 #include "util/string.h"
28 #if USE_GETTEXT && defined(_MSC_VER)
34 #define setlocale(category, localename) \
35 setlocale(category, MSVC_LocaleLookup(localename))
37 static std::map<std::wstring, std::wstring> glb_supported_locales;
39 /******************************************************************************/
40 BOOL CALLBACK UpdateLocaleCallback(LPTSTR pStr)
43 int LOCALEID = strtol(pStr, &endptr,16);
45 wchar_t buffer[LOCALE_NAME_MAX_LENGTH];
46 memset(buffer, 0, sizeof(buffer));
49 LOCALE_SISO639LANGNAME,
51 LOCALE_NAME_MAX_LENGTH)) {
53 std::wstring name = buffer;
55 memset(buffer, 0, sizeof(buffer));
58 LOCALE_SISO3166CTRYNAME,
60 LOCALE_NAME_MAX_LENGTH);
62 std::wstring country = buffer;
64 memset(buffer, 0, sizeof(buffer));
67 LOCALE_SENGLISHLANGUAGENAME,
69 LOCALE_NAME_MAX_LENGTH);
71 std::wstring languagename = buffer;
73 /* set both short and long variant */
74 glb_supported_locales[name] = languagename;
75 glb_supported_locales[name + L"_" + country] = languagename;
80 /******************************************************************************/
81 const char* MSVC_LocaleLookup(const char* raw_shortname) {
83 /* NULL is used to read locale only so we need to return it too */
84 if (raw_shortname == NULL) return NULL;
86 std::string shortname(raw_shortname);
87 if (shortname == "C") return "C";
88 if (shortname == "") return "";
90 static std::string last_raw_value = "";
91 static std::string last_full_name = "";
92 static bool first_use = true;
94 if (last_raw_value == shortname) {
95 return last_full_name.c_str();
99 EnumSystemLocalesA(UpdateLocaleCallback, LCID_SUPPORTED | LCID_ALTERNATE_SORTS);
103 last_raw_value = shortname;
105 if (glb_supported_locales.find(utf8_to_wide(shortname)) != glb_supported_locales.end()) {
106 last_full_name = wide_to_utf8(
107 glb_supported_locales[utf8_to_wide(shortname)]);
108 return last_full_name.c_str();
111 /* empty string is system default */
112 errorstream << "MSVC_LocaleLookup: unsupported locale: \"" << shortname
113 << "\" switching to system default!" << std::endl;
119 /******************************************************************************/
121 void init_gettext(const char *path, const std::string &configured_language, int argc, char** argv) {
123 void init_gettext(const char *path, const std::string &configured_language) {
126 /** first try to set user override environment **/
127 if (configured_language.length() != 0) {
129 /* add user specified locale to environment */
130 setenv("LANGUAGE", configured_language.c_str(), 1);
132 /* reload locale with changed environment */
133 setlocale(LC_ALL, "");
134 #elif defined(_MSC_VER)
135 std::string current_language_var("");
136 if (getenv("LANGUAGE") != 0) {
137 current_language_var = std::string(getenv("LANGUAGE"));
140 char *lang_str = (char*)calloc(10 + configured_language.length(), sizeof(char));
141 strcat(lang_str, "LANGUAGE=");
142 strcat(lang_str, configured_language.c_str());
145 SetEnvironmentVariableA("LANGUAGE",configured_language.c_str());
148 //very very dirty workaround to force gettext to see the right environment
149 if (current_language_var != configured_language) {
150 STARTUPINFO startupinfo;
151 PROCESS_INFORMATION processinfo;
152 memset(&startupinfo, 0, sizeof(startupinfo));
153 memset(&processinfo, 0, sizeof(processinfo));
154 errorstream << "MSVC localization workaround active restating minetest in new environment!" << std::endl;
156 std::string parameters = "";
158 for (unsigned int i=1;i < argc; i++) {
159 if (parameters != "") {
162 parameters += argv[i];
165 const char* ptr_parameters = 0;
167 if (parameters != "") {
168 ptr_parameters = parameters.c_str();
171 /** users may start by short name in commandline without extention **/
172 std::string appname = argv[0];
173 if (appname.substr(appname.length() - 4) != ".exe") {
177 if (!CreateProcess(appname.c_str(),
178 (char*) ptr_parameters,
182 DETACHED_PROCESS | CREATE_UNICODE_ENVIRONMENT,
188 FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM,
191 MAKELANGID(LANG_NEUTRAL,SUBLANG_DEFAULT),
195 errorstream << "*******************************************************" << std::endl;
196 errorstream << "CMD: " << appname << std::endl;
197 errorstream << "Failed to restart with current locale: " << std::endl;
198 errorstream << buffer;
199 errorstream << "Expect language to be broken!" << std::endl;
200 errorstream << "*******************************************************" << std::endl;
206 errorstream << "*******************************************************" << std::endl;
207 errorstream << "Can't apply locale workaround for server!" << std::endl;
208 errorstream << "Expect language to be broken!" << std::endl;
209 errorstream << "*******************************************************" << std::endl;
214 setlocale(LC_ALL,configured_language.c_str());
216 char *lang_str = (char*)calloc(10 + configured_language.length(), sizeof(char));
217 strcat(lang_str, "LANGUAGE=");
218 strcat(lang_str, configured_language.c_str());
221 setlocale(LC_ALL, "");
222 #endif // ifndef _WIN32
225 /* set current system default locale */
226 setlocale(LC_ALL, "");
230 if (getenv("LANGUAGE") != 0) {
231 setlocale(LC_ALL, getenv("LANGUAGE"));
234 else if (getenv("LANG") != 0) {
235 setlocale(LC_ALL, getenv("LANG"));
240 static std::string name = lowercase(PROJECT_NAME);
241 bindtextdomain(name.c_str(), path);
242 textdomain(name.c_str());
245 // Set character encoding for Win32
246 char *tdomain = textdomain( (char *) NULL );
247 if( tdomain == NULL )
249 errorstream << "Warning: domainname parameter is the null pointer" <<
250 ", default domain is not set" << std::endl;
251 tdomain = (char *) "messages";
253 /* char *codeset = */bind_textdomain_codeset( tdomain, "UTF-8" );
254 //errorstream << "Gettext debug: domainname = " << tdomain << "; codeset = "<< codeset << std::endl;
255 #endif // defined(_WIN32)
258 /* set current system default locale */
259 setlocale(LC_ALL, "");
260 #endif // if USE_GETTEXT
262 /* no matter what locale is used we need number format to be "C" */
263 /* to ensure formspec parameters are evaluated correct! */
265 setlocale(LC_NUMERIC, "C");
266 infostream << "Message locale is now set to: "
267 << setlocale(LC_ALL, 0) << std::endl;