소스 검색

Fix win32/msvc i18n (quite UGLY version, blame Microsoft)

sapier 10 년 전
부모
커밋
22a59b3912

+ 1 - 0
src/CMakeLists.txt

@@ -306,6 +306,7 @@ set(common_SRCS
 	serverlist.cpp
 	pathfinder.cpp
 	convert_json.cpp
+	gettext.cpp
 	${JTHREAD_SRCS}
 	${common_SCRIPT_SRCS}
 	${UTIL_SRCS}

+ 10 - 6
src/cguittfont/irrUString.h

@@ -205,6 +205,10 @@ inline core::array<u8> getUnicodeBOM(EUTF_ENCODE mode)
 		case EUTFE_UTF32_LE:
 			COPY_ARRAY(BOM_ENCODE_UTF32_LE, BOM_ENCODE_UTF32_LEN);
 			break;
+		case EUTFE_NONE:
+			// TODO sapier: fixed warning only,
+			// don't know if something needs to be done here
+			break;
 	}
 	return ret;
 
@@ -257,7 +261,7 @@ public:
 				_set(c);
 				return *this;
 			}
-			
+
 			//! Increments the value by 1.
 			//! \return Myself.
 			_ustring16_iterator_access& operator++()
@@ -392,7 +396,7 @@ public:
 					return unicode::toUTF32(a[pos], a[pos + 1]);
 				}
 			}
-			
+
 			//! Sets a uchar32_t at our current position.
 			void _set(uchar32_t c)
 			{
@@ -707,7 +711,6 @@ public:
 			//! Moves the iterator to the end of the string.
 			void toEnd()
 			{
-				const uchar16_t* a = ref->c_str();
 				pos = ref->size_raw();
 			}
 
@@ -732,12 +735,13 @@ public:
 			typedef typename _Base::const_pointer const_pointer;
 			typedef typename _Base::const_reference const_reference;
 
+
 			typedef typename _Base::value_type value_type;
 			typedef typename _Base::difference_type difference_type;
 			typedef typename _Base::distance_type distance_type;
 			typedef access pointer;
 			typedef access reference;
-			
+
 			using _Base::pos;
 			using _Base::ref;
 
@@ -2096,7 +2100,7 @@ public:
 	}
 #endif
 
-	
+
 	//! Appends a number to this ustring16.
 	//! \param c Number to append.
 	//! \return A reference to our current string.
@@ -2958,7 +2962,7 @@ public:
 		if (endian != unicode::EUTFEE_NATIVE && getEndianness() != endian)
 		{
 			for (u32 i = 0; i <= used; ++i)
-				*ptr++ = unicode::swapEndian16(*ptr);
+				ptr[i] = unicode::swapEndian16(ptr[i]);
 		}
 		ret.set_used(used + (addBOM ? unicode::BOM_UTF16_LEN : 0));
 		ret.push_back(0);

+ 259 - 0
src/gettext.cpp

