← Back to team overview

widelands-dev team mailing list archive

[Merge] lp:~p-martin/widelands/i18n into lp:widelands

 

Martin has proposed merging lp:~p-martin/widelands/i18n into lp:widelands.

Requested reviews:
  Widelands Developers (widelands-dev)

For more details, see:
https://code.launchpad.net/~p-martin/widelands/i18n/+merge/49506

This should fix the i18n problem with Ubuntu.
>From now on, you are able
 - to select "your" language from the options and it should work
 - to select ANY language from the language list, even if it isn't installed on the system
 - to select "try system language" and it should work without restarting widelands

Please test the following
 - does widelands start with your selected language? (see config file)
 - do you see a long list of languages in the options menu?
 - does the selection of an installed language work?
 - does the selection of an uninstalled language work?
 - does the selection of "system language" apply without restarting widelands?
 - does it work with other Linuxes: (open)SuSE, Mandriva, Gentoo, Arch, etc.?
 - does it work with Mac OS X?
 - does it work with Windows?

-- 
https://code.launchpad.net/~p-martin/widelands/i18n/+merge/49506
Your team Widelands Developers is requested to review the proposed merge of lp:~p-martin/widelands/i18n into lp:widelands.
=== modified file 'src/i18n.cc'
--- src/i18n.cc	2010-11-01 21:43:46 +0000
+++ src/i18n.cc	2011-02-12 16:07:24 +0000
@@ -19,6 +19,7 @@
 
 #include "i18n.h"
 #include "log.h"
+#include "profile/profile.h"
 
 #include <config.h>
 
@@ -27,6 +28,14 @@
 #include <cstdlib>
 #include <utility>
 
+#ifdef __APPLE__
+#define SETLOCALE libintl_setlocale
+#elif _MSC_VER
+#define SETLOCALE setlocale
+#else
+#define SETLOCALE std::setlocale
+#endif
+
 extern int _nl_msg_cat_cntr;
 
 namespace i18n {
@@ -36,6 +45,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 +80,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 +110,116 @@
 }
 
 /**
- * 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
+	// first, save environment variable
+	env_locale = getenv("LANG");
+	if (env_locale.empty()) env_locale = getenv("LANGUAGE");
+	
+	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);
 
+	log("selected language: %s\n", lang.empty()?"(system language)":lang.c_str());
+
+#ifndef _WIN32
+#ifndef __AMIGAOS4__
+#ifndef __APPLE__
+	unsetenv ("LANGUAGE"); // avoid problems with this variable
+#endif
+#endif
+#endif
+
+	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 ("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;
+	// try every possible combination of alternative and encoding
+	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 found - trying to set it via LANGUAGE=%s\n", lang.c_str());
+		setenv("LANGUAGE", lang.c_str(), 1);
+		SETLOCALE(LC_MESSAGES, "");    // set locale according to the env. variables
+		                               // --> see  $ man 3 setlocale
+		// assume that it worked
+		// maybe, do another check with the return value (?)
+		locale = lang;
+	}
 
 	/* Finally make changes known.  */
 	++_nl_msg_cat_cntr;
 #endif
-	setlocale(LC_ALL, ""); //  call to libintl
-	locale = lang.c_str();
+
+	SETLOCALE(LC_ALL, ""); //  call to libintl
 
 	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-12 16:07:24 +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-12 16:07:24 +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-12 16:07:24 +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();
 

=== modified file 'txts/developers'
--- txts/developers	2011-02-07 14:53:40 +0000
+++ txts/developers	2011-02-12 16:07:24 +0000
@@ -68,6 +68,7 @@
 "<rt image=pics/genstats_nrwares.png image-align=left text-align=left><p font-size=12> Joachim Breitner (nomeata)</p></rt>"
 "<rt image=pics/genstats_nrwares.png image-align=left text-align=left><p font-size=12> Nizamov Shawkat</p></rt>"
 "<rt image=pics/genstats_nrwares.png image-align=left text-align=left><p font-size=12> Carl-Philip Hänsch (carli)</p></rt>"
+"<rt image=pics/genstats_nrwares.png image-align=left text-align=left><p font-size=12> Martin Prussak (martin)</p></rt>"
 "<rt text-align=left><p font-size=24 font-decoration=bold font-face=FreeSerif font-color=f4a131><br><br>"
 ""
 ""

=== added file 'txts/locales'
--- txts/locales	1970-01-01 00:00:00 +0000
+++ txts/locales	2011-02-12 16:07:24 +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"
+