← Back to team overview

widelands-dev team mailing list archive

[Merge] lp:~widelands-dev/widelands/martin_i18n into lp:widelands

 

SirVer has proposed merging lp:~widelands-dev/widelands/martin_i18n into lp:widelands.

Requested reviews:
  SirVer (sirver)

For more details, see:
https://code.launchpad.net/~widelands-dev/widelands/martin_i18n/+merge/49202

Martin explored wesnoths code and duplicated their ideas to properly fix i18n under linux.
-- 
https://code.launchpad.net/~widelands-dev/widelands/martin_i18n/+merge/49202
Your team Widelands Developers is subscribed to branch lp:~widelands-dev/widelands/martin_i18n.
=== modified file 'src/i18n.cc'
--- src/i18n.cc	2010-11-01 21:43:46 +0000
+++ src/i18n.cc	2011-02-10 10:00:41 +0000
@@ -19,6 +19,7 @@
 
 #include "i18n.h"
 #include "log.h"
+#include "profile/profile.h"
 
 #include <config.h>
 
@@ -27,6 +28,12 @@
 #include <cstdlib>
 #include <utility>
 
+#ifdef __APPLE__
+#define SETLOCALE libintl_setlocale
+#else
+#define SETLOCALE std::setlocale
+#endif
+
 extern int _nl_msg_cat_cntr;
 
 namespace i18n {
@@ -36,6 +43,7 @@
 /// \see grab_texdomain()
 std::vector<std::pair<std::string, std::string> > textdomains;
 
+std::string env_locale;
 std::string locale;
 std::string localedir;
 
@@ -70,8 +78,8 @@
 	char const * const dom = domain.c_str();
 	char const * const ldir = localedir.c_str();
 
+	bindtextdomain(dom, ldir);
 	bind_textdomain_codeset(dom, "UTF-8");
-	bindtextdomain(dom, ldir);
 	// log("textdomain %s @ %s\n", dom, ldir);
 	textdomain(dom);
 	textdomains.push_back(std::make_pair(dom, ldir));
@@ -100,55 +108,106 @@
 }
 
 /**
- * Set the locale to the given string
+ * Initialize locale to English.
+ * Save system language (for later selection).
+ * Code inspired by wesnoth.org
+ */
+void init_locale() {
+#ifdef _WIN32
+	env_locale = "";
+	locale = "English";
+	SETLOCALE(LC_ALL, "English");
+#else
+	env_locale = getenv("LANG");  // save environment variable
+	locale = "C";
+	SETLOCALE(LC_ALL, "C");
+	SETLOCALE(LC_MESSAGES, "");
+#endif
+}
+
+/**
+ * Set the locale to the given string.
+ * Code inspired by wesnoth.org
  */
 void set_locale(std::string name) {
 	std::string lang(name);
 
+#ifndef _WIN32
+#ifndef __AMIGAOS4__
+	unsetenv ("LANGUAGE"); // avoid problems with this variable
+#endif
+#endif
+
+	log("selected language: %s\n", lang.empty()?"(system language)":lang.c_str());
+
+	std::string alt_str;
+	if (lang.empty()) {
+		// reload system language, if selected
+		lang = env_locale;
+		alt_str = env_locale + ",";
+	} else {
+		// otherwise, read alternatives from file
+		Profile loc("txts/locales");
+		Section * s = &loc.pull_section("alternatives");
+		alt_str = s->get_string(lang.c_str(), lang.c_str());
+		alt_str += ",";
+	}
+
 	// Somehow setlocale doesn't behave same on
 	// some systems.
 #ifdef __BEOS__
 	setenv ("LANG",   lang.c_str(), 1);
 	setenv ("LC_ALL", lang.c_str(), 1);
+	locale = lang;
 #endif
 #ifdef __APPLE__
 	setenv ("LANGUAGE", lang.c_str(), 1);
+	setenv ("LANG",     lang.c_str(), 1);
 	setenv ("LC_ALL",   lang.c_str(), 1);
+	locale = lang;
 #endif
-
 #ifdef _WIN32
 	putenv(const_cast<char *>((std::string("LANG=") + lang).c_str()));
+	locale = lang;
 #endif
 
 #ifdef linux
-	// hopefully this gets gettext to run on all linux distributions - some like
-	// ubuntu are very problematic with setting language variables.
-	// If this doesn't solve the problem on your linux-distribution, here comes
-	// a quote from
-	// http://www.gnu.org/software/automake/manual/
-	//  gettext/Locale-Environment-Variables.html
-	//
-	//   Some systems, unfortunately, set LC_ALL in /etc/profile or in similar
-	//   initialization files. As a user, you therefore have to unset this
-	//   variable if you want to set LANG and optionally some of the other LC_xxx
-	//   variables.
-
-	/* If lang is empty, fill it with $LANG */
-	if (lang.size() < 1)
-		if (char const * const l = getenv("LANG"))
-			lang = l;
-	/* Than set the variables */
-	setenv ("LANG",     lang.c_str(), 1);
-	setenv ("LANGUAGE", lang.c_str(), 1);
-	log
-		("LANG %s, LANGUAGE %s:%s\n",
-		 lang.c_str(), lang.c_str(), + lang.substr(0, 2).c_str());
+	char * res = NULL;
+	char const * encoding[] = {"", ".utf-8", "@euro", ".UTF-8"};
+	std::size_t found = alt_str.find(',', 0);
+	bool leave_while = false;
+	while (found != std::string::npos) {
+		std::string base_locale = alt_str.substr(0, int(found));
+		alt_str = alt_str.erase(0, int(found) + 1);
+
+		for (int j = 0; j < 4; ++j) {
+			std::string try_locale = base_locale + encoding[j];
+			res = SETLOCALE(LC_MESSAGES, try_locale.c_str());
+			if (res) {
+				locale = try_locale;
+				log("using locale %s\n", try_locale.c_str());
+				leave_while = true;
+				break;
+			} else {
+				//log("locale is not working: %s\n", try_locale.c_str());
+			}
+		}
+		if (leave_while) break;
+
+		found = alt_str.find(',', 0);
+	}
+	if (leave_while) {
+		setenv("LANG", locale.c_str(), 1);
+	} else {
+		log("No corresponding locale was found!\n");
+	}
 
 	/* Finally make changes known.  */
 	++_nl_msg_cat_cntr;
 #endif
-	setlocale(LC_ALL, ""); //  call to libintl
-	locale = lang.c_str();
+
+	SETLOCALE(LC_NUMERIC, NULL);
+	SETLOCALE(LC_ALL,     NULL);
 
 	if (textdomains.size()) {
 		char const * const domain = textdomains.back().first.c_str();

=== modified file 'src/i18n.h'
--- src/i18n.h	2010-04-12 09:11:24 +0000
+++ src/i18n.h	2011-02-10 10:00:41 +0000
@@ -48,6 +48,7 @@
 	~Textdomain()                         {release_textdomain();}
 };
 
+void init_locale();
 void set_locale(std::string);
 std::string const & get_locale();
 

=== modified file 'src/wlapplication.cc'
--- src/wlapplication.cc	2010-12-14 12:36:29 +0000
+++ src/wlapplication.cc	2011-02-10 10:00:41 +0000
@@ -286,6 +286,7 @@
 	init_settings();
 	if (m_default_datadirs)
 		setup_searchpaths(m_commandline["EXENAME"]);
+	init_language(); // search paths must already be set up
 	cleanup_replays();
 	init_hardware();
 
@@ -780,16 +781,6 @@
 	//then parse the commandline - overwrites conffile settings
 	handle_commandline_parameters();
 
-	// Set Locale and grab default domain
-	i18n::set_locale(s.get_string("language", ""));
-
-	std::string localedir = s.get_string("localedir", INSTALL_LOCALEDIR);
-	i18n::set_localedir(find_relative_locale_path(localedir));
-
-	i18n::grab_textdomain("widelands");
-
-	log("using locale %s\n", i18n::get_locale().c_str());
-
 	set_input_grab(s.get_bool("inputgrab", false));
 	set_mouse_swap(s.get_bool("swapmouse", false));
 
@@ -835,6 +826,23 @@
 }
 
 /**
+ * Initialize language settings
+ */
+void WLApplication::init_language() {
+	// retrieve configuration settings
+	Section & s = g_options.pull_section("global");
+
+	// Initialize locale and grab "widelands" textdomain
+	i18n::init_locale();
+	std::string localedir = s.get_string("localedir", INSTALL_LOCALEDIR);
+	i18n::set_localedir(find_relative_locale_path(localedir));
+	i18n::grab_textdomain("widelands");
+
+	// Set locale corresponding to selected language
+	i18n::set_locale(s.get_string("language", ""));
+}
+
+/**
  * Remember the last settings: write them into the config file
  */
 void WLApplication::shutdown_settings()