@@ -0,0 +1,259 @@
+/*
+Minetest
+Copyright (C) 2013 celeron55, Perttu Ahola <celeron55@gmail.com>
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU Lesser General Public License as published by
+the Free Software Foundation; either version 2.1 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public License along
+with this program; if not, write to the Free Software Foundation, Inc.,
+51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+
+#include <string>
+#include <string.h>
+#include <iostream>
+#include <stdlib.h>
+#include "gettext.h"
+#include "util/string.h"
+
+#if USE_GETTEXT and defined(_MSC_VER)
+#include <WinNls.h>
+#include <map>
+#include <direct.h>
+#include "filesys.h"
+
+#define setlocale(category,localename) \
+	setlocale(category,MSVC_LocaleLookup(localename))
+
+static std::map<std::wstring,std::wstring> glb_supported_locales;
+
+/******************************************************************************/
+BOOL CALLBACK UpdateLocaleCallback(LPTSTR pStr)
+{
+	char* endptr = 0;
+	int LOCALEID = strtol(pStr,&endptr,16);
+
+	wchar_t buffer[LOCALE_NAME_MAX_LENGTH];
+	memset(buffer,0,sizeof(buffer));
+	if (GetLocaleInfoW(
+		LOCALEID,
+		LOCALE_SISO639LANGNAME,
+		buffer,
+		LOCALE_NAME_MAX_LENGTH)) {
+
+		std::wstring name = buffer;
+
+		memset(buffer,0,sizeof(buffer));
+		GetLocaleInfoW(
+		LOCALEID,
+		LOCALE_SISO3166CTRYNAME,
+		buffer,
+		LOCALE_NAME_MAX_LENGTH);
+
+		std::wstring country = buffer;
+
+		memset(buffer,0,sizeof(buffer));
+		GetLocaleInfoW(
+		LOCALEID,
+		LOCALE_SENGLISHLANGUAGENAME,
+		buffer,
+		LOCALE_NAME_MAX_LENGTH);
+
+		std::wstring languagename = buffer;
+
+		/* set both short and long variant */
+		glb_supported_locales[name] = languagename;
+		glb_supported_locales[name + L"_" + country] = languagename;
+	}
+	return true;
+}
+
+/******************************************************************************/
+const char* MSVC_LocaleLookup(const char* raw_shortname) {
+
+	/* NULL is used to read locale only so we need to return it too */
+	if (raw_shortname == NULL) return NULL;
+
+	std::string shortname(raw_shortname);
+	if (shortname == "C") return "C";
+	if (shortname == "") return "";
+
+	static std::string last_raw_value = "";
+	static std::string last_full_name = "";
+	static bool first_use = true;
+
+	if (last_raw_value == shortname) {
+		return last_full_name.c_str();
+	}
+
+	if (first_use) {
+		EnumSystemLocalesA(UpdateLocaleCallback,LCID_SUPPORTED | LCID_ALTERNATE_SORTS);
+		first_use = false;
+	}
+
+	last_raw_value = shortname;
+
+	if (glb_supported_locales.find(narrow_to_wide(shortname)) != glb_supported_locales.end()) {
+		last_full_name = wide_to_narrow(glb_supported_locales[narrow_to_wide(shortname)]);
+		return last_full_name.c_str();
+	}
+
+	/* empty string is system default */
+	errorstream << "MSVC_LocaleLookup: unsupported locale: \"" << shortname
+				<< "\" switching to system default!" << std::endl;
+	return "";
+}
+
+#endif
+
+/******************************************************************************/
+#ifdef _MSC_VER
+void init_gettext(const char *path,std::string configured_language,int argc, char** argv) {
+#else
+void init_gettext(const char *path,std::string configured_language) {
+#endif
+#if USE_GETTEXT
+	/** first try to set user override environment **/
+	if (configured_language.length() != 0) {
+#ifndef _WIN32
+		/* add user specified locale to environment */
+		setenv("LANGUAGE", configured_language.c_str(), 1);
+
+		/* reload locale with changed environment */
+		setlocale(LC_ALL, "");
+#elif defined(_MSC_VER)
+		std::string current_language_var("");
+		if (getenv("LANGUAGE") != 0) {
+			current_language_var = std::string(getenv("LANGUAGE"));
+		}
+
+		char *lang_str = (char*)calloc(10 + configured_language.length(), sizeof(char));
+		strcat(lang_str, "LANGUAGE=");
+		strcat(lang_str, configured_language.c_str());
+		putenv(lang_str);
+
+		SetEnvironmentVariableA("LANGUAGE",configured_language.c_str());
+
+		//very very dirty workaround to force gettext to see the right environment
+		if (current_language_var != configured_language) {
+			STARTUPINFO startupinfo;
+			PROCESS_INFORMATION processinfo;
+			memset(&startupinfo,0,sizeof(startupinfo));
+			memset(&processinfo,0,sizeof(processinfo));
+			errorstream << "MSVC localization workaround aktive restating minetest in new environment!" << std::endl;
+
+			std::string parameters = "";
+
+			for (unsigned int i=1;i < argc; i++) {
+				if (parameters != "") {
+					parameters += " ";
+				}
+				parameters += argv[i];
+			}
+
+			const char* ptr_parameters = 0;
+
+			if (parameters != "") {
+				ptr_parameters = parameters.c_str();
+			}
+			
+			/** users may start by short name in commandline without extention **/
+			std::string appname = argv[0];
+			if (appname.substr(appname.length() -4) != ".exe") {
+				appname += ".exe";
+			}
+
+			if (!CreateProcess(appname.c_str(),
+								(char*) ptr_parameters,
+								NULL,
+								NULL,
+								false,
+								DETACHED_PROCESS | CREATE_UNICODE_ENVIRONMENT,
+								NULL,
+								NULL,
+								&startupinfo,
+								&processinfo)) {
+				char buffer[1024];		
+				FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM,
+					NULL,
+					GetLastError(),
+					MAKELANGID(LANG_NEUTRAL,SUBLANG_DEFAULT),
+					buffer,
+					sizeof(buffer)-1,
+					NULL);
+				errorstream << "*******************************************************" << std::endl;
+				errorstream << "CMD: " << appname << std::endl;
+				errorstream << "Failed to restart with current locale: " << std::endl;
+				errorstream << buffer;
+				errorstream << "Expect language to be broken!" << std::endl;
+				errorstream << "*******************************************************" << std::endl;
+			}
+			else {
+				exit(0);
+			}
+		}
+
+		setlocale(LC_ALL,configured_language.c_str());
+#else // Mingw
+		char *lang_str = (char*)calloc(10 + configured_language.length(), sizeof(char));
+		strcat(lang_str, "LANGUAGE=");
+		strcat(lang_str, configured_language.c_str());
+		putenv(lang_str);
+
+		setlocale(LC_ALL, "");
+#endif // ifndef _WIN32
+	}
+	else {
+		 /* set current system default locale */
+		setlocale(LC_ALL, "");
+	}
+
+#if defined(_WIN32)
+	if (getenv("LANGUAGE") != 0) {
+		setlocale(LC_ALL, getenv("LANGUAGE"));
+	}
+#ifdef _MSC_VER
+	else if (getenv("LANG") != 0) {
+		setlocale(LC_ALL, getenv("LANG"));
+	}
+#endif
+#endif
+
+	bindtextdomain(PROJECT_NAME, path);
+	textdomain(PROJECT_NAME);
+
+#if defined(_WIN32)
+	// Set character encoding for Win32
+	char *tdomain = textdomain( (char *) NULL );
+	if( tdomain == NULL )
+	{
+		errorstream << "Warning: domainname parameter is the null pointer" <<
+				", default domain is not set" << std::endl;
+		tdomain = (char *) "messages";
+	}
+	/* char *codeset = */bind_textdomain_codeset( tdomain, "UTF-8" );
+	//errorstream << "Gettext debug: domainname = " << tdomain << "; codeset = "<< codeset << std::endl;
+#endif // defined(_WIN32)
+
+	/* no matter what locale is used we need number format to be "C" */
+	/* to ensure formspec parameters are evaluated correct!          */
+
+
+	setlocale(LC_NUMERIC,"C");
+	infostream << "Message locale is now set to: "
+			<< setlocale(LC_ALL,0) << std::endl;
+			
+#endif // if USE_GETTEXT
+}
+
+
+
+

