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"
27 #if USE_GETTEXT && defined(_MSC_VER)
33 #define setlocale(category,localename) \
34 setlocale(category,MSVC_LocaleLookup(localename))
36 static std::map<std::wstring,std::wstring> glb_supported_locales;
38 /******************************************************************************/
39 BOOL CALLBACK UpdateLocaleCallback(LPTSTR pStr)
42 int LOCALEID = strtol(pStr,&endptr,16);
44 wchar_t buffer[LOCALE_NAME_MAX_LENGTH];
45 memset(buffer,0,sizeof(buffer));
48 LOCALE_SISO639LANGNAME,
50 LOCALE_NAME_MAX_LENGTH)) {
52 std::wstring name = buffer;
54 memset(buffer,0,sizeof(buffer));
57 LOCALE_SISO3166CTRYNAME,
59 LOCALE_NAME_MAX_LENGTH);
61 std::wstring country = buffer;
63 memset(buffer,0,sizeof(buffer));
66 LOCALE_SENGLISHLANGUAGENAME,
68 LOCALE_NAME_MAX_LENGTH);
70 std::wstring languagename = buffer;
72 /* set both short and long variant */
73 glb_supported_locales[name] = languagename;
74 glb_supported_locales[name + L"_" + country] = languagename;
79 /******************************************************************************/
80 const char* MSVC_LocaleLookup(const char* raw_shortname) {
82 /* NULL is used to read locale only so we need to return it too */
83 if (raw_shortname == NULL) return NULL;
85 std::string shortname(raw_shortname);
86 if (shortname == "C") return "C";
87 if (shortname == "") return "";
89 static std::string last_raw_value = "";
90 static std::string last_full_name = "";
91 static bool first_use = true;
93 if (last_raw_value == shortname) {
94 return last_full_name.c_str();
98 EnumSystemLocalesA(UpdateLocaleCallback,LCID_SUPPORTED | LCID_ALTERNATE_SORTS);
102 last_raw_value = shortname;
104 if (glb_supported_locales.find(narrow_to_wide(shortname)) != glb_supported_locales.end()) {
105 last_full_name = wide_to_narrow(glb_supported_locales[narrow_to_wide(shortname)]);
106 return last_full_name.c_str();
109 /* empty string is system default */
110 errorstream << "MSVC_LocaleLookup: unsupported locale: \"" << shortname
111 << "\" switching to system default!" << std::endl;
117 /******************************************************************************/
119 void init_gettext(const char *path,std::string configured_language,int argc, char** argv) {
121 void init_gettext(const char *path,std::string configured_language) {
124 /** first try to set user override environment **/
125 if (configured_language.length() != 0) {
127 /* add user specified locale to environment */
128 setenv("LANGUAGE", configured_language.c_str(), 1);
130 /* reload locale with changed environment */
131 setlocale(LC_ALL, "");
132 #elif defined(_MSC_VER)
133 std::string current_language_var("");
134 if (getenv("LANGUAGE") != 0) {
135 current_language_var = std::string(getenv("LANGUAGE"));
138 char *lang_str = (char*)calloc(10 + configured_language.length(), sizeof(char));
139 strcat(lang_str, "LANGUAGE=");
140 strcat(lang_str, configured_language.c_str());
143 SetEnvironmentVariableA("LANGUAGE",configured_language.c_str());
146 //very very dirty workaround to force gettext to see the right environment
147 if (current_language_var != configured_language) {
148 STARTUPINFO startupinfo;
149 PROCESS_INFORMATION processinfo;
150 memset(&startupinfo,0,sizeof(startupinfo));
151 memset(&processinfo,0,sizeof(processinfo));
152 errorstream << "MSVC localization workaround active restating minetest in new environment!" << std::endl;
154 std::string parameters = "";
156 for (unsigned int i=1;i < argc; i++) {
157 if (parameters != "") {
160 parameters += argv[i];
163 const char* ptr_parameters = 0;
165 if (parameters != "") {
166 ptr_parameters = parameters.c_str();
169 /** users may start by short name in commandline without extention **/
170 std::string appname = argv[0];
171 if (appname.substr(appname.length() -4) != ".exe") {
175 if (!CreateProcess(appname.c_str(),
176 (char*) ptr_parameters,
180 DETACHED_PROCESS | CREATE_UNICODE_ENVIRONMENT,
186 FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM,
189 MAKELANGID(LANG_NEUTRAL,SUBLANG_DEFAULT),
193 errorstream << "*******************************************************" << std::endl;
194 errorstream << "CMD: " << appname << std::endl;
195 errorstream << "Failed to restart with current locale: " << std::endl;
196 errorstream << buffer;
197 errorstream << "Expect language to be broken!" << std::endl;
198 errorstream << "*******************************************************" << std::endl;
204 errorstream << "*******************************************************" << std::endl;
205 errorstream << "Can't apply locale workaround for server!" << std::endl;
206 errorstream << "Expect language to be broken!" << std::endl;
207 errorstream << "*******************************************************" << std::endl;
212 setlocale(LC_ALL,configured_language.c_str());
214 char *lang_str = (char*)calloc(10 + configured_language.length(), sizeof(char));
215 strcat(lang_str, "LANGUAGE=");
216 strcat(lang_str, configured_language.c_str());
219 setlocale(LC_ALL, "");
220 #endif // ifndef _WIN32
223 /* set current system default locale */
224 setlocale(LC_ALL, "");
228 if (getenv("LANGUAGE") != 0) {
229 setlocale(LC_ALL, getenv("LANGUAGE"));
232 else if (getenv("LANG") != 0) {
233 setlocale(LC_ALL, getenv("LANG"));
238 bindtextdomain(PROJECT_NAME, path);
239 textdomain(PROJECT_NAME);
242 // Set character encoding for Win32
243 char *tdomain = textdomain( (char *) NULL );
244 if( tdomain == NULL )
246 errorstream << "Warning: domainname parameter is the null pointer" <<
247 ", default domain is not set" << std::endl;
248 tdomain = (char *) "messages";
250 /* char *codeset = */bind_textdomain_codeset( tdomain, "UTF-8" );
251 //errorstream << "Gettext debug: domainname = " << tdomain << "; codeset = "<< codeset << std::endl;
252 #endif // defined(_WIN32)
255 /* set current system default locale */
256 setlocale(LC_ALL, "");
257 #endif // if USE_GETTEXT
259 /* no matter what locale is used we need number format to be "C" */
260 /* to ensure formspec parameters are evaluated correct! */
262 setlocale(LC_NUMERIC,"C");
263 infostream << "Message locale is now set to: "
264 << setlocale(LC_ALL,0) << std::endl;