|
@@ -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
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|