+ 30 - 35
src/gettext.h

@@ -1,4 +1,25 @@
+/*
+Minetest
+Copyright (C) 2013 celeron55, Perttu Ahola <celeron55@gmail.com>
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU Lesser General Public License as published by
+the Free Software Foundation; either version 2.1 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public License along
+with this program; if not, write to the Free Software Foundation, Inc.,
+51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+
 #ifndef GETTEXT_HEADER
+#define GETTEXT_HEADER
+
 #include "config.h" // for USE_GETTEXT
 #include "log.h"
 
@@ -18,34 +39,16 @@
 	#define _WIN32_WINNT 0x0501
 #endif
 #include <windows.h>
-#endif
 
-inline void init_gettext(const char *path) {
-#if USE_GETTEXT
-	// don't do this if MSVC compiler is used, it gives an assertion fail
-	#ifndef _MSC_VER
-		setlocale(LC_MESSAGES, "");
-	#endif
-	bindtextdomain(PROJECT_NAME, path);
-	textdomain(PROJECT_NAME);
-#if defined(_WIN32)
-	// As linux is successfully switched to UTF-8 completely at about year 2005
-	// Windows still uses obsolete codepage based locales because you
-	// cannot recompile closed-source applications
+#endif // #if defined(_WIN32)
 
-	// Set character encoding for Win32
-	char *tdomain = textdomain( (char *) NULL );
-	if( tdomain == NULL )
-	{
-		fprintf( stderr, "warning: domainname parameter is the null pointer, default domain is not set\n" );
-		tdomain = (char *) "messages";
-	}
-	/*char *codeset = */bind_textdomain_codeset( tdomain, "UTF-8" );
-	//fprintf( stdout, "%s: debug: domainname = %s; codeset = %s\n", argv[0], tdomain, codeset );
-#endif // defined(_WIN32)
+#ifdef _MSC_VER
+void init_gettext(const char *path,std::string configured_language,int argc, char** argv);
+#else
+void init_gettext(const char *path,std::string configured_language);
 #endif
