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(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();
110 /* empty string is system default */
111 errorstream << "MSVC_LocaleLookup: unsupported locale: \"" << shortname
112 << "\" switching to system default!" << std::endl;
118 /******************************************************************************/
120 void init_gettext(const char *path, const std::string &configured_language, int argc, char** argv) {
122 void init_gettext(const char *path, const std::string &configured_language) {
125 /** first try to set user override environment **/
126 if (configured_language.length() != 0) {
128 /* add user specified locale to environment */
129 setenv("LANGUAGE", configured_language.c_str(), 1);
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"));
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());
144 SetEnvironmentVariableA("LANGUAGE",configured_language.c_str());
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;
155 std::string parameters = "";
157 for (unsigned int i=1;i < argc; i++) {
158 if (parameters != "") {
161 parameters += argv[i];
164 const char* ptr_parameters = 0;
166 if (parameters != "") {
167 ptr_parameters = parameters.c_str();
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") {
176 if (!CreateProcess(appname.c_str(),
177 (char*) ptr_parameters,
181 DETACHED_PROCESS | CREATE_UNICODE_ENVIRONMENT,
187 FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM,
190 MAKELANGID(LANG_NEUTRAL,SUBLANG_DEFAULT),
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;
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;
213 setlocale(LC_ALL,configured_language.c_str());
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());
220 setlocale(LC_ALL, "");
221 #endif // ifndef _WIN32
224 /* set current system default locale */
225 setlocale(LC_ALL, "");
229 if (getenv("LANGUAGE") != 0) {
230 setlocale(LC_ALL, getenv("LANGUAGE"));
233 else if (getenv("LANG") != 0) {
234 setlocale(LC_ALL, getenv("LANG"));
239 bindtextdomain(PROJECT_NAME, path);
240 textdomain(PROJECT_NAME);
243 // Set character encoding for Win32
244 char *tdomain = textdomain( (char *) NULL );
245 if( tdomain == NULL )
247 errorstream << "Warning: domainname parameter is the null pointer" <<
248 ", default domain is not set" << std::endl;
249 tdomain = (char *) "messages";
251 /* char *codeset = */bind_textdomain_codeset( tdomain, "UTF-8" );
252 //errorstream << "Gettext debug: domainname = " << tdomain << "; codeset = "<< codeset << std::endl;
253 #endif // defined(_WIN32)
256 /* set current system default locale */
257 setlocale(LC_ALL, "");
258 #endif // if USE_GETTEXT
260 /* no matter what locale is used we need number format to be "C" */
261 /* to ensure formspec parameters are evaluated correct! */
263 setlocale(LC_NUMERIC,"C");
264 infostream << "Message locale is now set to: "
265 << setlocale(LC_ALL, 0) << std::endl;