=== modified file 'src/wlapplication.h'
--- src/wlapplication.h	2010-11-21 11:44:22 +0000
+++ src/wlapplication.h	2011-02-10 10:00:41 +0000
@@ -222,6 +222,7 @@
 	bool poll_event(SDL_Event &, bool throttle);
 
 	bool init_settings();
+	void init_language();
 	std::string find_relative_locale_path(std::string localedir);
 	void shutdown_settings();
 

=== added file 'txts/locales'
--- txts/locales	1970-01-01 00:00:00 +0000
+++ txts/locales	2011-02-10 10:00:41 +0000
@@ -0,0 +1,44 @@
+[alternatives]
+ar="ar,ar_AR,ar_AE,ar_BH,ar_DZ,ar_EG,ar_IN,ar_IQ,ar_JO,ar_KW,ar_LB,ar_LY,ar_MA,ar_OM,ar_QA,ar_SA,ar_SD,ar_SY,ar_TN,ar_YE"
+ca="ca,ca_ES,ca_ES@valencia,ca_FR,ca_IT"
+cs="cs,cs_CZ"
+da="da,da_DK"
+de="de,de_DE,de_AT,de_CH,de_LI,de_LU,de_BE"
+en="en,en_US,en_GB,en_AU,en_CA,en_AG,en_BW,en_DK,en_HK,en_IE,en_IN,en_NG,en_NZ,en_PH,en_SG,en_ZA,en_ZW"
+en_AU="en_AU,en,en_US,en_GB"
+en_CA="en_CA,en,en_US,en_GB"
+en_GB="en_GB,en,en_US"
+eo="eo,eo_XX"
+es="es,es_ES,es_MX,es_US"
+et="et,et_EE"
+eu="eu,eu_ES,eu_FR"
+fa="fa,fa_IR"
+fi="fi,fi_FI"
+fr="fr,fr_FR,fr_CH,fr_BE,fr_CA,fr_LU"
+gl="ga,gl_ES"
+he="he,he_IL"
+hu="hu,hu_HU"
+ia="ia"
+id="id,id_ID"
+it="it,it_IT,it_CH"
+ja="ja,ja_JP"
+ko="ko,ko_KR"
+la="la,la_AU"
+ms="ms,ms_MY"
+nb="nb,nb_NO"
+nl="nl,nl_NL,nl_BE,nl_AW"
+nn="nn,nn_NO"
+oc="oc,oc_FR"
+pl="pl,pl_PL"
+pt="pt,pt_PT,pt_BR"
+pt_BR="pt_BR,pt,pt_PT"
+ru="ru,ru_RU,ru_UA"
+si="si,si_LK"
+sk="sk,sk_SK"
+sl="sl,sl_SI"
+sr="sr,sr_RS,sr_ME"
+sv="sv,sv_FI,sv_SE"
+tr="tr,tr_TR,tr_CY"
+uk="uk,uk_UA"
+vi="vi,vi_VN"
+


Follow ups