-}
 
+/******************************************************************************/
 inline wchar_t* chartowchar_t(const char *str)
 {
 	wchar_t* nstr = 0;
@@ -69,26 +72,18 @@ inline wchar_t* chartowchar_t(const char *str)
 	return nstr;
 }
 
+/******************************************************************************/
 inline wchar_t* wgettext(const char *str)
 {
 	return chartowchar_t(gettext(str));
 }
 
-inline void changeCtype(const char *l)
-{
-	/*char *ret = NULL;
-	ret = setlocale(LC_CTYPE, l);
-	if(ret == NULL)
-		infostream<<"locale could not be set"<<std::endl;
-	else
-		infostream<<"locale has been set to:"<<ret<<std::endl;*/
-}
-
+/******************************************************************************/
 inline std::wstring wstrgettext(std::string text) {
 	wchar_t* wlabel = wgettext(text.c_str());
 	std::wstring out = (std::wstring)wlabel;
 	delete[] wlabel;
 	return out;
 }
-#define GETTEXT_HEADER
+
 #endif

+ 1 - 2
src/guiDeathScreen.cpp

@@ -89,7 +89,7 @@ void GUIDeathScreen::regenerateGui(v2u32 screensize)
 	/*
 		Add stuff
 	*/
-	changeCtype("");
+	
 	{
 		core::rect<s32> rect(0, 0, 400, 50);
 		rect = rect + v2s32(size.X/2-400/2, size.Y/2-50/2-25);
@@ -108,7 +108,6 @@ void GUIDeathScreen::regenerateGui(v2u32 screensize)
 		delete[] text;
 		Environment->setFocus(e);
 	}
-	changeCtype("C");
 }
 
 void GUIDeathScreen::drawMenu()

+ 0 - 2
src/guiFileSelectMenu.cpp

@@ -31,13 +31,11 @@ GUIModalMenu(env, parent, id, menumgr)
 	m_formname = formname;
 	m_text_dst = 0;
 	m_accepted = false;
-	m_previous_locale = setlocale(LC_ALL,0);
 }
 
 GUIFileSelectMenu::~GUIFileSelectMenu()
 {
 	removeChildren();
-	setlocale(LC_ALL,m_previous_locale.c_str());
 }
 
 void GUIFileSelectMenu::removeChildren()

+ 0 - 2
src/guiFileSelectMenu.h

@@ -66,8 +66,6 @@ private:
 
 	gui::IGUIFileOpenDialog* m_fileOpenDialog;
 
-	std::string m_previous_locale;
-
 	bool m_running;
 
 	TextDest *m_text_dst;

+ 1 - 3
src/guiFormSpecMenu.cpp

@@ -1629,7 +1629,6 @@ void GUIFormSpecMenu::regenerateGui(v2u32 screensize)
 
 
 	std::vector<std::string> elements = split(m_formspec_string,']');
-
 	for (unsigned int i=0;i< elements.size();i++) {
 		parseElement(&mydata,elements[i]);
 	}
@@ -1648,7 +1647,6 @@ void GUIFormSpecMenu::regenerateGui(v2u32 screensize)
 		recalculateAbsolutePosition(false);
 		mydata.basepos = getBasePos();
 
-		changeCtype("");
 		{
 			v2s32 pos = mydata.basepos;
 			pos.Y = ((m_fields.size()+2)*60);
@@ -1659,7 +1657,7 @@ void GUIFormSpecMenu::regenerateGui(v2u32 screensize)
 			Environment->addButton(mydata.rect, this, 257, text);
 			delete[] text;
 		}
-		changeCtype("C");
+
 	}
 
 	//set initial focus if parser didn't set it

+ 3 - 14
src/guiKeyChangeMenu.cpp

@@ -113,7 +113,7 @@ void GUIKeyChangeMenu::regenerateGui(v2u32 screensize)
 	recalculateAbsolutePosition(false);
 
 	v2s32 topleft(0, 0);
-	changeCtype("");
+	
 	{
 		core::rect < s32 > rect(0, 0, 600, 40);
 		rect += topleft + v2s32(25, 3);
@@ -196,9 +196,7 @@ void GUIKeyChangeMenu::regenerateGui(v2u32 screensize)
 		Environment->addButton(rect, this, GUI_ID_ABORT_BUTTON,
 							 text );
 		delete[] text;
-	}
-	changeCtype("C");
-	
+	}	
 }
 
 void GUIKeyChangeMenu::drawMenu()
@@ -265,7 +263,7 @@ bool GUIKeyChangeMenu::OnEvent(const SEvent& event)
 	if (event.EventType == EET_KEY_INPUT_EVENT && activeKey >= 0
 		&& event.KeyInput.PressedDown)
 	{
-		changeCtype("");
+		
 		bool prefer_character = shift_down;
 		KeyPress kp(event.KeyInput, prefer_character);
 		
@@ -313,7 +311,6 @@ bool GUIKeyChangeMenu::OnEvent(const SEvent& event)
 
 			this->key_used.push_back(kp);
 
-			changeCtype("C");
 			// Allow characters made with shift
 			if(shift_went_down){
 				shift_down = true;
@@ -339,12 +336,6 @@ bool GUIKeyChangeMenu::OnEvent(const SEvent& event)
 		}
 		if (event.GUIEvent.EventType == gui::EGET_BUTTON_CLICKED)
 		{
-			if(event.GUIEvent.Caller->getID() != GUI_ID_BACK_BUTTON &&
-			   event.GUIEvent.Caller->getID() != GUI_ID_ABORT_BUTTON)
-			{
-				changeCtype("");
-			}
-
 			switch (event.GUIEvent.Caller->getID())
 			{
 				case GUI_ID_BACK_BUTTON: //back
@@ -377,8 +368,6 @@ bool GUIKeyChangeMenu::OnEvent(const SEvent& event)
 					break;
 			}
 			Environment->setFocus(this);
-			//Buttons
-			changeCtype("C");
 		}
 	}
 	return Parent ? Parent->OnEvent(event) : false;

+ 1 - 2
src/guiMessageMenu.cpp

@@ -99,7 +99,7 @@ void GUIMessageMenu::regenerateGui(v2u32 screensize)
 		Environment->addStaticText(m_message_text.c_str(),
 			rect, false, true, this, -1);
 	}
-	changeCtype("");
+
 	int bw = 140;
 	{
 		core::rect<s32> rect(0, 0, bw, 30);
@@ -111,7 +111,6 @@ void GUIMessageMenu::regenerateGui(v2u32 screensize)
 		Environment->setFocus(e);
 		delete[] text;
 	}
-	changeCtype("C");
 }
 
 void GUIMessageMenu::drawMenu()

+ 0 - 9
src/guiPasswordChange.cpp

@@ -100,7 +100,6 @@ void GUIPasswordChange::regenerateGui(v2u32 screensize)
 		Add stuff
 	*/
 	s32 ypos = 50;
-	changeCtype("");
 	{
 		core::rect<s32> rect(0, 0, 110, 20);
 		rect += topleft_client + v2s32(35, ypos+6);
@@ -108,7 +107,6 @@ void GUIPasswordChange::regenerateGui(v2u32 screensize)
 		Environment->addStaticText(text, rect, false, true, this, -1);
 		delete[] text;
 	}
-	changeCtype("C");
 	{
 		core::rect<s32> rect(0, 0, 230, 30);
 		rect += topleft_client + v2s32(160, ypos);
@@ -118,7 +116,6 @@ void GUIPasswordChange::regenerateGui(v2u32 screensize)
 		e->setPasswordBox(true);
 	}
 	ypos += 50;
-	changeCtype("");
 	{
 		core::rect<s32> rect(0, 0, 110, 20);
 		rect += topleft_client + v2s32(35, ypos+6);
@@ -126,7 +123,6 @@ void GUIPasswordChange::regenerateGui(v2u32 screensize)
 		Environment->addStaticText(text, rect, false, true, this, -1);
 		delete[] text;
 	}
-	changeCtype("C");
 	{
 		core::rect<s32> rect(0, 0, 230, 30);
 		rect += topleft_client + v2s32(160, ypos);
@@ -135,7 +131,6 @@ void GUIPasswordChange::regenerateGui(v2u32 screensize)
 		e->setPasswordBox(true);
 	}
 	ypos += 50;
-	changeCtype("");
 	{
 		core::rect<s32> rect(0, 0, 110, 20);
 		rect += topleft_client + v2s32(35, ypos+6);
@@ -143,7 +138,6 @@ void GUIPasswordChange::regenerateGui(v2u32 screensize)
 		Environment->addStaticText(text, rect, false, true, this, -1);
 		delete[] text;
 	}
-	changeCtype("C");
 	{
 		core::rect<s32> rect(0, 0, 230, 30);
 		rect += topleft_client + v2s32(160, ypos);
@@ -153,7 +147,6 @@ void GUIPasswordChange::regenerateGui(v2u32 screensize)
 	}
 
 	ypos += 50;
-	changeCtype("");
 	{
 		core::rect<s32> rect(0, 0, 140, 30);
 		rect = rect + v2s32(size.X/2-140/2, ypos);
@@ -174,8 +167,6 @@ void GUIPasswordChange::regenerateGui(v2u32 screensize)
 		e->setVisible(false);
 		delete[] text;
 	}
-	changeCtype("C");
-
 }
 
 void GUIPasswordChange::drawMenu()

+ 0 - 2
src/guiPauseMenu.cpp

@@ -116,7 +116,6 @@ void GUIPauseMenu::regenerateGui(v2u32 screensize)
 	const s32 btn_gap = 20;
 	const s32 btn_num = m_simple_singleplayer_mode ? 4 : 5;
 	s32 btn_y = size.Y/2-((btn_num*btn_height+(btn_num-1)*btn_gap))/2;
-	changeCtype("");
 	{
 		core::rect<s32> rect(0, 0, 140, btn_height);
 		rect = rect + v2s32(size.X/2-140/2, btn_y);
@@ -201,7 +200,6 @@ void GUIPauseMenu::regenerateGui(v2u32 screensize)
 	
 		Environment->addStaticText(narrow_to_wide(os.str()).c_str(), rect, false, true, this, 259);
 	}
-	changeCtype("C");
 }
 
 void GUIPauseMenu::drawMenu()

+ 0 - 2
src/guiTextInputMenu.cpp

@@ -133,7 +133,6 @@ void GUITextInputMenu::regenerateGui(v2u32 screensize)
 		evt.KeyInput.Shift = 0;
 		e->OnEvent(evt);
 	}
-	changeCtype("");
 	{
 		core::rect<s32> rect(0, 0, 140, 30);
 		rect = rect + v2s32(size.X/2-140/2, size.Y/2-30/2+25);
@@ -142,7 +141,6 @@ void GUITextInputMenu::regenerateGui(v2u32 screensize)
 			text);
 		delete[] text;
 	}
-	changeCtype("C");
 }
 
 void GUITextInputMenu::drawMenu()

+ 0 - 2
src/guiVolumeChange.cpp

@@ -101,7 +101,6 @@ void GUIVolumeChange::regenerateGui(v2u32 screensize)
 	/*
 		Add stuff
 	*/
-	changeCtype("");
 	{
 		core::rect<s32> rect(0, 0, 120, 20);
 		rect = rect + v2s32(size.X/2-60, size.Y/2-35);
@@ -132,7 +131,6 @@ void GUIVolumeChange::regenerateGui(v2u32 screensize)
 		e->setMax(100);
 		e->setPos(volume);
 	}
-	changeCtype("");
 }
 
 void GUIVolumeChange::drawMenu()

+ 3 - 26
src/main.cpp

@@ -750,20 +750,6 @@ int main(int argc, char *argv[])
 	log_add_output_all_levs(&main_dstream_no_stderr_log_out);
 
 	log_register_thread("main");
-
-	// This enables internatonal characters input
-	if( setlocale(LC_ALL, "") == NULL )
-	{
-		fprintf( stderr, "%s: warning: could not set default locale\n", argv[0] );
-	}
-
-	// Set locale. This is for forcing '.' as the decimal point.
-	try {
-		std::locale::global(std::locale(std::locale(""), "C", std::locale::numeric));
-		setlocale(LC_NUMERIC, "C");
-	} catch (const std::exception& ex) {
-		errorstream<<"Could not set numeric locale to C"<<std::endl;
-	}
 	/*
 		Parse command line
 	*/
@@ -885,8 +871,6 @@ int main(int argc, char *argv[])
 	// Create user data directory
 	fs::CreateDir(porting::path_user);
 
-	init_gettext((porting::path_share + DIR_DELIM + "locale").c_str());
-
 	infostream<<"path_share = "<<porting::path_share<<std::endl;
 	infostream<<"path_user  = "<<porting::path_user<<std::endl;
 
@@ -1018,18 +1002,11 @@ int main(int argc, char *argv[])
 	{
 		run_tests();
 	}
-
-	std::string language = g_settings->get("language");
-	if (language.length()) {
-#ifndef _WIN32
-		setenv("LANGUAGE", language.c_str(), 1);
+#ifdef _MSC_VER
+	init_gettext((porting::path_share + DIR_DELIM + "locale").c_str(),g_settings->get("language"),argc,argv);
 #else
-		char *lang_str = (char*)calloc(10 + language.length(), sizeof(char));
-		strcat(lang_str, "LANGUAGE=");
-		strcat(lang_str, language.c_str());
-		putenv(lang_str);
+	init_gettext((porting::path_share + DIR_DELIM + "locale").c_str(),g_settings->get("language"));
 #endif
-	}
 
 	/*
 		Game parameters

+ 1 - 0
src/util/pointer.h

@@ -197,6 +197,7 @@ public:
 		else
 			data = NULL;
 		refcount = new unsigned int;
+		memset(data,0,sizeof(T)*m_size);
 		(*refcount) = 1;
 	}
 	SharedBuffer(const SharedBuffer &buffer)

+ 3 - 2
src/util/string.cpp

@@ -41,8 +41,9 @@ std::string wide_to_narrow(const std::wstring& wcs)
 	size_t mbl = wcs.size()*4;
 	SharedBuffer<char> mbs(mbl+1);
 	size_t l = wcstombs(*mbs, wcs.c_str(), mbl);
-	if(l == (size_t)(-1))
-		mbs[0] = 0;
+	if(l == (size_t)(-1)) {
+		return "Character conversion failed!";
+	}
 	else
 		mbs[l] = 0;
 	return *mbs;