Index: binaries/data/mods/public/gui/common/init.xml
===================================================================
--- binaries/data/mods/public/gui/common/init.xml	(revision 13483)
+++ binaries/data/mods/public/gui/common/init.xml	(working copy)
@@ -24,4 +24,6 @@
 
         <script file="gui/common/functions_global_object.js" />
 
+        <script file="gui/common/sprintf.js" />
+
 </objects>
Index: binaries/data/mods/public/gui/common/sprintf.js
===================================================================
--- binaries/data/mods/public/gui/common/sprintf.js	(revision 0)
+++ binaries/data/mods/public/gui/common/sprintf.js	(working copy)
@@ -0,0 +1,183 @@
+/**
+sprintf() for JavaScript 0.7-beta1
+http://www.diveintojavascript.com/projects/javascript-sprintf
+
+Copyright (c) Alexandru Marasteanu <alexaholic [at) gmail (dot] com>
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+    * Redistributions in binary form must reproduce the above copyright
+      notice, this list of conditions and the following disclaimer in the
+      documentation and/or other materials provided with the distribution.
+    * Neither the name of sprintf() for JavaScript nor the
+      names of its contributors may be used to endorse or promote products
+      derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL Alexandru Marasteanu BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+Changelog:
+2010.09.06 - 0.7-beta1
+  - features: vsprintf, support for named placeholders
+  - enhancements: format cache, reduced global namespace pollution
+
+2010.05.22 - 0.6:
+ - reverted to 0.4 and fixed the bug regarding the sign of the number 0
+ Note:
+ Thanks to Raphael Pigulla <raph (at] n3rd [dot) org> (http://www.n3rd.org/)
+ who warned me about a bug in 0.5, I discovered that the last update was
+ a regress. I appologize for that.
+
+2010.05.09 - 0.5:
+ - bug fix: 0 is now preceeded with a + sign
+ - bug fix: the sign was not at the right position on padded results (Kamal Abdali)
+ - switched from GPL to BSD license
+
+2007.10.21 - 0.4:
+ - unit test and patch (David Baird)
+
+2007.09.17 - 0.3:
+ - bug fix: no longer throws exception on empty paramenters (Hans Pufal)
+
+2007.09.11 - 0.2:
+ - feature: added argument swapping
+
+2007.04.03 - 0.1:
+ - initial release
+**/
+
+var sprintf = (function() {
+	function get_type(variable) {
+		return Object.prototype.toString.call(variable).slice(8, -1).toLowerCase();
+	}
+	function str_repeat(input, multiplier) {
+		for (var output = []; multiplier > 0; output[--multiplier] = input) {/* do nothing */}
+		return output.join('');
+	}
+
+	var str_format = function() {
+		if (!str_format.cache.hasOwnProperty(arguments[0])) {
+			str_format.cache[arguments[0]] = str_format.parse(arguments[0]);
+		}
+		return str_format.format.call(null, str_format.cache[arguments[0]], arguments);
+	};
+
+	str_format.format = function(parse_tree, argv) {
+		var cursor = 1, tree_length = parse_tree.length, node_type = '', arg, output = [], i, k, match, pad, pad_character, pad_length;
+		for (i = 0; i < tree_length; i++) {
+			node_type = get_type(parse_tree[i]);
+			if (node_type === 'string') {
+				output.push(parse_tree[i]);
+			}
+			else if (node_type === 'array') {
+				match = parse_tree[i]; // convenience purposes only
+				if (match[2]) { // keyword argument
+					arg = argv[cursor];
+					for (k = 0; k < match[2].length; k++) {
+						if (!arg.hasOwnProperty(match[2][k])) {
+							throw(sprintf('[sprintf] property "%s" does not exist', match[2][k]));
+						}
+						arg = arg[match[2][k]];
+					}
+				}
+				else if (match[1]) { // positional argument (explicit)
+					arg = argv[match[1]];
+				}
+				else { // positional argument (implicit)
+					arg = argv[cursor++];
+				}
+
+				if (/[^s]/.test(match[8]) && (get_type(arg) != 'number')) {
+					throw(sprintf('[sprintf] expecting number but found %s', get_type(arg)));
+				}
+				switch (match[8]) {
+					case 'b': arg = arg.toString(2); break;
+					case 'c': arg = String.fromCharCode(arg); break;
+					case 'd': arg = parseInt(arg, 10); break;
+					case 'e': arg = match[7] ? arg.toExponential(match[7]) : arg.toExponential(); break;
+					case 'f': arg = match[7] ? parseFloat(arg).toFixed(match[7]) : parseFloat(arg); break;
+					case 'o': arg = arg.toString(8); break;
+					case 's': arg = ((arg = String(arg)) && match[7] ? arg.substring(0, match[7]) : arg); break;
+					case 'u': arg = Math.abs(arg); break;
+					case 'x': arg = arg.toString(16); break;
+					case 'X': arg = arg.toString(16).toUpperCase(); break;
+				}
+				arg = (/[def]/.test(match[8]) && match[3] && arg >= 0 ? '+'+ arg : arg);
+				pad_character = match[4] ? match[4] == '0' ? '0' : match[4].charAt(1) : ' ';
+				pad_length = match[6] - String(arg).length;
+				pad = match[6] ? str_repeat(pad_character, pad_length) : '';
+				output.push(match[5] ? arg + pad : pad + arg);
+			}
+		}
+		return output.join('');
+	};
+
+	str_format.cache = {};
+
+	str_format.parse = function(fmt) {
+		var _fmt = fmt, match = [], parse_tree = [], arg_names = 0;
+		while (_fmt) {
+			if ((match = /^[^\x25]+/.exec(_fmt)) !== null) {
+				parse_tree.push(match[0]);
+			}
+			else if ((match = /^\x25{2}/.exec(_fmt)) !== null) {
+				parse_tree.push('%');
+			}
+			else if ((match = /^\x25(?:([1-9]\d*)\$|\(([^\)]+)\))?(\+)?(0|'[^$])?(-)?(\d+)?(?:\.(\d+))?([b-fosuxX])/.exec(_fmt)) !== null) {
+				if (match[2]) {
+					arg_names |= 1;
+					var field_list = [], replacement_field = match[2], field_match = [];
+					if ((field_match = /^([a-z_][a-z_\d]*)/i.exec(replacement_field)) !== null) {
+						field_list.push(field_match[1]);
+						while ((replacement_field = replacement_field.substring(field_match[0].length)) !== '') {
+							if ((field_match = /^\.([a-z_][a-z_\d]*)/i.exec(replacement_field)) !== null) {
+								field_list.push(field_match[1]);
+							}
+							else if ((field_match = /^\[(\d+)\]/.exec(replacement_field)) !== null) {
+								field_list.push(field_match[1]);
+							}
+							else {
+								throw('[sprintf] huh?');
+							}
+						}
+					}
+					else {
+						throw('[sprintf] huh?');
+					}
+					match[2] = field_list;
+				}
+				else {
+					arg_names |= 2;
+				}
+				if (arg_names === 3) {
+					throw('[sprintf] mixing positional and named placeholders is not (yet) supported');
+				}
+				parse_tree.push(match);
+			}
+			else {
+				throw('[sprintf] huh?');
+			}
+			_fmt = _fmt.substring(match[0].length);
+		}
+		return parse_tree;
+	};
+
+	return str_format;
+})();
+
+var vsprintf = function(fmt, argv) {
+	argv.unshift(fmt);
+	return sprintf.apply(null, argv);
+};
Index: binaries/data/mods/public/gui/pregame/mainmenu.xml
===================================================================
--- binaries/data/mods/public/gui/pregame/mainmenu.xml	(revision 13483)
+++ binaries/data/mods/public/gui/pregame/mainmenu.xml	(working copy)
@@ -339,9 +339,9 @@
 					style="StoneButtonFancy"
 					size="4 4 100%-4 32"
 					tooltip_style="pgToolTip"
-					tooltip="The 0 A.D. Game Manual"
 				>
-					Learn To Play
+					<localizableAttribute id="caption">Learn To Play</localizableAttribute>
+					<localizableAttribute id="tooltip">The 0 A.D. Game Manual</localizableAttribute>
 					<action on="Press">
 						closeMenu();
 						<![CDATA[
@@ -356,9 +356,9 @@
 					type="button"
 					size="4 36 100%-4 64"
 					tooltip_style="pgToolTip"
-					tooltip="Challenge the computer player to a single player match."
 				>
-					Single Player
+					<localizableAttribute id="caption">Single Player</localizableAttribute>
+					<localizableAttribute id="tooltip">Challenge the computer player to a single player match.</localizableAttribute>
 					<action on="Press">
 						closeMenu();
 						openMenu("submenuSinglePlayer", (this.parent.size.top+this.size.top), (this.size.bottom-this.size.top), 3);
@@ -371,9 +371,9 @@
 					type="button"
 					size="4 68 100%-4 96"
 					tooltip_style="pgToolTip"
-					tooltip="Fight against one or more human players in a multiplayer game."
 				>
-					Multiplayer
+					<localizableAttribute id="caption">Multiplayer</localizableAttribute>
+					<localizableAttribute id="tooltip">Fight against one or more human players in a multiplayer game.</localizableAttribute>
 					<action on="Press">
 						closeMenu();
 						openMenu("submenuMultiplayer", (this.parent.size.top+this.size.top), (this.size.bottom-this.size.top), 2);
@@ -386,9 +386,9 @@
 					type="button"
 					size="4 100 100%-4 128"
 					tooltip_style="pgToolTip"
-					tooltip="Game options and scenario design tools."
 				>
-					Tools <![CDATA[&]]> Options
+					<localizableAttribute id="caption">Tools &amp; Options</localizableAttribute>
+					<localizableAttribute id="tooltip">Game options and scenario design tools.</localizableAttribute>
 					<action on="Press">
 						closeMenu();
 						openMenu("submenuToolsAndOptions", (this.parent.size.top+this.size.top), (this.size.bottom-this.size.top), 2);
@@ -401,9 +401,9 @@
 					type="button"
 					size="4 132 100%-4 160"
 					tooltip_style="pgToolTip"
-					tooltip="Learn about the many civilizations featured in 0 A.D."
 				>
-					History
+					<localizableAttribute id="caption">History</localizableAttribute>
+					<localizableAttribute id="tooltip">Learn about the many civilizations featured in 0 A.D.</localizableAttribute>
 					<action on="Press">
 						closeMenu();
 						<![CDATA[
@@ -418,9 +418,9 @@
 					style="StoneButtonFancy"
 					size="4 164 100%-4 192"
 					tooltip_style="pgToolTip"
-					tooltip="Exit Game"
 				>
-					Exit
+					<localizableAttribute id="caption">Exit</localizableAttribute>
+					<localizableAttribute id="tooltip">Exit Game</localizableAttribute>
 					<action on="Press">
 						closeMenu();
 						<![CDATA[
@@ -446,21 +446,18 @@
 					size="8 8 100%-8 100%-36"
                                         ghost="true"
 				>
-[font="serif-bold-16"]Alpha XIII: Magadha<!-- IMPORTANT: remember to update session/session.xml in sync with this -->[/font]
-
-WARNING: This is an early development version of the game. Many features have not been added yet.
-
-Get involved at: play0ad.com
+					<!-- IMPORTANT: remember to update session/session.xml in sync with this ↓ -->
+                    <localizableAttribute id="caption">[font="serif-bold-16"]Alpha XIII: Magadha[/font]\n\nWARNING: This is an early development version of the game. Many features have not been added yet.\n\nGet involved at: play0ad.com</localizableAttribute>
 				</object>
 
 				<!-- CONTACT METHODS -->
 				<object type="button"
 					style="StoneButton"
 					tooltip_style="pgToolTip"
-					tooltip="Click to open play0ad.com in your web browser."
 					size="8 100%-72 50%-4 100%-44"
 				>
-					Website
+					<localizableAttribute id="caption">Website</localizableAttribute>
+					<localizableAttribute id="tooltip">Click to open play0ad.com in your web browser.</localizableAttribute>
 					<action on="Press"><![CDATA[
 						var url = "http://play0ad.com/";
 						Engine.OpenURL(url);
@@ -471,10 +468,10 @@
 				<object type="button"
 					style="StoneButton"
 					tooltip_style="pgToolTip"
-					tooltip="Click to open the 0 A.D. IRC chat in your browser. (#0ad on webchat.quakenet.org)"
 					size="50%+4 100%-72 100%-8 100%-44"
 				>
-					Chat
+					<localizableAttribute id="caption">Chat</localizableAttribute>
+					<localizableAttribute id="tooltip">Click to open the 0 A.D. IRC chat in your browser. (#0ad on webchat.quakenet.org)</localizableAttribute>
 					<action on="Press"><![CDATA[
 						var url = "http://webchat.quakenet.org/?channels=0ad";
 						Engine.OpenURL(url);
@@ -485,10 +482,10 @@
 				<object type="button"
 					style="StoneButton"
 					tooltip_style="pgToolTip"
-					tooltip="Click to visit 0 A.D. Trac to report a bug, crash, or error"
 					size="8 100%-36 100%-8 100%-8"
 				>
-					Report a Bug
+					<localizableAttribute id="caption">Report a Bug</localizableAttribute>
+					<localizableAttribute id="tooltip">Click to visit 0 A.D. Trac to report a bug, crash, or error</localizableAttribute>
 					<action on="Press"><![CDATA[
 						var url = "http://trac.wildfiregames.com/wiki/ReportingErrors/";
 						Engine.OpenURL(url);
@@ -517,7 +514,9 @@
 				        style="MediumTitleText"
 					ghost="true"
 					size="50%-128 32 50%+128 48"
-				>WILDFIRE GAMES</object>
+				>
+					<localizableAttribute id="caption">WILDFIRE GAMES</localizableAttribute>
+				</object>
 			</object>
 
 			<!-- VERSION -->
@@ -527,9 +526,9 @@
 				ghost="true"
 				size="50%-128 100%-36 50%+128 100%"
 			>
-				<action on="Load"><![CDATA[
-					this.caption = "Build: " + buildTime(0) + " - " + buildTime(2);
-				]]></action>
+				<action on="Load">
+					<keep>this.caption = sprintf("</keep><localize>Build: %(buildDate)s - %(buildDetails)s</localize><keep>", { buildDate: buildTime(0), buildDetails: buildTime(2) });</keep>
+				</action>
 			</object>
 		</object>
 	</object>
Index: binaries/data/mods/public/po/gl.public.po
===================================================================
--- binaries/data/mods/public/po/gl.public.po	(revision 0)
+++ binaries/data/mods/public/po/gl.public.po	(working copy)
@@ -0,0 +1,140 @@
+# Adrián Chaves Fernández <adriyetichaves@gmail.com>, 2013.
+msgid ""
+msgstr ""
+"Project-Id-Version: \n"
+"POT-Creation-Date: 2013-05-29 08:24+0200\n"
+"PO-Revision-Date: 2013-05-29 08:35+0200\n"
+"Last-Translator: Adrián Chaves Fernández <adriyetichaves@gmail.com>\n"
+"Language-Team: Galician <kde-i18n-doc@kde.org>\n"
+"Language: gl\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=n != 1;\n"
+"X-Generator: Lokalize 1.5\n"
+
+#. (itstool) path: object/localizableAttribute
+#: binaries/data/mods/public/gui/pregame/mainmenu.xml:343
+msgid "Learn To Play"
+msgstr "Aprender a xogar"
+
+#. (itstool) path: object/localizableAttribute
+#: binaries/data/mods/public/gui/pregame/mainmenu.xml:344
+msgid "The 0 A.D. Game Manual"
+msgstr "Manual do xogo."
+
+#. (itstool) path: object/localizableAttribute
+#: binaries/data/mods/public/gui/pregame/mainmenu.xml:360
+msgid "Single Player"
+msgstr "Un xogador"
+
+#. (itstool) path: object/localizableAttribute
+#: binaries/data/mods/public/gui/pregame/mainmenu.xml:361
+msgid "Challenge the computer player to a single player match."
+msgstr "Xoga unha partida contra a intelixencia artificial."
+
+#. (itstool) path: object/localizableAttribute
+#: binaries/data/mods/public/gui/pregame/mainmenu.xml:375
+msgid "Multiplayer"
+msgstr "Varios xogadores"
+
+#. (itstool) path: object/localizableAttribute
+#: binaries/data/mods/public/gui/pregame/mainmenu.xml:376
+msgid "Fight against one or more human players in a multiplayer game."
+msgstr "Xoga contra outras persoas."
+
+#. (itstool) path: object/localizableAttribute
+#: binaries/data/mods/public/gui/pregame/mainmenu.xml:390
+msgid "Tools & Options"
+msgstr "Ferramentas e opcións"
+
+#. (itstool) path: object/localizableAttribute
+#: binaries/data/mods/public/gui/pregame/mainmenu.xml:391
+msgid "Game options and scenario design tools."
+msgstr "Opcións do xogo e ferramentas de deseño de escenarios."
+
+#. (itstool) path: object/localizableAttribute
+#: binaries/data/mods/public/gui/pregame/mainmenu.xml:405
+msgid "History"
+msgstr "Historia"
+
+#. (itstool) path: object/localizableAttribute
+#: binaries/data/mods/public/gui/pregame/mainmenu.xml:406
+msgid "Learn about the many civilizations featured in 0 A.D."
+msgstr "Infórmate sobre as civilizacións do xogo."
+
+#. (itstool) path: object/localizableAttribute
+#: binaries/data/mods/public/gui/pregame/mainmenu.xml:422
+msgid "Exit"
+msgstr "Saír"
+
+#. (itstool) path: object/localizableAttribute
+#: binaries/data/mods/public/gui/pregame/mainmenu.xml:423
+msgid "Exit Game"
+msgstr "Saír do xogo."
+
+#. (itstool) path: object/localizableAttribute
+#: binaries/data/mods/public/gui/pregame/mainmenu.xml:450
+msgid ""
+"[font=\"serif-bold-16\"]Alpha XIII: Magadha[/font]\\n\\nWARNING: This is an "
+"early development version of the game. Many features have not been added yet."
+"\\n\\nGet involved at: play0ad.com"
+msgstr ""
+"[font=\"serif-bold-16\"]Alfa XIII: Magadha[/font]\\n"
+"\\n"
+"Advertencia: Esta versión do xogo aínda está en pleno desenvolvemento. Queda "
+"moito por facer.\\n"
+"\\n"
+"Colabora: play0ad.com"
+
+#. (itstool) path: object/localizableAttribute
+#: binaries/data/mods/public/gui/pregame/mainmenu.xml:459
+msgid "Website"
+msgstr "Sitio web"
+
+#. (itstool) path: object/localizableAttribute
+#: binaries/data/mods/public/gui/pregame/mainmenu.xml:460
+msgid "Click to open play0ad.com in your web browser."
+msgstr "Preme aquí para abrir play0ad.com nun navegador web."
+
+#. (itstool) path: object/localizableAttribute
+#: binaries/data/mods/public/gui/pregame/mainmenu.xml:473
+msgid "Chat"
+msgstr "Conversa"
+
+#. (itstool) path: object/localizableAttribute
+#: binaries/data/mods/public/gui/pregame/mainmenu.xml:474
+msgid ""
+"Click to open the 0 A.D. IRC chat in your browser. (#0ad on webchat.quakenet."
+"org)"
+msgstr ""
+"Preme aquí para abrir una xanela de conversa IRC de 0 A.D. nun navegador web "
+"(#0ad en webchat.quakenet.org)."
+
+#. (itstool) path: object/localizableAttribute
+#: binaries/data/mods/public/gui/pregame/mainmenu.xml:487
+msgid "Report a Bug"
+msgstr "Informar dun erro"
+
+#. (itstool) path: object/localizableAttribute
+#: binaries/data/mods/public/gui/pregame/mainmenu.xml:488
+msgid "Click to visit 0 A.D. Trac to report a bug, crash, or error"
+msgstr ""
+"Preme aquí para visitar o sitio Trac de 0 A.D., no que poderás informar dun "
+"erro, fallo ou quebra."
+
+#. (itstool) path: object/localizableAttribute
+#: binaries/data/mods/public/gui/pregame/mainmenu.xml:518
+msgid "WILDFIRE GAMES"
+msgstr "WILDFIRE GAMES"
+
+#. (itstool) path: action/localize
+#: binaries/data/mods/public/gui/pregame/mainmenu.xml:530
+msgid "Build: %(buildDate)s - %(buildDetails)s"
+msgstr "Versión: %(buildDate)s (%(buildDetails)s)"
+
+#~ msgid "Alpha XIII: Magadha"
+#~ msgstr "Alfa XIII: Magadha"
+
+#~ msgid "Get involved at: play0ad.com"
+#~ msgstr "Axúdanos: play0ad.com"
Index: binaries/data/mods/public/po/public.pot
===================================================================
--- binaries/data/mods/public/po/public.pot	(revision 0)
+++ binaries/data/mods/public/po/public.pot	(working copy)
@@ -0,0 +1,116 @@
+msgid ""
+msgstr ""
+"Project-Id-Version: PACKAGE VERSION\n"
+"POT-Creation-Date: 2013-06-15 21:58+0200\n"
+"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
+"Language-Team: LANGUAGE <LL@li.org>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+#. (itstool) path: object/localizableAttribute
+#: binaries/data/mods/public/gui/pregame/mainmenu.xml:343
+msgid "Learn To Play"
+msgstr ""
+
+#. (itstool) path: object/localizableAttribute
+#: binaries/data/mods/public/gui/pregame/mainmenu.xml:344
+msgid "The 0 A.D. Game Manual"
+msgstr ""
+
+#. (itstool) path: object/localizableAttribute
+#: binaries/data/mods/public/gui/pregame/mainmenu.xml:360
+msgid "Single Player"
+msgstr ""
+
+#. (itstool) path: object/localizableAttribute
+#: binaries/data/mods/public/gui/pregame/mainmenu.xml:361
+msgid "Challenge the computer player to a single player match."
+msgstr ""
+
+#. (itstool) path: object/localizableAttribute
+#: binaries/data/mods/public/gui/pregame/mainmenu.xml:375
+msgid "Multiplayer"
+msgstr ""
+
+#. (itstool) path: object/localizableAttribute
+#: binaries/data/mods/public/gui/pregame/mainmenu.xml:376
+msgid "Fight against one or more human players in a multiplayer game."
+msgstr ""
+
+#. (itstool) path: object/localizableAttribute
+#: binaries/data/mods/public/gui/pregame/mainmenu.xml:390
+msgid "Tools & Options"
+msgstr ""
+
+#. (itstool) path: object/localizableAttribute
+#: binaries/data/mods/public/gui/pregame/mainmenu.xml:391
+msgid "Game options and scenario design tools."
+msgstr ""
+
+#. (itstool) path: object/localizableAttribute
+#: binaries/data/mods/public/gui/pregame/mainmenu.xml:405
+msgid "History"
+msgstr ""
+
+#. (itstool) path: object/localizableAttribute
+#: binaries/data/mods/public/gui/pregame/mainmenu.xml:406
+msgid "Learn about the many civilizations featured in 0 A.D."
+msgstr ""
+
+#. (itstool) path: object/localizableAttribute
+#: binaries/data/mods/public/gui/pregame/mainmenu.xml:422
+msgid "Exit"
+msgstr ""
+
+#. (itstool) path: object/localizableAttribute
+#: binaries/data/mods/public/gui/pregame/mainmenu.xml:423
+msgid "Exit Game"
+msgstr ""
+
+#. (itstool) path: object/localizableAttribute
+#: binaries/data/mods/public/gui/pregame/mainmenu.xml:450
+msgid "[font=\"serif-bold-16\"]Alpha XIII: Magadha[/font]\\n\\nWARNING: This is an early development version of the game. Many features have not been added yet.\\n\\nGet involved at: play0ad.com"
+msgstr ""
+
+#. (itstool) path: object/localizableAttribute
+#: binaries/data/mods/public/gui/pregame/mainmenu.xml:459
+msgid "Website"
+msgstr ""
+
+#. (itstool) path: object/localizableAttribute
+#: binaries/data/mods/public/gui/pregame/mainmenu.xml:460
+msgid "Click to open play0ad.com in your web browser."
+msgstr ""
+
+#. (itstool) path: object/localizableAttribute
+#: binaries/data/mods/public/gui/pregame/mainmenu.xml:473
+msgid "Chat"
+msgstr ""
+
+#. (itstool) path: object/localizableAttribute
+#: binaries/data/mods/public/gui/pregame/mainmenu.xml:474
+msgid "Click to open the 0 A.D. IRC chat in your browser. (#0ad on webchat.quakenet.org)"
+msgstr ""
+
+#. (itstool) path: object/localizableAttribute
+#: binaries/data/mods/public/gui/pregame/mainmenu.xml:487
+msgid "Report a Bug"
+msgstr ""
+
+#. (itstool) path: object/localizableAttribute
+#: binaries/data/mods/public/gui/pregame/mainmenu.xml:488
+msgid "Click to visit 0 A.D. Trac to report a bug, crash, or error"
+msgstr ""
+
+#. (itstool) path: object/localizableAttribute
+#: binaries/data/mods/public/gui/pregame/mainmenu.xml:518
+msgid "WILDFIRE GAMES"
+msgstr ""
+
+#. (itstool) path: action/localize
+#: binaries/data/mods/public/gui/pregame/mainmenu.xml:530
+msgid "Build: %(buildDate)s - %(buildDetails)s"
+msgstr ""
+
Index: build/premake/extern_libs4.lua
===================================================================
--- build/premake/extern_libs4.lua	(revision 13483)
+++ build/premake/extern_libs4.lua	(working copy)
@@ -567,6 +567,22 @@
 			end
 		end,
 	},
+	tinygettext = {
+		compile_settings = function()
+			if not _OPTIONS["with-system-tinygettext"] then
+				includedirs { libraries_source_dir .. "tinygettext" }
+			end
+		end,
+		link_settings = function()
+			if not _OPTIONS["with-system-tinygettext"] then
+				add_source_lib_paths("tinygettext")
+			end
+			add_default_links({
+				win_names  = { "tinygettext" },
+				unix_names = { "tinygettext" },
+			})
+		end,
+	},
 	valgrind = {
 		compile_settings = function()
 			add_source_include_paths("valgrind")
Index: build/premake/premake4.lua
===================================================================
--- build/premake/premake4.lua	(revision 13483)
+++ build/premake/premake4.lua	(working copy)
@@ -13,6 +13,7 @@
 newoption { trigger = "with-system-nvtt", description = "Search standard paths for nvidia-texture-tools library, instead of using bundled copy" }
 newoption { trigger = "with-system-enet", description = "Search standard paths for libenet, instead of using bundled copy" }
 newoption { trigger = "with-system-mozjs185", description = "Search standard paths for libmozjs185, instead of using bundled copy" }
+newoption { trigger = "with-system-tinygettext", description = "Search standard paths for tinygettext, instead of using bundled copy" }
 newoption { trigger = "sysroot", description = "Set compiler system root path, used for building against a non-system SDK. For example /usr/local becomes SYSROOT/user/local" }
 newoption { trigger = "macosx-version-min", description = "Set minimum required version of the OS X API, the build will possibly fail if an older SDK is used, while newer API functions will be weakly linked (i.e. resolved at runtime)" }
 newoption { trigger = "macosx-bundle", description = "Enable OSX bundle, the argument is the bundle identifier string (e.g. com.wildfiregames.0ad)" }
@@ -622,7 +623,8 @@
 		"spidermonkey",
 		"sdl",	-- key definitions
 		"opengl",
-		"boost"
+		"boost",
+		"tinygettext",
 	}
 	setup_static_lib_project("gui", source_dirs, extern_libs, {})
 
@@ -653,6 +655,7 @@
 		"libjpg",
 		"valgrind",
 		"cxxtest",
+		"tinygettext",
 	}
 
 	-- CPU architecture-specific
@@ -743,6 +746,7 @@
 	"cxxtest",
 	"comsuppw",
 	"enet",
+	"tinygettext",
 	"libcurl",
 
 	"valgrind",
Index: build/workspaces/update-workspaces.sh
===================================================================
--- build/workspaces/update-workspaces.sh	(revision 13483)
+++ build/workspaces/update-workspaces.sh	(working copy)
@@ -37,6 +37,7 @@
 with_system_nvtt=false
 with_system_enet=false
 with_system_mozjs185=false
+with_system_tinygettext=false
 enable_atlas=true
 
 for i in "$@"
@@ -46,6 +47,7 @@
     --with-system-nvtt ) with_system_nvtt=true; premake_args="${premake_args} --with-system-nvtt" ;;
     --with-system-enet ) with_system_enet=true; premake_args="${premake_args} --with-system-enet" ;;
     --with-system-mozjs185 ) with_system_mozjs185=true; premake_args="${premake_args} --with-system-mozjs185" ;;
+    --with-system-tinygettext ) with_system_tinygettext=true; premake_args="${premake_args} --with-system-tinygettext" ;;
     --enable-atlas ) enable_atlas=true ;;
     --disable-atlas ) enable_atlas=false ;;
     -j* ) JOBS=$i ;;
@@ -91,6 +93,10 @@
     (cd ../../libraries/source/enet && MAKE=${MAKE} JOBS=${JOBS} ./build.sh) || die "ENet build failed"
   fi
   echo
+  if [ "$with_system_tinygettext" = "false" ]; then
+    (cd ../../libraries/source/tinygettext && JOBS=${JOBS} ./build.sh) || die "TinyGettext build failed"
+  fi
+  echo
 fi
 
 # Now build premake and run it to create the makefiles
Index: libraries/LICENSE.txt
===================================================================
--- libraries/LICENSE.txt	(revision 13483)
+++ libraries/LICENSE.txt	(working copy)
@@ -23,6 +23,9 @@
   source/spidermonkey
     MPL / GPL / LGPL
 
+  source/tinygettext
+    GNU GPL v2 (see COPYING)
+
   source/valgrind
     BSD
 
Index: libraries/source/tinygettext/CMakeLists.txt
===================================================================
--- libraries/source/tinygettext/CMakeLists.txt	(revision 0)
+++ libraries/source/tinygettext/CMakeLists.txt	(working copy)
@@ -0,0 +1,177 @@
+#
+# TinyGetText build script
+# Copyright (C) 2006 Christoph Sommer <christoph.sommer@2006.expires.deltadevelopment.de>
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 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 General Public License for more details.
+# 
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+#
+
+
+#
+# INSTRUCTIONS:
+# -------------
+#
+# Create a directory build/ and change to it. Run
+#
+#   cmake ..
+#
+# This creates a set of Makefiles to build the project. Run
+#
+#   make
+#
+
+
+CMAKE_POLICY(SET CMP0005 NEW)
+
+## Project name to use as command prefix
+
+PROJECT(tinygettext)
+SET(VERSION "0.1")
+
+### CMake configuration
+
+CMAKE_MINIMUM_REQUIRED(VERSION 2.4)
+IF(COMMAND cmake_policy)
+	CMAKE_POLICY(SET CMP0003 NEW)
+ENDIF(COMMAND cmake_policy)
+SET(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${tinygettext_SOURCE_DIR})
+
+# move some config clutter to the advanced section
+MARK_AS_ADVANCED(
+	CMAKE_BACKWARDS_COMPATIBILITY
+	CMAKE_BUILD_TYPE
+	CMAKE_INSTALL_PREFIX
+	EXECUTABLE_OUTPUT_PATH
+	CMAKE_OSX_ARCHITECTURES
+	CMAKE_OSX_SYSROOT
+)
+
+## Reveal library type choice to users
+OPTION(BUILD_SHARED_LIBS "Produce dynamic library instead of static archive" ON)
+
+## Add iconv to include directories
+
+FIND_PACKAGE(ICONV REQUIRED)
+INCLUDE_DIRECTORIES(${ICONV_INCLUDE_DIR})
+
+## Check iconv_const
+
+INCLUDE(CheckCXXSourceCompiles)
+
+SET(CMAKE_REQUIRED_INCLUDES ${CMAKE_REQUIRED_INCLUDES} ${ICONV_INCLUDE_DIR})
+CHECK_CXX_SOURCE_COMPILES(
+	"
+	#include <iconv.h>
+	// this declaration will fail when there already exists a non const char** version which returns size_t
+	double iconv(iconv_t cd,  char **inbuf, size_t *inbytesleft, char **outbuf, size_t *outbytesleft);
+	int main() { return 0; }
+	"
+	HAVE_ICONV_CONST
+)
+
+# TODO: better way of config
+
+IF(HAVE_ICONV_CONST)
+  ADD_DEFINITIONS(-DHAVE_ICONV_CONST)
+ELSE(HAVE_ICONV_CONST)
+  REMOVE_DEFINITIONS(-DHAVE_ICONV_CONST)
+ENDIF(HAVE_ICONV_CONST)
+
+## TinyGetText library compilation
+
+## build list of source files
+
+FILE(GLOB TINYGETTEXT_SOURCES RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} tinygettext/*.cpp)
+FILE(GLOB TINYGETTEXT_HEADERS RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} tinygettext/*.hpp)
+
+## define a target for building the library
+
+ADD_LIBRARY(tinygettext ${TINYGETTEXT_SOURCES})
+
+## Add tinygettext dir to search path
+
+INCLUDE_DIRECTORIES(${tinygettext_SOURCE_DIR})
+
+## Debug options
+
+OPTION(WERROR "Stops on first compiler warning in debug mode" OFF)
+IF(CMAKE_COMPILER_IS_GNUCC)
+  ADD_DEFINITIONS(-O3 -Wall -Wextra -Weffc++ -pedantic) 
+  # -ansi fails in MinGW
+  OPTION(WARNINGS "Enable long list of warnings for compiler to check" ON)
+  IF(WARNINGS)
+    ADD_DEFINITIONS(
+          -Wabi  -Wctor-dtor-privacy
+          -Wstrict-null-sentinel
+          -Wold-style-cast
+          -Woverloaded-virtual
+          -Wsign-promo -Wswitch-enum
+          -Wcast-align  -Wcast-qual
+          -Wdisabled-optimization
+          -Wfloat-equal  
+          -Wformat=2
+          -Winit-self 
+          -Winvalid-pch  -Wunsafe-loop-optimizations
+          -Wlogical-op 
+          -Wmissing-format-attribute  -Wmissing-include-dirs -Wmissing-noreturn 
+          -Wpacked
+          -Wredundant-decls
+          -Wshadow
+          -Wsign-conversion  -Wstack-protector
+          -Wstrict-overflow=5
+          -Wswitch-default  -Wswitch-enum
+          -Wundef)
+        # Still left:
+        # -Wconversion  (find alternative to using toupper(int) on char)
+        # -Wpadded      (DictionaryManager has a bool that sticks out)
+  ENDIF(WARNINGS)
+  IF(WERROR)
+    ADD_DEFINITIONS(-Werror)
+  ENDIF(WERROR)
+ENDIF(CMAKE_COMPILER_IS_GNUCC)
+
+## Extra definitions
+
+ADD_DEFINITIONS(-DVERSION=\\\"${VERSION}\\\")
+
+## Generate test executables in the right place
+
+SET(EXECUTABLE_OUTPUT_PATH ${tinygettext_BINARY_DIR}/test)
+
+## Build tinygettext tests
+
+FOREACH(TEST tinygettext_test po_parser_test)
+  ## Add target for tinygettext test
+  ADD_EXECUTABLE(${TEST} test/${TEST}.cpp)
+  ## Link with tinygettext library
+  TARGET_LINK_LIBRARIES(${TEST} tinygettext)
+  TARGET_LINK_LIBRARIES(${TEST} ${ICONV_LIBRARY})
+ENDFOREACH(TEST)
+
+## Install tinygettext
+
+# use standardized variable name
+SET(LIB_SUBDIR "lib${LIB_SUFFIX}"
+	CACHE STRING "Subdirectory of prefix into which libraries are installed (e.g., lib32, lib64)")
+
+## prepare tinygettext.pc
+CONFIGURE_FILE(tinygettext.pc.in tinygettext.pc @ONLY)
+
+INSTALL(TARGETS tinygettext
+	ARCHIVE DESTINATION ${LIB_SUBDIR}
+	LIBRARY DESTINATION ${LIB_SUBDIR})
+INSTALL(FILES ${TINYGETTEXT_HEADERS}
+	DESTINATION include/tinygettext)
+INSTALL(FILES ${tinygettext_BINARY_DIR}/tinygettext.pc
+	DESTINATION ${LIB_SUBDIR}/pkgconfig)
Index: libraries/source/tinygettext/COPYING
===================================================================
--- libraries/source/tinygettext/COPYING	(revision 0)
+++ libraries/source/tinygettext/COPYING	(working copy)
@@ -0,0 +1,339 @@
+                    GNU GENERAL PUBLIC LICENSE
+                       Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+                            Preamble
+
+  The licenses for most software are designed to take away your
+freedom to share and change it.  By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users.  This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it.  (Some other Free Software Foundation software is covered by
+the GNU Lesser General Public License instead.)  You can apply it to
+your programs, too.
+
+  When we speak of free software, we are referring to freedom, not
+price.  Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+  To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+  For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have.  You must make sure that they, too, receive or can get the
+source code.  And you must show them these terms so they know their
+rights.
+
+  We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+  Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software.  If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+  Finally, any free program is threatened constantly by software
+patents.  We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary.  To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.
+
+                    GNU GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License.  The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language.  (Hereinafter, translation is included without limitation in
+the term "modification".)  Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope.  The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+  1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+  2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+    a) You must cause the modified files to carry prominent notices
+    stating that you changed the files and the date of any change.
+
+    b) You must cause any work that you distribute or publish, that in
+    whole or in part contains or is derived from the Program or any
+    part thereof, to be licensed as a whole at no charge to all third
+    parties under the terms of this License.
+
+    c) If the modified program normally reads commands interactively
+    when run, you must cause it, when started running for such
+    interactive use in the most ordinary way, to print or display an
+    announcement including an appropriate copyright notice and a
+    notice that there is no warranty (or else, saying that you provide
+    a warranty) and that users may redistribute the program under
+    these conditions, and telling the user how to view a copy of this
+    License.  (Exception: if the Program itself is interactive but
+    does not normally print such an announcement, your work based on
+    the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole.  If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works.  But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+  3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+    a) Accompany it with the complete corresponding machine-readable
+    source code, which must be distributed under the terms of Sections
+    1 and 2 above on a medium customarily used for software interchange; or,
+
+    b) Accompany it with a written offer, valid for at least three
+    years, to give any third party, for a charge no more than your
+    cost of physically performing source distribution, a complete
+    machine-readable copy of the corresponding source code, to be
+    distributed under the terms of Sections 1 and 2 above on a medium
+    customarily used for software interchange; or,
+
+    c) Accompany it with the information you received as to the offer
+    to distribute corresponding source code.  (This alternative is
+    allowed only for noncommercial distribution and only if you
+    received the program in object code or executable form with such
+    an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it.  For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable.  However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+  4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License.  Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+  5. You are not required to accept this License, since you have not
+signed it.  However, nothing else grants you permission to modify or
+distribute the Program or its derivative works.  These actions are
+prohibited by law if you do not accept this License.  Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+  6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions.  You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+  7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all.  For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices.  Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+  8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded.  In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+  9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time.  Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number.  If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation.  If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+  10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission.  For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this.  Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+                            NO WARRANTY
+
+  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+                     END OF TERMS AND CONDITIONS
+
+            How to Apply These Terms to Your New Programs
+
+  If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+  To do so, attach the following notices to the program.  It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+    tinygettext - A gettext replacement that works directly on .po files
+    Copyright (C) 2006 Ingo Ruhnke <grumbel@gmx.de>
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 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 General Public License for more details.
+
+    You should have received a copy of the GNU 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.
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+    Gnomovision version 69, Copyright (C) year name of author
+    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+    This is free software, and you are welcome to redistribute it
+    under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License.  Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary.  Here is a sample; alter the names:
+
+  Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+  `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+  <signature of Ty Coon>, 1 April 1989
+  Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs.  If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library.  If this is what you want to do, use the GNU Lesser General
+Public License instead of this License.
Index: libraries/source/tinygettext/FindICONV.cmake
===================================================================
--- libraries/source/tinygettext/FindICONV.cmake	(revision 0)
+++ libraries/source/tinygettext/FindICONV.cmake	(working copy)
@@ -0,0 +1,100 @@
+#
+#  Copyright (c) 2006, Peter K�mmel, <syntheticpp@gmx.net>
+#
+#  Redistribution and use in source and binary forms, with or without
+#  modification, are permitted provided that the following conditions
+#  are met:
+#  
+#  1. Redistributions of source code must retain the copyright
+#     notice, this list of conditions and the following disclaimer.
+#  2. Redistributions in binary form must reproduce the copyright
+#     notice, this list of conditions and the following disclaimer in the
+#     documentation and/or other materials provided with the distribution.
+#  3. The name of the author may not be used to endorse or promote products 
+#     derived from this software without specific prior written permission.
+#  
+#  THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+#  IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+#  OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+#  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+#  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+#  NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+#  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+#  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+#  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+#  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#  
+
+set(CMAKE_ALLOW_LOOSE_LOOP_CONSTRUCTS true)
+
+if (ICONV_INCLUDE_DIR)
+  # Already in cache, be silent
+  set(ICONV_FIND_QUIETLY TRUE)
+endif()
+
+find_path(ICONV_INCLUDE_DIR iconv.h
+ /usr/include
+ /usr/local/include)
+
+set(POTENTIAL_ICONV_LIBS iconv libiconv libiconv2)
+
+find_library(ICONV_LIBRARY NAMES ${POTENTIAL_ICONV_LIBS}
+	PATHS /usr/lib /usr/local/lib)
+
+if(WIN32)
+	set(ICONV_DLL_NAMES iconv.dll  libiconv.dll libiconv2.dll)
+	find_file(ICONV_DLL   
+					NAMES ${ICONV_DLL_NAMES}
+					PATHS ENV PATH
+					NO_DEFAULT_PATH)
+	find_file(ICONV_DLL_HELP   
+					NAMES ${ICONV_DLL_NAMES}
+					PATHS ENV PATH
+					${ICONV_INCLUDE_DIR}/../bin)
+	if(ICONV_FIND_REQUIRED)
+		if(NOT ICONV_DLL AND NOT ICONV_DLL_HELP)
+			message(FATAL_ERROR "Could not find iconv.dll, please add correct your PATH environment variable")
+		endif()
+		if(NOT ICONV_DLL AND ICONV_DLL_HELP)
+			get_filename_component(ICONV_DLL_HELP ${ICONV_DLL_HELP} PATH)
+			message(STATUS)
+			message(STATUS "Could not find iconv.dll in standard search path, please add ")
+			message(STATUS "${ICONV_DLL_HELP}")
+			message(STATUS "to your PATH environment variable.")
+			message(STATUS)
+			message(FATAL_ERROR "exit cmake")
+		endif()
+	endif()
+	if(ICONV_INCLUDE_DIR AND ICONV_LIBRARY AND ICONV_DLL)
+   		set(ICONV_FOUND TRUE)
+	endif()
+else()
+	include(CheckFunctionExists)
+	check_function_exists(iconv HAVE_ICONV_IN_LIBC)
+	if(ICONV_INCLUDE_DIR AND HAVE_ICONV_IN_LIBC)
+   		set(ICONV_FOUND TRUE)
+		set(ICONV_LIBRARY  CACHE TYPE STRING FORCE)
+	endif()
+	if(ICONV_INCLUDE_DIR AND ICONV_LIBRARY)
+   		set(ICONV_FOUND TRUE)
+	endif()
+endif()
+
+
+
+if(ICONV_FOUND)
+   if(NOT ICONV_FIND_QUIETLY)
+      message(STATUS "Found iconv library: ${ICONV_LIBRARY}")
+      #message(STATUS "Found iconv   dll  : ${ICONV_DLL}")
+   endif()
+else()
+   if(ICONV_FIND_REQUIRED)
+      message(STATUS "Looked for iconv library named ${POTENTIAL_ICONV_LIBS}.")
+      message(STATUS "Found no acceptable iconv library. This is fatal.")
+      message(STATUS "iconv header: ${ICONV_INCLUDE_DIR}")
+      message(STATUS "iconv lib   : ${ICONV_LIBRARY}")
+      message(FATAL_ERROR "Could NOT find iconv library")
+   endif()
+endif()
+
+mark_as_advanced(ICONV_LIBRARY ICONV_INCLUDE_DIR)
Index: libraries/source/tinygettext/NEWS
===================================================================
--- libraries/source/tinygettext/NEWS	(revision 0)
+++ libraries/source/tinygettext/NEWS	(working copy)
@@ -0,0 +1,6 @@
+tinygettext 0.0.1 - (??. Feb 2009)
+==================================
+
+* initial release
+
+# EOF #
Index: libraries/source/tinygettext/README
===================================================================
--- libraries/source/tinygettext/README	(revision 0)
+++ libraries/source/tinygettext/README	(working copy)
@@ -0,0 +1,21 @@
+tinygettext
+===========
+
+tinygettext is a minimal gettext() replacement written in C++. It can
+read .po files directly and doesn't need .mo files generated from .po.
+It also can read the .po files from arbitary locations, so its much
+better suited for non-Unix systems and situations in which one wants
+to store or distrubite .po files seperatly from the software itself.
+
+
+
+Detecting the locale setting
+============================
+
+Different operating systems store the default locale in different
+places; a portable way to find it is provided by FindLocale:
+
+ * http://icculus.org/~aspirin/findlocale/
+
+
+# EOF #
Index: libraries/source/tinygettext/SConstruct
===================================================================
--- libraries/source/tinygettext/SConstruct	(revision 0)
+++ libraries/source/tinygettext/SConstruct	(working copy)
@@ -0,0 +1,37 @@
+# -*- python -*-
+
+env = Environment(CXXFLAGS=['-O0',
+                            '-g3',
+                            '-Wall',
+                            '-Wcast-qual',
+                            '-Wconversion',
+                            '-Weffc++',
+                            '-Werror',
+                            '-Wextra',
+                            '-Winit-self',
+                            '-Wno-unused-parameter',
+                            '-Wnon-virtual-dtor',
+                            '-Wshadow',
+                            '-ansi',
+                            '-pedantic',
+                            ],
+                  CPPPATH=['tinygettext', '.'])
+
+# env.ParseConfig("sdl-config --cflags --libs")
+# env['CPPDEFINES'] += HAVE_SDL
+
+libtinygettext = env.SharedLibrary('tinygettext/tinygettext', 
+                                   ['tinygettext/tinygettext.cpp',
+                                    'tinygettext/language.cpp',
+                                    'tinygettext/plural_forms.cpp',
+                                    'tinygettext/dictionary.cpp',
+                                    'tinygettext/dictionary_manager.cpp',
+                                    'tinygettext/unix_file_system.cpp',
+                                    'tinygettext/po_parser.cpp',
+                                    'tinygettext/iconv.cpp',
+                                    'tinygettext/log.cpp'])
+
+env.Program('test/tinygettext_test', ['test/tinygettext_test.cpp', libtinygettext])
+env.Program('test/po_parser_test', ['test/po_parser_test.cpp', libtinygettext])
+
+# EOF #
Index: libraries/source/tinygettext/TODO
===================================================================
--- libraries/source/tinygettext/TODO	(revision 0)
+++ libraries/source/tinygettext/TODO	(working copy)
@@ -0,0 +1,76 @@
+tinygettext API related stuff:
+==============================
+
+* translate, translate_ctxt, translate_ctxt_plural, ... could be
+  unified via overloading, not sure if that is a good idea. For the
+  same reason add_translation() could be de-overloaded, to
+  add_translation_ctxt, ...
+
+* iconv handling needs cleanup and more flexibility, since some
+  systems don't provide iconv or only through SDL
+
+* Customizability could use grouping and documentation or other means
+  to make it more obvious:
+
+  - POParser::pedantic
+  - iconv (???)
+  - logging (log_callback(std::string))
+
+* handle errors better, not with log_* stream, cases of errors:
+
+  - couldn't translate
+  - collision while adding translation
+  - failure to open file or directory
+  - unknown language
+  - iconv failure to convert charset
+
+* ABI management/freezing. If tinygettext is to benefit other projects,
+  it should be able to provide a stable API (and, better, ABI).
+
+
+tinygettext implementation details:
+===================================
+
+* with PluralForms moved into Dictionary a lot of the Langugae stuff
+  is pointless
+
+* get rid of goto
+
+* POParser can handle Big5, but needs testing.
+  Big5 is one byte for ASCII letters and two bytes for chinese ones,
+  this means some two byte characters collide with '\', some .po files
+  seem to escape the \ properly so that the string can be read as
+  usual, while others don't.
+
+* _()  -> getext() (gettext default)
+  N_(id) -> gettext_noop(id) (gettext default)
+  C_(ctxt, id) -> pgettext(ctxt, id) (Gnome does this: http://library.gnome.org/devel/glib/2.16/glib-I18N.html#Q-:CAPS)
+  NC_(ctxt, id) -> pgettext(ctxt, id) (Gnome does this: http://library.gnome.org/devel/glib/2.16/glib-I18N.html#Q-:CAPS)
+
+* figure out how up-to-date other tinygettext implementations in the
+  wild are (LinCity):
+
+  Pingus: 
+  -------
+  dictionary.hpp (synced with Pingus)
+  dictionary_manager.hpp (PhysFS vs opendir())
+  language_def.hpp (synced with Pingus)
+  po_file_reader.hpp (UTF-8 0xef-'header', lots of stuff from mathner)
+  tinygettext.hpp (iconv vs convert)
+
+
+Random Unimportant Stuff
+========================
+
+* a hashmap instead of std::map might be a good idea
+
+* support for .gmo files would be cool
+
+tinygettext Documentation:
+==========================
+
+* recommend a way to handle translation of speech and other data files
+
+* document how to use tinygettext and make it work like gettext
+
+# EOF #
Index: libraries/source/tinygettext/build.sh
===================================================================
--- libraries/source/tinygettext/build.sh	(revision 0)
+++ libraries/source/tinygettext/build.sh	(working copy)
@@ -0,0 +1,23 @@
+#!/bin/sh
+
+set -e
+
+JOBS=${JOBS:="-j2"}
+
+echo "Building TinyGettext…"
+echo
+
+scons ${JOBS}
+
+mkdir -p lib/
+
+if [ "`uname -s`" = "Darwin" ]
+then
+  extension=dylib
+else
+  extension=so
+fi
+
+filepath=tinygettext/libtinygettext.${extension}
+cp $filepath lib/
+cp $filepath ../../../binaries/system/

Property changes on: libraries/source/tinygettext/build.sh
___________________________________________________________________
Added: svn:executable
## -0,0 +1 ##
+*
\ No newline at end of property
Index: libraries/source/tinygettext/test/broken.po
===================================================================
--- libraries/source/tinygettext/test/broken.po	(revision 0)
+++ libraries/source/tinygettext/test/broken.po	(working copy)
@@ -0,0 +1,57 @@
+# SOME DESCRIPTIVE TITLE.
+# Copyright (C) YEAR Free Software Foundation, Inc.
+# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
+#
+#, fuzzy
+msgid ""
+msgstr ""
+"Project-Id-Version: PACKAGE VERSION\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2009-01-30 08:01+0100\n"
+"PO-Revision-Date: 2009-01-30 08:39+0100\n"
+"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
+"Language-Team: LANGUAGE <LL@li.org>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+#: helloworld.cpp:7
+msgid "Short Hello World"
+msgstr "kurzes Hallo Welt
+
+#: helloworld.cpp:8 helloworld.cpp:14
+#, fuzzy
+msgid "Hello World"
+msgid_plural "Hello Worlds"
+msgstr[0] "Hallo Welt (singular)"
+msgstr[1] "Hallo Welt (plural)"
+msgstr[10] "Hallo Welt (plural)"
+
+#: helloworld.cpp:10 helloworld.cpp:16
+#, fuzzy
+msgctxt ""
+msgid "Hello World"
+msgid_plural "Hello Worlds"
+msgstr[0] Hallo Welt (singular) mit leerem Kontext"
+msgstr[1] "Hallo Welt (plural) mit leerem Kontext"
+
+#: helloworld.cpp:11 helloworld.cpp:17
+msgctxt "console"
+msgid "Hello World"
+msgid_plural "Hello Worlds"
+msgstr[0]"Hallo Welt (singular) in der Console"
+msgstr[1] "Hallo Welt (plural) in der Console"
+
+#: helloworld.cpp:13
+msgid "gui"
+msgid_plural "Hello World"
+msgstr[0]	"Hallo Welt (singular)"
+msgstr[1] "Hallo Welt (plural)"
+
+#: helloworld.cpp:18
+#, fuzzy
+msgctxt "gui"
+msgid "Hello World"
+msgid_plural "Hello Worlds"
+msgstr[0] "Hallo Welt im GUI"
+msgstr[1] "Hallo Welt (plural) im GUI"
Index: libraries/source/tinygettext/test/game/de.po
===================================================================
--- libraries/source/tinygettext/test/game/de.po	(revision 0)
+++ libraries/source/tinygettext/test/game/de.po	(working copy)
@@ -0,0 +1,1040 @@
+# SOME DESCRIPTIVE TITLE.
+# Copyright (C) YEAR Free Software Foundation, Inc.
+# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: Pingus 0.6.0\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2004-04-09 18:37+0000\n"
+"PO-Revision-Date: 2003-04-15 17:31+0200\n"
+"Last-Translator: David Philippi <david@torangan.de>\n"
+"Language-Team: David Philippi <david@torangan.de>, Ingo Ruhnke <grumbel@gmx."
+"de>, Giray Devlet <giray@devlet.cc>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=ISO-8859-1\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+#: src/actions/bridger.cxx:48 src/actions/bridger.cxx:232
+#: src/pingu_enums.cxx:40
+msgid "Bridger"
+msgstr "Bridger"
+
+#: src/config.cxx:73
+msgid "Couldn't open: "
+msgstr "Datei oder Verzeichnis konnte nicht ge�ffnet werden: "
+
+#: src/config.cxx:172
+msgid "Unexpected char: '"
+msgstr "Unerwartetes Zeichen: '"
+
+#: src/config.cxx:206
+msgid "Unexpected char '"
+msgstr "Unerwartetes Zeichen: '"
+
+#: src/credits.cxx:48
+msgid "-Idea"
+msgstr "-Idee"
+
+#: src/credits.cxx:52
+msgid "-Maintaining"
+msgstr "-Verwaltung"
+
+#: src/credits.cxx:56
+msgid "-Programming"
+msgstr "-Programmierung"
+
+#: src/credits.cxx:62
+msgid "-Porting (Win32)"
+msgstr "-Portierung (Win32)"
+
+#: src/credits.cxx:70
+msgid "-Gfx"
+msgstr "-Grafiken"
+
+#: src/credits.cxx:82
+msgid "-Music"
+msgstr "-Musik"
+
+#: src/credits.cxx:88
+msgid "-Level Design"
+msgstr "-Level Design"
+
+#: src/credits.cxx:93
+msgid "-Story"
+msgstr "-Geschichte"
+
+#: src/credits.cxx:97
+msgid "-Translation"
+msgstr "-�bersetzung"
+
+#: src/credits.cxx:112
+msgid "-Special"
+msgstr "-Besonderen"
+
+#: src/credits.cxx:113
+msgid "-Thanks to"
+msgstr "-Dank an"
+
+#: src/credits.cxx:154
+msgid "_And a very Special Thanks"
+msgstr "_Und einen besonderen Dank"
+
+#: src/credits.cxx:155
+msgid "_to all the people who"
+msgstr "_an alle Leute die"
+
+#: src/credits.cxx:156
+msgid "_contribute to"
+msgstr "_an Freier Software"
+
+#: src/credits.cxx:157
+msgid "_Free Software!"
+msgstr "_mitarbeiten!"
+
+#: src/credits.cxx:163
+msgid "_Thank you for"
+msgstr "_Dankesch�n f�rs"
+
+#: src/credits.cxx:164
+msgid "_playing!"
+msgstr "_spielen!"
+
+#: src/editor/editor_event.cxx:588
+msgid "Enter filename to save as:"
+msgstr "Datei speichern als:  "
+
+#: src/editor/editor_help_screen.cxx:43
+msgid "Editor Helpscreen (hide with F1)"
+msgstr "Editor Hilfe (ausblenden mit F1)"
+
+#: src/editor/editor_help_screen.cxx:51
+msgid "F1 - show/hide this help screen"
+msgstr "F1 - Hilfe anzeigen/verstecken"
+
+#: src/editor/editor_help_screen.cxx:52
+msgid "F2 - launch level building tutorial"
+msgstr "F2 - Starte Levelbau Tutorial"
+
+#: src/editor/editor_help_screen.cxx:53
+msgid "F3 - toggle background color"
+msgstr "F3 - Hintergrundfarbe aendern"
+
+#: src/editor/editor_help_screen.cxx:54
+msgid "F4 - play/test the level"
+msgstr "F4 - Level starten/testen"
+
+#: src/editor/editor_help_screen.cxx:55
+msgid "F5 - load a level"
+msgstr "Level Laden (F5)"
+
+#: src/editor/editor_help_screen.cxx:56
+msgid "F6 - save this level"
+msgstr "Level Speichern (F6)"
+
+#: src/editor/editor_help_screen.cxx:57
+msgid "F7 - [unset]"
+msgstr "F7 - [nicht belegt]"
+
+#: src/editor/editor_help_screen.cxx:58
+msgid "F8 - quick save/backup save?!"
+msgstr "F8 - Schnellspeichern/Backup"
+
+#: src/editor/editor_help_screen.cxx:59
+msgid "F9 - change level width and height"
+msgstr "F9 - Level H�he und Breite �ndern"
+
+#: src/editor/editor_help_screen.cxx:60
+msgid "F10 - [unset]"
+msgstr "F10 - [nicht belegt]"
+
+#: src/editor/editor_help_screen.cxx:61
+msgid "F11 - toggle fps counter"
+msgstr "F11 - fps Z�hler an/aus"
+
+#: src/editor/editor_help_screen.cxx:62
+msgid "F12 - make screenshot"
+msgstr "F12 - Screenshot erstellen"
+
+#: src/editor/editor_help_screen.cxx:66
+msgid "Home - increase object size"
+msgstr "Einfg - Objekt vergr��ern"
+
+#: src/editor/editor_help_screen.cxx:67
+msgid "End  - decrease object size"
+msgstr "Ende - Objekt verkleinern"
+
+#: src/editor/editor_help_screen.cxx:68
+msgid "Cursor Keys - Move object"
+msgstr "Cursor Tasten - Objekt bewegen"
+
+#: src/editor/editor_help_screen.cxx:69
+msgid "Shift 'Cursor Keys' - Move objects fast "
+msgstr "Shift Cursor Tasten - Objekt schneller bewegen"
+
+#: src/editor/editor_help_screen.cxx:70
+msgid "PageUp   - level object up"
+msgstr "Bild rauf - Objekt nach oben"
+
+#: src/editor/editor_help_screen.cxx:71
+msgid "PageDown - level object down"
+msgstr "Bild runter - Objekt nach unten"
+
+#: src/editor/editor_help_screen.cxx:72
+msgid "Shift PageUp   - increase objects z-pos by 50"
+msgstr "Shift Bild rauf - Objekt nach oben"
+
+#: src/editor/editor_help_screen.cxx:73
+msgid "Shift PageDown - decrease objects z-pos by 50"
+msgstr "Shift Bild runter - Objekt nach unten"
+
+#: src/editor/editor_help_screen.cxx:74
+msgid "Enter - Set default zoom (1:1)"
+msgstr "Eingabe - Setze Standard Zoom (1:1)"
+
+#: src/editor/editor_help_screen.cxx:75
+msgid "d - duplicate object"
+msgstr "d - Objekt kopieren"
+
+#: src/editor/editor_help_screen.cxx:76
+msgid "a - mark all objects"
+msgstr "a - Alle Objekte markieren"
+
+#: src/editor/editor_help_screen.cxx:77
+msgid "shift leftmouseclick - add object to selection"
+msgstr "Shift + linke Maustaste - Objekt zur Auswahl tun"
+
+#: src/editor/editor_help_screen.cxx:78
+msgid "leftmouseclick - select object"
+msgstr "linke Maustaste - Objekt ausw�hlen"
+
+#: src/editor/editor_help_screen.cxx:79
+msgid "Insert - insert new object"
+msgstr "Einf�gen - neues Objekt einf�gen"
+
+#: src/editor/editor_help_screen.cxx:80
+msgid "Remove - remove selected object"
+msgstr "Entfernen - entferne ausgew�hltes Objekt"
+
+#: src/editor/editor_help_screen.cxx:81
+msgid "g - ungroup/group current selection"
+msgstr "g - Auswahl gruppieren / Gruppierung aufheben"
+
+#: src/editor/editor_help_screen.cxx:82
+msgid "Ctrl PageUp   - increase objects z-pos by 1"
+msgstr "Strg Bild rauf - z-pos des Objekts um 1 erh�hen"
+
+#: src/editor/editor_help_screen.cxx:83
+msgid "Ctrl PageDown - decrease objects z-pos by 1"
+msgstr "Strg Bild runter - z-pos des Objekts um 1 senken"
+
+#: src/editor/editor_help_screen.cxx:89
+msgid "Naming Convention: <LEVELNAME><NUMBER>-<CREATOR>.plf"
+msgstr "Dateinamensvorgabe: <LEVELNAME><NUMMER>-<AUTOR>.pfl"
+
+#: src/editor/editor_help_screen.cxx:91
+msgid ""
+"When you have created a level and want to have it in the next Pingus "
+"release,\n"
+"please mail it to pingus-devel@nongnu.org."
+msgstr ""
+"Falls Du einen Level erstellt hast und ihn gerne im n�chsten Pingus\n"
+"Release h�ttest, schicke ihn an pingus-devel@nongnu.org."
+
+#: src/editor/object_selector.cxx:106
+msgid "1 - guillotine"
+msgstr "1 - Guillotine"
+
+#: src/editor/object_selector.cxx:107
+msgid "2 - hammer"
+msgstr "2 - Hammer"
+
+#: src/editor/object_selector.cxx:108
+msgid "3 - spike"
+msgstr "3 - Stacheln"
+
+#: src/editor/object_selector.cxx:109
+msgid "4 - laser_exit"
+msgstr "4 - Laser Ausgang"
+
+#: src/editor/object_selector.cxx:110
+msgid "5 - fake_exit"
+msgstr "5 - T�usch Ausgang"
+
+#: src/editor/object_selector.cxx:111
+msgid "6 - smasher"
+msgstr "6 - Stampfer"
+
+#: src/editor/object_selector.cxx:112
+msgid "7 - bumper"
+msgstr "7 - Stosser"
+
+#: src/editor/object_selector.cxx:186
+msgid "Select a WorldObj"
+msgstr "W�hle ein WeltObjekt"
+
+#: src/editor/object_selector.cxx:187
+msgid "1 - teleporter"
+msgstr "1 - Teleporter"
+
+#: src/editor/object_selector.cxx:188
+msgid "2 - switch and door"
+msgstr "2 - Schalter und T�r"
+
+#: src/editor/object_selector.cxx:189
+msgid "3 - ConveyorBelt"
+msgstr "3 - F�rderband"
+
+#: src/editor/object_selector.cxx:190
+msgid "4 - IceBlock"
+msgstr "4 - Eisblock"
+
+#: src/editor/object_selector.cxx:191
+msgid "5 - InfoBox"
+msgstr "5 - InfoBox"
+
+#: src/editor/object_selector.cxx:232
+msgid "Select a weather"
+msgstr "W�hle ein Wetter"
+
+#: src/editor/object_selector.cxx:233
+msgid "1 - snow"
+msgstr "1 - Schnee"
+
+#: src/editor/object_selector.cxx:234
+msgid "2 - rain"
+msgstr "2 - Regen"
+
+#: src/editor/object_selector.cxx:265
+msgid "Select an entrance"
+msgstr "W�hle einen Eingang"
+
+#: src/editor/object_selector.cxx:266
+msgid "1 - generic"
+msgstr "1 - allgemein"
+
+#: src/editor/object_selector.cxx:267
+msgid "2 - woodthing"
+msgstr "2 - h�lzern"
+
+#: src/editor/object_selector.cxx:268
+msgid "3 - cloud"
+msgstr "3 - Wolke"
+
+#: src/editor/object_selector.cxx:269
+msgid "h - entrance surface (hotspot)"
+msgstr "h - Eingangs Grafik (hotspot)"
+
+#: src/editor/object_selector.cxx:343
+msgid "What object type do you want?"
+msgstr "Was f�r ein Objekt willst du?"
+
+#: src/editor/object_selector.cxx:344 src/editor/object_selector.cxx:400
+msgid "h - Hotspot"
+msgstr "h - Grafikelement (hotspot)"
+
+#: src/editor/object_selector.cxx:345
+msgid "g - Groundpiece (ground) [not implemented]"
+msgstr "g - Bodenst�ck (ground) [nicht implementiert]"
+
+#: src/editor/object_selector.cxx:394 src/editor/object_selector.cxx:562
+msgid "Which object do you want?"
+msgstr "Welches Objekt willst du?"
+
+#: src/editor/object_selector.cxx:395
+msgid "g - Groundpiece (ground)"
+msgstr "g - Bodenst�ck (ground)"
+
+#: src/editor/object_selector.cxx:396
+msgid "s - Groundpiece (solid)"
+msgstr "s - Bodenelement (Stahl)"
+
+#: src/editor/object_selector.cxx:397
+msgid "b - Groundpiece (bridge)"
+msgstr "b - Bodenelement (Bruecke)"
+
+#: src/editor/object_selector.cxx:398
+msgid "n - Groundpiece (transparent)"
+msgstr "n - Bodenelement (transparent)"
+
+#: src/editor/object_selector.cxx:399
+msgid "r - Groundpiece (remove)"
+msgstr "r - Bodenelement (entfernen)"
+
+#: src/editor/object_selector.cxx:401
+msgid "e - Entrance"
+msgstr "e - Eingang"
+
+#: src/editor/object_selector.cxx:402
+msgid "x - Exit"
+msgstr "x - Ausgang"
+
+#: src/editor/object_selector.cxx:403
+msgid "l - Liquid"
+msgstr "l - Fl�ssigkeit"
+
+#: src/editor/object_selector.cxx:404
+msgid "w - Weather"
+msgstr "w - Wetter"
+
+#: src/editor/object_selector.cxx:405
+msgid "t - Traps"
+msgstr "t - Falle"
+
+#: src/editor/object_selector.cxx:406
+msgid "o - WorldObject"
+msgstr "o - WeltObjekt"
+
+#: src/editor/object_selector.cxx:407
+msgid "z - Background"
+msgstr "z - Hintergrund"
+
+#: src/editor/object_selector.cxx:408
+msgid "p - Prefab (ObjectGroup)"
+msgstr "p - Prefab (Objekt Gruppe)"
+
+#: src/editor/object_selector.cxx:409
+msgid "f - something from file (~/.pingus/images/)"
+msgstr "f - etwas aus einer Datei (~/.pingus/images/)"
+
+#: src/editor/object_selector.cxx:498
+msgid "Which prefab do you want?"
+msgstr "Welche Prefab willst du?"
+
+#: src/editor/object_selector.cxx:563
+msgid "1 - Surface Background"
+msgstr "1 - Bild Hintergrund"
+
+#: src/editor/object_selector.cxx:564
+msgid "2 - Solid Color Background"
+msgstr "2 - Farb Hintergrund"
+
+#: src/editor/object_selector.cxx:565
+msgid "3 - Starfield Background"
+msgstr "3 - Sternen Hintergrund"
+
+#: src/editor/object_selector.cxx:566
+msgid "4 - Thunderstorm Background"
+msgstr "4 - Gewitter Hintergrund"
+
+#: src/editor/panel_icons.cxx:33
+msgid "Load a level (F5)"
+msgstr "Level laden (F5)"
+
+#: src/editor/panel_icons.cxx:46
+msgid "Exit the editor (Escape)"
+msgstr "Editor Beenden (Esc)"
+
+#: src/editor/panel_icons.cxx:58
+msgid "Save this level (F6)"
+msgstr "Level Speichern (F6)"
+
+#: src/editor/panel_icons.cxx:70
+msgid "Delete marked objects (delete)"
+msgstr "Markierte Objekte L�schen (Entfernen)"
+
+#: src/editor/panel_icons.cxx:82
+msgid "Duplicate current object (d)"
+msgstr "Aktuelles Object kopieren (d)"
+
+#: src/editor/panel_icons.cxx:94
+msgid "Edit Level Properties"
+msgstr "Leveleigenschaften �ndern"
+
+#: src/editor/panel_icons.cxx:106
+msgid "Edit Object Properties"
+msgstr "Objekteigenschaften �ndern"
+
+#: src/editor/panel_icons.cxx:118
+msgid "Start the level and test it (F4)"
+msgstr "Level starten und testen (F4)"
+
+#: src/editor/panel_icons.cxx:130
+msgid "Create a new level from scratch"
+msgstr "Neuen Level erstellen"
+
+#: src/editor/panel_icons.cxx:142
+msgid "Insert an object (Insert)"
+msgstr "Objekt einfuegen (Einfg)"
+
+#: src/editor/panel_icons.cxx:154
+msgid "Zoom into a region"
+msgstr "Einen Bereich vergr�ssern"
+
+#: src/editor/panel_icons.cxx:166
+msgid "Zoom in"
+msgstr "Vergroessern"
+
+#: src/editor/panel_icons.cxx:179
+msgid "Zoom out"
+msgstr "Verkleinern"
+
+#: src/editor/panel_icons.cxx:192
+msgid "Setup Number of Actions"
+msgstr "Stelle die Anzahl der F�higkeiten ein"
+
+#: src/editor/panel_icons.cxx:204
+msgid "Display Help Screen (F1)"
+msgstr "Hilfe Anzeigen (F1)"
+
+#: src/exit_menu.cxx:48
+msgid "Yes"
+msgstr "Ja"
+
+#: src/exit_menu.cxx:81
+msgid "No"
+msgstr "Nein"
+
+#: src/exit_menu.cxx:114
+msgid "Exit Pingus?"
+msgstr "Pingus beenden?"
+
+#: src/fps_counter.cxx:48
+msgid "unknown"
+msgstr "unbekannt"
+
+#: src/game_time.cxx:70
+msgid "unlimited"
+msgstr "unbegrenzt"
+
+#: src/level_desc.cxx:74
+msgid "Designed by "
+msgstr "Erstellt von "
+
+#: src/level_desc.cxx:79
+#, c-format
+msgid "Pingus to Save: %d"
+msgstr "Zu rettende Pingus: %d"
+
+#: src/level_desc.cxx:81
+#, c-format
+msgid "Number of Pingus: %d"
+msgstr "Anzahl an Pingus: %d"
+
+#: src/level_desc.cxx:86
+msgid "Loading..."
+msgstr "Ladevorgang l�uft..."
+
+#: src/level_desc.cxx:89
+msgid "Loading finished. Press a mouse button to start the level"
+msgstr ""
+"Ladevorgang abgeschlossen. Dr�cke eine Maus Taste um den Level zu starten"
+
+#: src/level_result.cxx:61
+msgid "Results:"
+msgstr "Ergebnisse:"
+
+#: src/level_result.cxx:67
+#, c-format
+msgid "Pingus saved:   %3d/%3d"
+msgstr "Gerettete Pingus: %3d/%3d"
+
+#: src/level_result.cxx:72
+#, c-format
+msgid "Pingus died:  %3d/%3d"
+msgstr "Tote Pingus: %3d/%3d"
+
+#: src/level_result.cxx:88
+msgid "Press button to continue..."
+msgstr "Knopf dr�cken um fortzufahren"
+
+#: src/level_result.cxx:102
+msgid ""
+"As many Pingus escaped as entered the level. That's going to be hard to "
+"beat.... unless this game becomes pornographic."
+msgstr ""
+"Es wurden alle Pingu dieses Levels gerettet. Das wird hart zu schlagen "
+"sein... es sei denn dieses Spiel wird pornographisch."
+
+#: src/level_result.cxx:104
+msgid "Very impressive indeed."
+msgstr "In der Tat sehr eindrucksvoll."
+
+#: src/level_result.cxx:106
+msgid "Good work. Still room for improvement though."
+msgstr "Gute Arbeit. Aber �bung macht den Meiser!"
+
+#: src/level_result.cxx:108
+msgid "Not too shabby, not too shabby at all."
+msgstr "Nicht schlecht, nicht schlecht!"
+
+#: src/level_result.cxx:110
+msgid ""
+"That was OK, but Pingu life insurance premiums have just gotten more "
+"expensive."
+msgstr ""
+"Das war ok, aber die Lebensversicherungspr�mien f�r Pingus sind gerade "
+"gestiegen."
+
+#: src/level_result.cxx:112
+msgid "Maybe this level calls for a different strategy."
+msgstr "M�glicherweise verlangt dieser Level eine andere Strategie."
+
+#: src/level_result.cxx:114
+msgid "Exactly half. Are you saving only the female ones?"
+msgstr "Genau die H�lfte! Rettest du nur die Weibchen?"
+
+#: src/level_result.cxx:116
+msgid "If I were a Pingu, I never would have left that entrance."
+msgstr "Wenn ich ein Pingu w�re, h�tte ich den Eingang nie verlassen."
+
+#: src/level_result.cxx:118
+msgid "Maybe you would feel more at home playing Quake."
+msgstr "M�glicherweise w�re es besser Quake zu spielen?"
+
+#: src/level_result.cxx:120
+msgid ""
+"Maybe this level calls for a different strategy. Like attempting to save "
+"them, for example."
+msgstr ""
+"Es kann sein, dass wir etwas anderes versuchen sollten.  Vielleicht k�nnten "
+"wir ja die Pingus retten?"
+
+#: src/level_result.cxx:122
+msgid "Ever considered a career as a Pingu exterminator?"
+msgstr "Hast du mal �ber eine Karriere als Pingu Zerst�rer nachgedacht?"
+
+#: src/level_result.cxx:124
+msgid "You missed one! What's your excuse!?"
+msgstr "Du hast einen vergessen! Was ist deine Entschuldigung?"
+
+#: src/level_result.cxx:126
+msgid "Please reassure me that you hit the Armageddon button."
+msgstr "Best�tige mir bitte, dass das die Armageddon Taste war."
+
+#: src/level_result.cxx:128
+msgid "You've got a negative save/total value, something is buggy."
+msgstr "Ein negativer Wert? Hier liegt ein Fehler vor."
+
+#: src/menu_button.cxx:181
+msgid "..:: The people who brought this game to you ::.."
+msgstr "..:: Die Leute, die fuer dieses Spiel verantwortlich sind... ::.."
+
+#: src/menu_button.cxx:184
+msgid "Credits"
+msgstr "Mitwirkende"
+
+#: src/menu_button.cxx:216
+msgid "..:: Takes you to the options menu ::.."
+msgstr "..:: Einstellungen, Cheats und Debugging stuff ::.."
+
+#: src/menu_button.cxx:219
+msgid "Options"
+msgstr "Einstellungen"
+
+#: src/menu_button.cxx:252
+msgid "..:: Bye, bye ::.."
+msgstr "..:: Auf Wiedersehen ::.."
+
+#: src/menu_button.cxx:255
+msgid "Exit"
+msgstr "Beenden"
+
+#: src/menu_button.cxx:306
+msgid "..:: Launch the level editor ::.."
+msgstr "..:: Erstelle deinen eigenen Level ::.."
+
+#: src/menu_button.cxx:309
+msgid "Create a"
+msgstr "Bau einen"
+
+#: src/menu_button.cxx:310
+msgid "Level"
+msgstr "Level"
+
+#: src/menu_button.cxx:344
+msgid "..:: Start the game ::.."
+msgstr "..:: das Spiel starten ::.."
+
+#: src/menu_button.cxx:345
+msgid "Start"
+msgstr "Start"
+
+#: src/menu_button.cxx:375
+msgid "..:: Start a contrib level ::.."
+msgstr "..:: Contrib level Spielen ::.."
+
+#: src/menu_button.cxx:377
+msgid "Contrib"
+msgstr "Levels"
+
+#: src/menu_button.cxx:399
+msgid "..:: Multiplayer Modes... experimental stuff ::.."
+msgstr "..:: Mehrspieler Modus ::.. Experimentelles Zeug ::.."
+
+#: src/menu_button.cxx:401
+msgid "Multi"
+msgstr "Multi"
+
+#: src/pingu_enums.cxx:35
+msgid "Angel"
+msgstr "Angel"
+
+#: src/pingu_enums.cxx:36
+msgid "Basher"
+msgstr "Basher"
+
+#: src/pingu_enums.cxx:37
+msgid "Blocker"
+msgstr "Blocker"
+
+#: src/pingu_enums.cxx:38
+msgid "Boarder"
+msgstr "Boarder"
+
+#: src/pingu_enums.cxx:39
+msgid "Bomber"
+msgstr "Bomber"
+
+#: src/pingu_enums.cxx:41
+msgid "Climber"
+msgstr "Climber"
+
+#: src/pingu_enums.cxx:42
+msgid "Digger"
+msgstr "Digger"
+
+#: src/pingu_enums.cxx:43
+msgid "Drown"
+msgstr "Drown"
+
+#: src/pingu_enums.cxx:44
+msgid "Exiter"
+msgstr "Exiter"
+
+#: src/pingu_enums.cxx:45
+msgid "Faller"
+msgstr "Faller"
+
+#: src/pingu_enums.cxx:46
+msgid "Floater"
+msgstr "Floater"
+
+#: src/pingu_enums.cxx:47
+msgid "Jumper"
+msgstr "Jumper"
+
+#: src/pingu_enums.cxx:48
+msgid "Laserkill"
+msgstr "Laserkill"
+
+#: src/pingu_enums.cxx:49
+msgid "Miner"
+msgstr "Miner"
+
+#: src/pingu_enums.cxx:50
+msgid "Rocketlauncher"
+msgstr "Rocketlauncher"
+
+#: src/pingu_enums.cxx:51
+msgid "Slider"
+msgstr "Slider"
+
+#: src/pingu_enums.cxx:52
+msgid "Smashed"
+msgstr "Smashed"
+
+#: src/pingu_enums.cxx:53
+msgid "Splashed"
+msgstr "Splashed"
+
+#: src/pingu_enums.cxx:54
+msgid "Superman"
+msgstr "Superman"
+
+#: src/pingu_enums.cxx:55
+msgid "Teleported"
+msgstr "Teleported"
+
+#: src/pingu_enums.cxx:56
+msgid "Waiter"
+msgstr "Waiter"
+
+#: src/pingu_enums.cxx:57
+msgid "Walker"
+msgstr "Walker"
+
+#: src/pingus_counter.cxx:52
+#, c-format
+msgid "Released:%3d/%-3d   Out:%3d   Saved:%3d/%-3d"
+msgstr "Rein: %3d/%-3d  Raus: %3d Gerettet: %3d/%-3d"
+
+#: src/pingus_main.cxx:90
+msgid "| segfault_handler: catched a SIGSEGV."
+msgstr "| segfault_handler: SIGSEGV abgefangen."
+
+#: src/pingus_main.cxx:92
+msgid "| Woops, Pingus just crashed, congratulations you've found a bug."
+msgstr ""
+"| Woops, Pingus ist abgest�rzt. Gratuliere, du hast einen Bug gefunden."
+
+#: src/pingus_main.cxx:93
+msgid ""
+"| Please write a little bug report to <grumbel@gmx.de>, include informations"
+msgstr ""
+"| Bitte schreibe einen kleinen Report an <pingus-devel@nongnu.org, mit "
+"Informationen,"
+
+#: src/pingus_main.cxx:94
+msgid "| where exacly the SIGSEGV occured and how to reproduce it."
+msgstr "| wo genau der SIGSEGV auftrat und wie man ihn reproduziert."
+
+#: src/pingus_main.cxx:95
+msgid "| Also try include a backtrace, you can get it like this:"
+msgstr "| Versuche auch einen backtrace zu erstellen, du bekommst ihn so:"
+
+#: src/pingus_main.cxx:101
+msgid "| If that doesn't work, try this:"
+msgstr "| Wenn das nicht geht, versuche dies:"
+
+#: src/pingus_main.cxx:105
+msgid "| [play until it crashes again]"
+msgstr "| [spiele bis es wieder crasht]"
+
+#: src/pingus_main.cxx:113
+msgid "| Warning: Pingus recieved a SIGINT, exiting now."
+msgstr "| Warnung: Pingus erhielt einen SIGINT, beende jetzt."
+
+#: src/pingus_main.cxx:301
+msgid "Warning: Larger resolution than 800x600 will result in visual problems"
+msgstr ""
+"Warnung: Aufl�sungen gr�sser als 800x600 k�nnen zu visuellen Problemen f�hren"
+
+#: src/pingus_main.cxx:488
+msgid "Unknow char: "
+msgstr "Unbekannter Buchstabe: "
+
+#: src/pingus_main.cxx:489
+msgid "Usage: "
+msgstr "Benutzung: "
+
+#: src/pingus_main.cxx:489
+msgid " [OPTIONS]... [LEVELFILE]"
+msgstr "[OPTIONEN]... [LEVELDATEI]"
+
+#: src/pingus_main.cxx:492
+msgid "Options:"
+msgstr "Einstellungen"
+
+#: src/pingus_main.cxx:494
+msgid "Set the resolution for pingus (default: 800x600)"
+msgstr "Setze die Aufl�sung f�r Pingus (Standard: 800x600)"
+
+#: src/pingus_main.cxx:495
+msgid "Displays this help"
+msgstr "Hilfe Anzeigen"
+
+#: src/pingus_main.cxx:496
+msgid "Disable intro"
+msgstr "Intro abschalten"
+
+#: src/pingus_main.cxx:497
+msgid "Use OpenGL"
+msgstr "OpenGL benutzen"
+
+#: src/pingus_main.cxx:499
+msgid "Start in Window Mode"
+msgstr "Pingus im Fenster starten"
+
+#: src/pingus_main.cxx:500
+msgid "Start in Fullscreen"
+msgstr "Pingus im Vollbild starten"
+
+#: src/pingus_main.cxx:504
+msgid "FILE      "
+msgstr "Datei     "
+
+#: src/pingus_main.cxx:504
+msgid "Load a custom level from FILE"
+msgstr "Einen Level aus DATEI laden"
+
+#: src/pingus_main.cxx:505
+msgid "FILE        "
+msgstr "Datei      "
+
+#: src/pingus_main.cxx:505
+msgid "Load a custom worldmap from FILE"
+msgstr "Eine Weltkarte aus DATEI laden"
+
+#: src/pingus_main.cxx:506
+msgid "Print some more messages to stdout, can be set"
+msgstr "Gibt mehr Nachrichten auf stdout aus, kann"
+
+#: src/pingus_main.cxx:507
+msgid "multiple times to increase verbosity"
+msgstr "mehrmals gesetzt werden, um die Genauigkeit zu erh�hen"
+
+#: src/pingus_main.cxx:508
+msgid "Prints version number and exit"
+msgstr "Version ausgeben und beenden"
+
+#: src/pingus_main.cxx:509
+msgid "Launch the Level editor (experimental)"
+msgstr "Level Editor starten (Experimentell)"
+
+#: src/pingus_main.cxx:510
+msgid "Disable automatic scrolling"
+msgstr "Automatisches Scrollen abschalten"
+
+#: src/pingus_main.cxx:512
+msgid "Enable software cursor"
+msgstr "Aktiviere Software Cursor"
+
+#: src/pingus_main.cxx:515
+msgid "Don't read ~/.pingus/config"
+msgstr "~/.pingus/config nicht einlesen"
+
+#: src/pingus_main.cxx:516
+msgid "FILE       "
+msgstr "Datei      "
+
+#: src/pingus_main.cxx:516
+msgid "Read config from FILE (default: ~/.pingus/config)"
+msgstr "Konfiguration aus DATEI lesen"
+
+#: src/pingus_main.cxx:517
+msgid "reduce CPU usage, might speed up the game on slower machines"
+msgstr ""
+"reduziere CPU Belastung, k�nnte das Spiel auf langsamen Rechnern "
+"beschleunigen"
+
+#: src/pingus_main.cxx:518
+msgid "Uses the controller given in FILE"
+msgstr "Controller aus FILE benutzen"
+
+#: src/pingus_main.cxx:520
+msgid "Debugging and experimental stuff:"
+msgstr "Debug und Experimentelles Zeug"
+
+#: src/pingus_main.cxx:521
+msgid "Enables some features, only interesting programmers"
+msgstr "Aktiviere einige Funktionen, nur f�r Programmierer"
+
+#: src/pingus_main.cxx:522
+msgid "Enable the output of debugging infos, possible"
+msgstr "Aktiviere die Ausgabe von Debug Informationen, m�gliche"
+
+#: src/pingus_main.cxx:523
+msgid "OPTION's are tiles, gametime, actions, sound, resources, gui,"
+msgstr "Optionen sind tiles, gametime, actions, sound, resources, gui,"
+
+#: src/pingus_main.cxx:525
+msgid "Skip at least N frames, larger values speed the game up"
+msgstr ""
+"�berspringe mindestens N Bilder, gr��ere Werte erh�hen die Geschwindigkeit"
+
+#: src/pingus_main.cxx:526
+msgid "Skip at most N frames"
+msgstr "�berspringe maximal N Bilder"
+
+#: src/pingus_main.cxx:527
+msgid "Set both min and max frameskip to N"
+msgstr "Setze sowohl minimalen als auch maximalen Bildsprung auf N"
+
+#: src/pingus_main.cxx:528
+msgid "Set the game speed (0=fastest, >0=slower)"
+msgstr "Setze die Geschwindigkeit (0=schnellste, >0=langsamer)"
+
+#: src/pingus_main.cxx:529
+msgid "Prints the fps to stdout"
+msgstr "Schreibe die fps auf stdout"
+
+#: src/pingus_main.cxx:530
+msgid "Set the size of the map tiles (default: 32)"
+msgstr "Setze die Gr��e der Kartenteile (Standard: 32)"
+
+#: src/pingus_main.cxx:531
+msgid "Disable some cpu intensive features"
+msgstr "Deaktivere einige CPU intensive Funktionen"
+
+#: src/pingus_main.cxx:532
+msgid "Reduces the CPU usage by issuing sleep()"
+msgstr "Reduziert die CPU Belastung durch Verwendung von sleep()"
+
+#: src/pingus_main.cxx:534
+msgid "Demo playing and recording:"
+msgstr "Demo aufzeichnung und wiedergabe:"
+
+#: src/pingus_main.cxx:535
+msgid "FILE     "
+msgstr "Datei    "
+
+#: src/pingus_main.cxx:535
+msgid "Plays a demo session from FILE"
+msgstr "Spielt eine Demo Sitzung aus FILE"
+
+#: src/pingus_main.cxx:537
+msgid "Record demos for each played level"
+msgstr "Nehme Demos f�r jeden gespielten Level auf"
+
+#: src/pingus_main.cxx:539
+msgid "Sound:"
+msgstr "Sound"
+
+#: src/pingus_main.cxx:540
+msgid "Disable sound"
+msgstr "Sound deaktivieren"
+
+#: src/pingus_main.cxx:541
+msgid "Disable music"
+msgstr "Musik deaktivieren"
+
+#: src/pingus_main.cxx:720
+msgid "clanVorbis support:           ok"
+msgstr "clanVorbis Unterst�tzung:    ok"
+
+#: src/pingus_main.cxx:722
+msgid "clanVoribs support:  missing (.ogg music files will not be playable)"
+msgstr ""
+"clanVorbis Unterst�tzung: fehlt (.ogg Musik Datein k�nnen nicht abgespielt "
+"werden)"
+
+#: src/pingus_main.cxx:726
+msgid "clanMikMod support:           ok"
+msgstr "clanMikMod Unterst�tzung:    ok"
+
+#: src/pingus_main.cxx:728
+msgid "clanMikMod support:  missing (music files will not be playable)"
+msgstr ""
+"clanMikMod Unters�tzung: fehlt (Musikdateien k�nnen nicht abgespielt werden)"
+
+#: src/pingus_main.cxx:732
+msgid "getext support:               ok"
+msgstr "gettext Unterst�tzung:       ok"
+
+#: src/pingus_main.cxx:733
+msgid "gettext language:        english"
+msgstr "gettext Sprache:        deutsch"
+
+#: src/pingus_main.cxx:739
+msgid "sound support:           enabled"
+msgstr "Sound Unterst�tzung:         an"
+
+#: src/pingus_main.cxx:741
+msgid "sound support:          disabled"
+msgstr "Sound Unterst�tzung:        aus"
+
+#: src/pingus_main.cxx:744
+msgid "music support:           enabled"
+msgstr "Musik Unterst�tzung:         an"
+
+#: src/pingus_main.cxx:746
+msgid "music support:          disabled"
+msgstr "Musik Unterst�tzung:        aus"
+
+#: src/pingus_main.cxx:748
+msgid "resolution set to:       "
+msgstr "Aufl�sung:              "
+
+#: src/pingus_main.cxx:749
+msgid "fullscreen:              "
+msgstr "Vollbild:           "
+
+#: src/pingus_main.cxx:750
+msgid " enabled"
+msgstr "aktiviert"
+
+#: src/pingus_main.cxx:750
+msgid "disabled"
+msgstr "deaktiviert"
+
Index: libraries/source/tinygettext/test/helloworld/de.po
===================================================================
--- libraries/source/tinygettext/test/helloworld/de.po	(revision 0)
+++ libraries/source/tinygettext/test/helloworld/de.po	(working copy)
@@ -0,0 +1,56 @@
+# SOME DESCRIPTIVE TITLE.
+# Copyright (C) YEAR Free Software Foundation, Inc.
+# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
+#
+#, fuzzy
+msgid ""
+msgstr ""
+"Project-Id-Version: PACKAGE VERSION\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2009-01-30 08:01+0100\n"
+"PO-Revision-Date: 2009-01-30 08:39+0100\n"
+"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
+"Language-Team: LANGUAGE <LL@li.org>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+#: helloworld.cpp:7
+msgid "Short Hello World"
+msgstr "kurzes Hallo Welt"
+
+#: helloworld.cpp:8 helloworld.cpp:14
+#, fuzzy
+msgid "Hello World"
+msgid_plural "Hello Worlds"
+msgstr[0] "Hallo Welt (singular)"
+msgstr[1] "Hallo Welt (plural)"
+
+#: helloworld.cpp:10 helloworld.cpp:16
+#, fuzzy
+msgctxt ""
+msgid "Hello World"
+msgid_plural "Hello Worlds"
+msgstr[0] "Hallo Welt (singular) mit leerem Kontext"
+msgstr[1] "Hallo Welt (plural) mit leerem Kontext"
+
+#: helloworld.cpp:11 helloworld.cpp:17
+msgctxt "console"
+msgid "Hello World"
+msgid_plural "Hello Worlds"
+msgstr[0] "Hallo Welt (singular) in der Console"
+msgstr[1] "Hallo Welt (plural) in der Console"
+
+#: helloworld.cpp:13
+msgid "gui"
+msgid_plural "Hello World"
+msgstr[0] "Hallo Welt (singular)"
+msgstr[1] "Hallo Welt (plural)"
+
+#: helloworld.cpp:18
+#, fuzzy
+msgctxt "gui"
+msgid "Hello World"
+msgid_plural "Hello Worlds"
+msgstr[0] "Hallo Welt im GUI"
+msgstr[1] "Hallo Welt (plural) im GUI"
Index: libraries/source/tinygettext/test/helloworld/helloworld.pot
===================================================================
--- libraries/source/tinygettext/test/helloworld/helloworld.pot	(revision 0)
+++ libraries/source/tinygettext/test/helloworld/helloworld.pot	(working copy)
@@ -0,0 +1,55 @@
+# SOME DESCRIPTIVE TITLE.
+# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
+# This file is distributed under the same license as the PACKAGE package.
+# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
+#
+#, fuzzy
+msgid ""
+msgstr ""
+"Project-Id-Version: PACKAGE VERSION\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2009-01-30 08:10+0100\n"
+"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
+"Language-Team: LANGUAGE <LL@li.org>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=CHARSET\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=INTEGER; plural=EXPRESSION;\n"
+
+#: helloworld.cpp:7
+msgid "Short Hello World"
+msgstr ""
+
+#: helloworld.cpp:8 helloworld.cpp:14
+msgid "Hello World"
+msgid_plural "Hello Worlds"
+msgstr[0] ""
+msgstr[1] ""
+
+#: helloworld.cpp:10 helloworld.cpp:16
+msgctxt ""
+msgid "Hello World"
+msgid_plural "Hello Worlds"
+msgstr[0] ""
+msgstr[1] ""
+
+#: helloworld.cpp:11 helloworld.cpp:17
+msgctxt "console"
+msgid "Hello World"
+msgid_plural "Hello Worlds"
+msgstr[0] ""
+msgstr[1] ""
+
+#: helloworld.cpp:13
+msgid "gui"
+msgid_plural "Hello World"
+msgstr[0] ""
+msgstr[1] ""
+
+#: helloworld.cpp:18
+msgctxt "gui"
+msgid "Hello World"
+msgid_plural "Hello Worlds"
+msgstr[0] ""
+msgstr[1] ""
Index: libraries/source/tinygettext/test/helloworld.cpp
===================================================================
--- libraries/source/tinygettext/test/helloworld.cpp	(revision 0)
+++ libraries/source/tinygettext/test/helloworld.cpp	(working copy)
@@ -0,0 +1,24 @@
+#include <iostream>
+
+#define _(x) gettext(x)
+
+int main()
+{
+  std::cout << _("Short Hello World") << std::endl;
+  std::cout << gettext("Hello World") << std::endl;
+  std::cout << gettext("Hello Worlds") << std::endl;
+
+  std::cout << pgettext("", "Hello World") << std::endl;
+  std::cout << pgettext("console", "Hello World") << std::endl;
+
+  std::cout << ngettext("gui", "Hello World") << std::endl;
+  std::cout << ngettext("Hello World", "Hello Worlds", 5) << std::endl;
+
+  std::cout << npgettext("", "Hello World", "Hello Worlds", 5) << std::endl;
+  std::cout << npgettext("console", "Hello World", "Hello Worlds", 5) << std::endl;
+  std::cout << npgettext("gui", "Hello World", "Hello Worlds", 5) << std::endl;
+
+  return 0;
+}
+
+/* EOF */
Index: libraries/source/tinygettext/test/level/de.po
===================================================================
--- libraries/source/tinygettext/test/level/de.po	(revision 0)
+++ libraries/source/tinygettext/test/level/de.po	(working copy)
@@ -0,0 +1,379 @@
+# SOME DESCRIPTIVE TITLE.
+# Copyright (C) YEAR Free Software Foundation, Inc.
+# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
+#
+#, fuzzy
+msgid ""
+msgstr ""
+"Project-Id-Version: PACKAGE VERSION\n"
+"PO-Revision-Date: YEAR-MO-DA HO:MI +ZONE\n"
+"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
+"Language-Team: LANGUAGE <LL@li.org>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=CHARSET\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+#: src/pingus_main.cxx:760
+msgid "PingusMain: Starting Main: "
+msgstr "PingusMain: Hauptteil wird gestartet: "
+
+#: src/pingus_main.cxx:805
+msgid "PingusMain: Levelfile not found, ignoring: "
+msgstr "PingusMain: Leveldatei nicht gefunden, Fehler wird ignoriert: "
+
+#: src/pingus_main.cxx:909
+msgid "Error caught from ClanLib: "
+msgstr "ClanLib Fehler abgefangen: "
+
+#: src/pingus_main.cxx:913
+msgid "Error caught from Pingus: "
+msgstr "Pingus Fehler wurde abgefangen: "
+
+#: src/pingus_main.cxx:917
+msgid "Pingus: Out of memory!"
+msgstr "Pingus: Speicher ist ausgegangen"
+
+#: src/pingus_main.cxx:921
+msgid "Pingus: Standard exception caught!:\n"
+msgstr "Pingus: Standard Ausnahme abgefangen!:\n"
+
+#: src/pingus_main.cxx:925
+msgid "Pingus: Unknown throw caught!"
+msgstr "Pingus: Unbekannte Ausnahme abgefangen!"
+
+#: src/result_screen.cxx:99 src/start_screen.cxx:111
+msgid "Abort"
+msgstr "Abbruch"
+
+#: src/result_screen.cxx:167
+msgid "Retry"
+msgstr "Versuche erneut"
+
+#: src/result_screen.cxx:175
+msgid "Success!"
+msgstr "Erfolg!"
+
+#: src/result_screen.cxx:182
+msgid "Failure!"
+msgstr "Fehler!"
+
+#: src/result_screen.cxx:191
+msgid "Perfect! You saved everyone possible - great!"
+msgstr "Perfekt! Du hast alle gerettet!"
+
+#: src/result_screen.cxx:193
+msgid "No-one got killed, pretty good work."
+msgstr "Keiner wurde get�tet, sehr gute Arbeit."
+
+#: src/result_screen.cxx:195
+msgid ""
+"You saved exactly what you needed - you made it, but\n"
+"maybe you can do better?"
+msgstr ""
+"Du hast so viele gerettet wie n�tig. Du hast es\n"
+"geschafft, aber vielleicht kannst Du es noch besser?"
+
+#: src/result_screen.cxx:198
+msgid "Not everybody was saved, but still good work!"
+msgstr "Nicht alle wurden gerettet, aber trotzdem noch gute Arbeit!"
+
+#: src/result_screen.cxx:200
+msgid "What can I say, you made it - congratulations!"
+msgstr "Was soll ich sagen, Du hast es geschafft. Gratuliere!"
+
+#: src/result_screen.cxx:205
+msgid "You killed everybody, not good."
+msgstr "Du hast alle get�tet, nicht gut."
+
+#: src/result_screen.cxx:207
+msgid "No-one got saved - I know you can do better."
+msgstr "Keiner wurde gerettet, ich wei�, dass du es besser kannst."
+
+#: src/result_screen.cxx:209
+msgid ""
+"You didn't save enough, but you saved a few.  Next\n"
+"time you might do better."
+msgstr ""
+"Du hast nicht genug gerettet, aber immerhin ein paar.\n"
+"N�chstes Mal machst du es bestimmt besser."
+
+#: src/result_screen.cxx:212
+msgid "Only one more and you would have made it - try again!"
+msgstr "Einer mehr und du hast es, versuch es nochmal!"
+
+#: src/result_screen.cxx:214
+msgid "Only a handful more and you would have made it - try again!"
+msgstr "Nur ein paar mehr und du h�ttest es, versuch es nochmal!"
+
+#: src/result_screen.cxx:216
+msgid "Better luck next time!"
+msgstr "Mehr Gl�ck f�rs n�chste Mal!"
+
+#: src/result_screen.cxx:232
+msgid "Saved: "
+msgstr "Gerettet: "
+
+#: src/result_screen.cxx:236
+msgid "Died: "
+msgstr "Get�tet: "
+
+#: src/result_screen.cxx:240
+msgid "Time left: "
+msgstr "Verbliebene Zeit: "
+
+#: src/screenshot.cxx:45
+msgid "Screenshot: Saving screenshot to: "
+msgstr "Screenshot: Speichere Screenshot als: "
+
+#: src/screenshot.cxx:47
+msgid "Screenshot: Screenshot is done."
+msgstr "Screenshot: Screenshot wurde erstellt."
+
+#: src/screenshot.cxx:53
+msgid "Screenshot: Couldn't save screenshot"
+msgstr "Screenshot: Screenshot konnte nicht gespeichert werden"
+
+#: src/screenshot.cxx:138
+msgid "Screenshot: Couldn't write file: "
+msgstr "Screenshot: Datei konnte nicht geschrieben werden: "
+
+#: src/spot_map.cxx:286
+#, c-format
+msgid "Image has wrong color depth: %d"
+msgstr "Bild hat falsche Farbtiefe: %d"
+
+#: src/start_screen.cxx:75
+msgid "Ok"
+msgstr "Ok"
+
+#: src/start_screen.cxx:158
+msgid "Number of Pingus: "
+msgstr "Anzahl an Pingus: "
+
+#: src/start_screen.cxx:161
+msgid "Number to Save: "
+msgstr "Zu rettende Pingus: "
+
+#: src/start_screen.cxx:164
+msgid "Time: "
+msgstr "Zeit: "
+
+#: src/start_screen.cxx:167
+msgid "Difficulty:"
+msgstr "Schwierigkeitsgrad:"
+
+#: src/start_screen.cxx:175
+msgid "Author: "
+msgstr "Autor: "
+
+#: src/start_screen.cxx:178
+msgid "Filename: "
+msgstr "Dateiname: "
+
+#: src/story.cxx:41
+msgid "The Journey Continues"
+msgstr "Die Reise geht weiter"
+
+#: src/story.cxx:46
+msgid ""
+"Now after you and the Pingus have learned the basics and\n"
+"practiced a bit it is time to move on and begin the journey into\n"
+"the world. Since the ice floe with which the Pingus traveled to the\n"
+"Tutorial Island isn't going to hold on the whole way into the warmer\n"
+"climates the Pingus have to find something else to guide\n"
+"them on their journey.\n"
+msgstr ""
+"Nachdem Du und die Pingus nun die Grundlagen gelernt und\n"
+"ein wenig �bung haben, ist es an der Zeit, weiter zu gehen und die\n"
+"Reise in die Welt zu beginnen. Da die Scholle, mit der die Pingus zum\n"
+"Tutorial Island reisten, nicht den ganzen Weg in die w�rmeren Regionen\n"
+"halten wird, m�ssen die Pingus etwas anderes finden, um sie auf der\n"
+"Reise zu begleiten.\n"
+
+#: src/story.cxx:58
+msgid ""
+"But as the eldest have said, the Tutorial Island provides not\n"
+"only a good way to practice, but it is also the starting point into\n"
+"the world. After some searching the Pingus discovered the meaning\n"
+"of this, and they found the large tree at the end of the island\n"
+"which gave them wood to construct a float.\n"
+msgstr ""
+"Aber wie die Weisen sagten, ist Tutorial Island nicht nur\n"
+"eine M�glichkeit zum �ben, es ist auch der erste Schritt in\n"
+"die Welt, denn das Holz der B�ume am Ende der Insel liefert\n"
+"gutes Material, um ein Flo� zu bauen.\n"
+
+#: src/story.cxx:69
+msgid ""
+"So the Pingus set out and constructed some large rafts, enough\n"
+"to carry them all. After also packing a bunch of provisions\n"
+"they were prepared to start their journey and leave\n"
+"their familiar ground and enter the unknown parts of the world.\n"
+msgstr ""
+"So gingen die Pingus hin und bauten ein paar gro�e\n"
+"Fl��e, genug, um alle zu tragen. Nachdem sie auch noch einigen\n"
+"Proviant eingepackt hatten, waren sie endlich bereit, ihre Reise zu\n"
+"beginnen, den bekannten Bereich zu verlassen und die unbekannten\n"
+"Bereiche der Welt zu betreten.\n"
+
+#: src/story.cxx:79
+msgid ""
+"So the Pingus sit on their raft, worrying about what's to come and\n"
+"where to go, while floating into the sunset.\n"
+"\n"
+"To be continued..."
+msgstr ""
+"So sa�en die Pingus nur auf ihrem Flo� und sorgten sich, was denn nun\n"
+"kommen m�ge, w�hrend sie in den Sonnenuntergang trieben.\n"
+"\n"
+"Fortsetzung folgt..."
+
+#: src/story.cxx:91
+msgid "The Journey Begins"
+msgstr "Die Reise beginnt"
+
+#: src/story.cxx:96
+msgid ""
+"For a long time, the Pingus have lived happily in peace on the\n"
+"South Pole along with all the other animals. Everything was in\n"
+"balance and it seemed like nothing could disrupt their peace.  The\n"
+"Pingus were happy and it seemed like this could never end.\n"
+msgstr ""
+"Die Pingus lebten schon lange gl�cklich und in Frieden am S�dpol,\n"
+"zusammen mit all den anderen Tieren. Alles war im Gleichgewicht und\n"
+"es schien, als k�nnte nichts ihren Frieden st�ren. Die Pingus waren\n"
+"gl�cklich und es schien, als w�rde dies niemals enden.\n"
+
+#: src/story.cxx:106
+msgid ""
+"But then one day, things began to change slowly: the sky got darker\n"
+"and the earth got warmer. Firstly, they thought this was just a\n"
+"normal fluctuation in the world's climate, but things seemed to get\n"
+"worse and worse with every year."
+msgstr ""
+"Aber dann, eines Tages, ver�nderten sich die Dinge langsam. Der\n"
+"Himmel wurde dunkler und die Erde w�rmer. Zuerst dachten sie, dies\n"
+"w�re nur eine normale Schwankung im Klima, aber es wurde von Jahr \n"
+"zu Jahr immer schlimmer."
+
+#: src/story.cxx:117
+msgid ""
+"The snow began to melt away in a few areas and food became an\n"
+"issue. Other animals tried to leave the region to search\n"
+"for colder areas, but the Pingus knew that this wouldn't help:\n"
+"they knew that they had to do something about it."
+msgstr ""
+"Der Schnee begann in einigen Bereichen zu schmelzen und Nahrung\n"
+"wurde ein Problem. Andere Tiere begannen bereits, die Region zu\n"
+"verlassen, um k�ltere Gebiete zu suchen. Aber die Pingus wussten,\n"
+"dass dies nicht helfen w�rde, sie wussten, es musste etwas gegen\n"
+"dieses Problem getan werden."
+
+#: src/story.cxx:127
+msgid ""
+"So the circle of the eldest came together to decide what to do\n"
+"about it. They decided to send out an expedition around the world\n"
+"to find the cause of this warming. The expedition consisted of\n"
+"hundreds of the bravest Pingus on the South Pole."
+msgstr ""
+"Darum traf sich der Rat der �ltesten, um zu entscheiden, was dagegen\n"
+"getan werden sollte. Sie entschieden, eine Expedition um die Welt\n"
+"zu senden, um den Grund f�r die Erw�rmung zu finden. Die Expedition\n"
+"bestand aus hunderten der mutigsten Pingus des ganzen S�dpols."
+
+#: src/story.cxx:137
+msgid ""
+"And they picked you to lead them on their journey around the\n"
+"world. Since the journey will be dangerous and difficult, your\n"
+"first goal is the Island of Mogorok, also known as the Tutorial\n"
+"Island. According to the eldest, this island has always been the\n"
+"first stop of Pingus that were sent out into the world."
+msgstr ""
+"Und sie w�hlten dich, um sie auf der Reise um die Welt zu f�hren.\n"
+"Denn die Reise wird gef�hrlich und schwierig werden. Dein erstes Ziel ist\n"
+"die Insel Mogorok, auch bekannt als Tutorial Island. Den Weisen\n"
+"zufolge war diese Insel immer der erste Anlaufpunkt f�r Pingus,\n"
+"die in die Welt gesandt wurden."
+
+#: src/story.cxx:148
+msgid ""
+"The island consists of many areas that are ideal to teach the\n"
+"Pingus their abilities. The Pingus can learn to build\n"
+"bridges, climb, bash and use many other talents which they\n"
+"will need on their long and dangerous journey."
+msgstr ""
+"Die Insel besteht aus verschiedenen Regionen, die ideal sind, um die\n"
+"F�higkeiten der Pingus zu trainieren. Sie k�nnen dort ihre F�hig-\n"
+"keiten im Br�ckenbau, klettern, graben und all die anderen Talente\n"
+"trainieren, die sie sicher auf der langen und gef�hrlichen Reise\n"
+"ben�tigen werden."
+
+#: src/story.cxx:158
+msgid ""
+"While there, you can practice your abilities in commanding\n"
+"and guiding the Pingus. You can also get familiar with\n"
+"all the abilities the Pingus provide and learn to master them,\n"
+"since you will need all of them on your journey around the\n"
+"world."
+msgstr ""
+"W�hrenddessen kannst Du auf der anderen Seite deine F�higkeit, die\n"
+"Pingus zu leiten und zu f�hren, trainieren. Du kannst dich dort auch mit\n"
+"allen F�higkeiten vertraut machen, die die Pingus besitzen und\n"
+"erlernen, sie zu meistern, denn du wirst sie sicher alle auf der\n"
+"Reise um die Welt ben�tigen."
+
+#: src/story.cxx:169
+msgid ""
+"Now that you and the Pingus have arrived at Tutorial Island it\n"
+"is time to take command and begin your mission.\n"
+"\n"
+"Good Luck!"
+msgstr ""
+"Nun da du und die Pingus im Tutorial Island angekommen sind,\n"
+"musst du das Kommando �bernehmen und deine Mission beginnen.\n"
+"\n"
+"Viel Gl�ck!"
+
+#: src/system.cxx:273
+msgid "Environment variable $HOME not set, fix that and start again."
+msgstr ""
+"Umgebungs Variable $HOME ist nicht gesetzt. Setze sie und starte erneut."
+
+#: src/worldmap/level_dot.cxx:174 src/worldmap/level_dot.cxx:184
+msgid "locked"
+msgstr "gesperrt"
+
+#: src/worldmap/manager.cxx:103
+msgid "Show Ending?"
+msgstr "Ende anzeigen?"
+
+#: src/worldmap/manager.cxx:133
+msgid "Show Story?"
+msgstr "Story zeigen?"
+
+#: src/worldmap/manager.cxx:161
+msgid "Leave?"
+msgstr "Verlassen?"
+
+#: src/worldmap/manager.cxx:201
+msgid "Enter?"
+msgstr "Betreten?"
+
+#: src/worldmap/worldmap.cxx:77
+msgid "WorldMap: File not found: "
+msgstr "Worldmap: Datei nicht gefunden: "
+
+#: src/worldmap/worldmap.cxx:261
+msgid "...walking..."
+msgstr "...laufe..."
+
+msgid "You got %d error.\n"
+msgid_plural "You got %d error.\n"
+msgstr[0] "Du hast %d fehler\n"
+msgstr[1] "Du hast %d fehlers\n"
+
+msgid "found %d fatal error"
+msgid_plural "found %d fatal errors"
+msgstr[0] "s'ha trobat %d error fatal"
+msgstr[1] "s'han trobat %d errors fatals"
+
Index: libraries/source/tinygettext/test/po/de.po
===================================================================
--- libraries/source/tinygettext/test/po/de.po	(revision 0)
+++ libraries/source/tinygettext/test/po/de.po	(working copy)
@@ -0,0 +1,1047 @@
+# SOME DESCRIPTIVE TITLE.
+# Copyright (C) YEAR Free Software Foundation, Inc.
+# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: Pingus 0.6.0\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2004-04-09 18:37+0000\n"
+"PO-Revision-Date: 2009-02-01 17:44+0100\n"
+"Last-Translator: David Philippi <david@torangan.de>\n"
+"Language-Team: David Philippi <david@torangan.de>, Ingo Ruhnke <grumbel@gmx.de>, Giray Devlet <giray@devlet.cc>\n"
+"MIME-Version: 1.0\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+msgid "umlaut"
+msgstr "ÄÖÜäöüß"
+
+#: src/actions/bridger.cxx:48 src/actions/bridger.cxx:232
+#: src/pingu_enums.cxx:40
+msgid "Bridger"
+msgstr "Bridger"
+
+#: src/config.cxx:73
+msgid "Couldn't open: "
+msgstr "Datei oder Verzeichnis konnte nicht ge�ffnet werden: "
+
+#: src/config.cxx:172
+msgid "Unexpected char: '"
+msgstr "Unerwartetes Zeichen: '"
+
+#: src/config.cxx:206
+msgid "Unexpected char '"
+msgstr "Unerwartetes Zeichen: '"
+
+#: src/credits.cxx:48
+msgid "-Idea"
+msgstr "-Idee"
+
+#: src/credits.cxx:52
+msgid "-Maintaining"
+msgstr "-Verwaltung"
+
+#: src/credits.cxx:56
+msgid "-Programming"
+msgstr "-Programmierung"
+
+#: src/credits.cxx:62
+msgid "-Porting (Win32)"
+msgstr "-Portierung (Win32)"
+
+#: src/credits.cxx:70
+msgid "-Gfx"
+msgstr "-Grafiken"
+
+#: src/credits.cxx:82
+msgid "-Music"
+msgstr "-Musik"
+
+#: src/credits.cxx:88
+msgid "-Level Design"
+msgstr "-Level Design"
+
+#: src/credits.cxx:93
+msgid "-Story"
+msgstr "-Geschichte"
+
+#: src/credits.cxx:97
+msgid "-Translation"
+msgstr "-�bersetzung"
+
+#: src/credits.cxx:112
+msgid "-Special"
+msgstr "-Besonderen"
+
+#: src/credits.cxx:113
+msgid "-Thanks to"
+msgstr "-Dank an"
+
+#: src/credits.cxx:154
+msgid "_And a very Special Thanks"
+msgstr "_Und einen besonderen Dank"
+
+#: src/credits.cxx:155
+msgid "_to all the people who"
+msgstr "_an alle Leute die"
+
+#: src/credits.cxx:156
+msgid "_contribute to"
+msgstr "_an Freier Software"
+
+#: src/credits.cxx:157
+msgid "_Free Software!"
+msgstr "_mitarbeiten!"
+
+#: src/credits.cxx:163
+msgid "_Thank you for"
+msgstr "_Dankesch�n f�rs"
+
+#: src/credits.cxx:164
+msgid "_playing!"
+msgstr "_spielen!"
+
+#: src/editor/editor_event.cxx:588
+msgid "Enter filename to save as:"
+msgstr "Datei speichern als:  "
+
+#: src/editor/editor_help_screen.cxx:43
+msgid "Editor Helpscreen (hide with F1)"
+msgstr "Editor Hilfe (ausblenden mit F1)"
+
+#: src/editor/editor_help_screen.cxx:51
+msgid "F1 - show/hide this help screen"
+msgstr "F1 - Hilfe anzeigen/verstecken"
+
+#: src/editor/editor_help_screen.cxx:52
+msgid "F2 - launch level building tutorial"
+msgstr "F2 - Starte Levelbau Tutorial"
+
+#: src/editor/editor_help_screen.cxx:53
+msgid "F3 - toggle background color"
+msgstr "F3 - Hintergrundfarbe aendern"
+
+#: src/editor/editor_help_screen.cxx:54
+msgid "F4 - play/test the level"
+msgstr "F4 - Level starten/testen"
+
+#: src/editor/editor_help_screen.cxx:55
+msgid "F5 - load a level"
+msgstr "Level Laden (F5)"
+
+#: src/editor/editor_help_screen.cxx:56
+msgid "F6 - save this level"
+msgstr "Level Speichern (F6)"
+
+#: src/editor/editor_help_screen.cxx:57
+msgid "F7 - [unset]"
+msgstr "F7 - [nicht belegt]"
+
+#: src/editor/editor_help_screen.cxx:58
+msgid "F8 - quick save/backup save?!"
+msgstr "F8 - Schnellspeichern/Backup"
+
+#: src/editor/editor_help_screen.cxx:59
+msgid "F9 - change level width and height"
+msgstr "F9 - Level H�he und Breite �ndern"
+
+#: src/editor/editor_help_screen.cxx:60
+msgid "F10 - [unset]"
+msgstr "F10 - [nicht belegt]"
+
+#: src/editor/editor_help_screen.cxx:61
+msgid "F11 - toggle fps counter"
+msgstr "F11 - fps Z�hler an/aus"
+
+#: src/editor/editor_help_screen.cxx:62
+msgid "F12 - make screenshot"
+msgstr "F12 - Screenshot erstellen"
+
+#: src/editor/editor_help_screen.cxx:66
+msgid "Home - increase object size"
+msgstr "Einfg - Objekt vergr��ern"
+
+#: src/editor/editor_help_screen.cxx:67
+msgid "End  - decrease object size"
+msgstr "Ende - Objekt verkleinern"
+
+#: src/editor/editor_help_screen.cxx:68
+msgid "Cursor Keys - Move object"
+msgstr "Cursor Tasten - Objekt bewegen"
+
+#: src/editor/editor_help_screen.cxx:69
+msgid "Shift 'Cursor Keys' - Move objects fast "
+msgstr "Shift Cursor Tasten - Objekt schneller bewegen"
+
+#: src/editor/editor_help_screen.cxx:70
+msgid "PageUp   - level object up"
+msgstr "Bild rauf - Objekt nach oben"
+
+#: src/editor/editor_help_screen.cxx:71
+msgid "PageDown - level object down"
+msgstr "Bild runter - Objekt nach unten"
+
+#: src/editor/editor_help_screen.cxx:72
+msgid "Shift PageUp   - increase objects z-pos by 50"
+msgstr "Shift Bild rauf - Objekt nach oben"
+
+#: src/editor/editor_help_screen.cxx:73
+msgid "Shift PageDown - decrease objects z-pos by 50"
+msgstr "Shift Bild runter - Objekt nach unten"
+
+#: src/editor/editor_help_screen.cxx:74
+msgid "Enter - Set default zoom (1:1)"
+msgstr "Eingabe - Setze Standard Zoom (1:1)"
+
+#: src/editor/editor_help_screen.cxx:75
+msgid "d - duplicate object"
+msgstr "d - Objekt kopieren"
+
+#: src/editor/editor_help_screen.cxx:76
+msgid "a - mark all objects"
+msgstr "a - Alle Objekte markieren"
+
+#: src/editor/editor_help_screen.cxx:77
+msgid "shift leftmouseclick - add object to selection"
+msgstr "Shift + linke Maustaste - Objekt zur Auswahl tun"
+
+#: src/editor/editor_help_screen.cxx:78
+msgid "leftmouseclick - select object"
+msgstr "linke Maustaste - Objekt ausw�hlen"
+
+#: src/editor/editor_help_screen.cxx:79
+msgid "Insert - insert new object"
+msgstr "Einf�gen - neues Objekt einf�gen"
+
+#: src/editor/editor_help_screen.cxx:80
+msgid "Remove - remove selected object"
+msgstr "Entfernen - entferne ausgew�hltes Objekt"
+
+#: src/editor/editor_help_screen.cxx:81
+msgid "g - ungroup/group current selection"
+msgstr "g - Auswahl gruppieren / Gruppierung aufheben"
+
+#: src/editor/editor_help_screen.cxx:82
+msgid "Ctrl PageUp   - increase objects z-pos by 1"
+msgstr "Strg Bild rauf - z-pos des Objekts um 1 erh�hen"
+
+#: src/editor/editor_help_screen.cxx:83
+msgid "Ctrl PageDown - decrease objects z-pos by 1"
+msgstr "Strg Bild runter - z-pos des Objekts um 1 senken"
+
+#: src/editor/editor_help_screen.cxx:89
+msgid "Naming Convention: <LEVELNAME><NUMBER>-<CREATOR>.plf"
+msgstr "Dateinamensvorgabe: <LEVELNAME><NUMMER>-<AUTOR>.pfl"
+
+#: src/editor/editor_help_screen.cxx:91
+msgid ""
+"When you have created a level and want to have it in the next Pingus "
+"release,\n"
+"please mail it to pingus-devel@nongnu.org."
+msgstr ""
+"Falls Du einen Level erstellt hast und ihn gerne im n�chsten Pingus\n"
+"Release h�ttest, schicke ihn an pingus-devel@nongnu.org."
+
+#: src/editor/object_selector.cxx:106
+msgid "1 - guillotine"
+msgstr "1 - Guillotine"
+
+#: src/editor/object_selector.cxx:107
+msgid "2 - hammer"
+msgstr "2 - Hammer"
+
+#: src/editor/object_selector.cxx:108
+msgid "3 - spike"
+msgstr "3 - Stacheln"
+
+#: src/editor/object_selector.cxx:109
+msgid "4 - laser_exit"
+msgstr "4 - Laser Ausgang"
+
+#: src/editor/object_selector.cxx:110
+msgid "5 - fake_exit"
+msgstr "5 - T�usch Ausgang"
+
+#: src/editor/object_selector.cxx:111
+msgid "6 - smasher"
+msgstr "6 - Stampfer"
+
+#: src/editor/object_selector.cxx:112
+msgid "7 - bumper"
+msgstr "7 - Stosser"
+
+#: src/editor/object_selector.cxx:186
+msgid "Select a WorldObj"
+msgstr "W�hle ein WeltObjekt"
+
+#: src/editor/object_selector.cxx:187
+msgid "1 - teleporter"
+msgstr "1 - Teleporter"
+
+#: src/editor/object_selector.cxx:188
+msgid "2 - switch and door"
+msgstr "2 - Schalter und T�r"
+
+#: src/editor/object_selector.cxx:189
+msgid "3 - ConveyorBelt"
+msgstr "3 - F�rderband"
+
+#: src/editor/object_selector.cxx:190
+msgid "4 - IceBlock"
+msgstr "4 - Eisblock"
+
+#: src/editor/object_selector.cxx:191
+msgid "5 - InfoBox"
+msgstr "5 - InfoBox"
+
+#: src/editor/object_selector.cxx:232
+msgid "Select a weather"
+msgstr "W�hle ein Wetter"
+
+#: src/editor/object_selector.cxx:233
+msgid "1 - snow"
+msgstr "1 - Schnee"
+
+#: src/editor/object_selector.cxx:234
+msgid "2 - rain"
+msgstr "2 - Regen"
+
+#: src/editor/object_selector.cxx:265
+msgid "Select an entrance"
+msgstr "W�hle einen Eingang"
+
+#: src/editor/object_selector.cxx:266
+msgid "1 - generic"
+msgstr "1 - allgemein"
+
+#: src/editor/object_selector.cxx:267
+msgid "2 - woodthing"
+msgstr "2 - h�lzern"
+
+#: src/editor/object_selector.cxx:268
+msgid "3 - cloud"
+msgstr "3 - Wolke"
+
+#: src/editor/object_selector.cxx:269
+msgid "h - entrance surface (hotspot)"
+msgstr "h - Eingangs Grafik (hotspot)"
+
+#: src/editor/object_selector.cxx:343
+msgid "What object type do you want?"
+msgstr "Was f�r ein Objekt willst du?"
+
+#: src/editor/object_selector.cxx:344 src/editor/object_selector.cxx:400
+msgid "h - Hotspot"
+msgstr "h - Grafikelement (hotspot)"
+
+#: src/editor/object_selector.cxx:345
+msgid "g - Groundpiece (ground) [not implemented]"
+msgstr "g - Bodenst�ck (ground) [nicht implementiert]"
+
+#: src/editor/object_selector.cxx:394 src/editor/object_selector.cxx:562
+msgid "Which object do you want?"
+msgstr "Welches Objekt willst du?"
+
+#: src/editor/object_selector.cxx:395
+msgid "g - Groundpiece (ground)"
+msgstr "g - Bodenst�ck (ground)"
+
+#: src/editor/object_selector.cxx:396
+msgid "s - Groundpiece (solid)"
+msgstr "s - Bodenelement (Stahl)"
+
+#: src/editor/object_selector.cxx:397
+msgid "b - Groundpiece (bridge)"
+msgstr "b - Bodenelement (Bruecke)"
+
+#: src/editor/object_selector.cxx:398
+msgid "n - Groundpiece (transparent)"
+msgstr "n - Bodenelement (transparent)"
+
+#: src/editor/object_selector.cxx:399
+msgid "r - Groundpiece (remove)"
+msgstr "r - Bodenelement (entfernen)"
+
+#: src/editor/object_selector.cxx:401
+msgid "e - Entrance"
+msgstr "e - Eingang"
+
+#: src/editor/object_selector.cxx:402
+msgid "x - Exit"
+msgstr "x - Ausgang"
+
+#: src/editor/object_selector.cxx:403
+msgid "l - Liquid"
+msgstr "l - Fl�ssigkeit"
+
+#: src/editor/object_selector.cxx:404
+msgid "w - Weather"
+msgstr "w - Wetter"
+
+#: src/editor/object_selector.cxx:405
+msgid "t - Traps"
+msgstr "t - Falle"
+
+#: src/editor/object_selector.cxx:406
+msgid "o - WorldObject"
+msgstr "o - WeltObjekt"
+
+#: src/editor/object_selector.cxx:407
+msgid "z - Background"
+msgstr "z - Hintergrund"
+
+#: src/editor/object_selector.cxx:408
+msgid "p - Prefab (ObjectGroup)"
+msgstr "p - Prefab (Objekt Gruppe)"
+
+#: src/editor/object_selector.cxx:409
+msgid "f - something from file (~/.pingus/images/)"
+msgstr "f - etwas aus einer Datei (~/.pingus/images/)"
+
+#: src/editor/object_selector.cxx:498
+msgid "Which prefab do you want?"
+msgstr "Welche Prefab willst du?"
+
+#: src/editor/object_selector.cxx:563
+msgid "1 - Surface Background"
+msgstr "1 - Bild Hintergrund"
+
+#: src/editor/object_selector.cxx:564
+msgid "2 - Solid Color Background"
+msgstr "2 - Farb Hintergrund"
+
+#: src/editor/object_selector.cxx:565
+msgid "3 - Starfield Background"
+msgstr "3 - Sternen Hintergrund"
+
+#: src/editor/object_selector.cxx:566
+msgid "4 - Thunderstorm Background"
+msgstr "4 - Gewitter Hintergrund"
+
+#: src/editor/panel_icons.cxx:33
+msgid "Load a level (F5)"
+msgstr "Level laden (F5)"
+
+#: src/editor/panel_icons.cxx:46
+msgid "Exit the editor (Escape)"
+msgstr "Editor Beenden (Esc)"
+
+#: src/editor/panel_icons.cxx:58
+msgid "Save this level (F6)"
+msgstr "Level Speichern (F6)"
+
+#: src/editor/panel_icons.cxx:70
+msgid "Delete marked objects (delete)"
+msgstr "Markierte Objekte L�schen (Entfernen)"
+
+#: src/editor/panel_icons.cxx:82
+msgid "Duplicate current object (d)"
+msgstr "Aktuelles Object kopieren (d)"
+
+#: src/editor/panel_icons.cxx:94
+msgid "Edit Level Properties"
+msgstr "Leveleigenschaften �ndern"
+
+#: src/editor/panel_icons.cxx:106
+msgid "Edit Object Properties"
+msgstr "Objekteigenschaften �ndern"
+
+#: src/editor/panel_icons.cxx:118
+msgid "Start the level and test it (F4)"
+msgstr "Level starten und testen (F4)"
+
+#: src/editor/panel_icons.cxx:130
+msgid "Create a new level from scratch"
+msgstr "Neuen Level erstellen"
+
+#: src/editor/panel_icons.cxx:142
+msgid "Insert an object (Insert)"
+msgstr "Objekt einfuegen (Einfg)"
+
+#: src/editor/panel_icons.cxx:154
+msgid "Zoom into a region"
+msgstr "Einen Bereich vergr�ssern"
+
+#: src/editor/panel_icons.cxx:166
+msgid "Zoom in"
+msgstr "Vergroessern"
+
+#: src/editor/panel_icons.cxx:179
+msgid "Zoom out"
+msgstr "Verkleinern"
+
+#: src/editor/panel_icons.cxx:192
+msgid "Setup Number of Actions"
+msgstr "Stelle die Anzahl der F�higkeiten ein"
+
+#: src/editor/panel_icons.cxx:204
+msgid "Display Help Screen (F1)"
+msgstr "Hilfe Anzeigen (F1)"
+
+#: src/exit_menu.cxx:48
+msgid "Yes"
+msgstr "Ja"
+
+#: src/exit_menu.cxx:81
+msgid "No"
+msgstr "Nein"
+
+#: src/exit_menu.cxx:114
+msgid "Exit Pingus?"
+msgstr "Pingus beenden?"
+
+#: src/fps_counter.cxx:48
+msgid "unknown"
+msgstr "unbekannt"
+
+#: src/game_time.cxx:70
+msgid "unlimited"
+msgstr "unbegrenzt"
+
+#: src/level_desc.cxx:74
+msgid "Designed by "
+msgstr "Erstellt von "
+
+#: src/level_desc.cxx:79
+#, c-format
+msgid "Pingus to Save: %d"
+msgstr "Zu rettende Pingus: %d"
+
+#: src/level_desc.cxx:81
+#, c-format
+msgid "Number of Pingus: %d"
+msgstr "Anzahl an Pingus: %d"
+
+#: src/level_desc.cxx:86
+msgid "Loading..."
+msgstr "Ladevorgang l�uft..."
+
+#: src/level_desc.cxx:89
+msgid "Loading finished. Press a mouse button to start the level"
+msgstr ""
+"Ladevorgang abgeschlossen. Dr�cke eine Maus Taste um den Level zu starten"
+
+#: src/level_result.cxx:61
+msgid "Results:"
+msgstr "Ergebnisse:"
+
+#: src/level_result.cxx:67
+#, c-format
+msgid "Pingus saved:   %3d/%3d"
+msgstr "Gerettete Pingus: %3d/%3d"
+
+#: src/level_result.cxx:72
+#, c-format
+msgid "Pingus died:  %3d/%3d"
+msgstr "Tote Pingus: %3d/%3d"
+
+#: src/level_result.cxx:88
+msgid "Press button to continue..."
+msgstr "Knopf dr�cken um fortzufahren"
+
+#: src/level_result.cxx:102
+msgid ""
+"As many Pingus escaped as entered the level. That's going to be hard to "
+"beat.... unless this game becomes pornographic."
+msgstr ""
+"Es wurden alle Pingu dieses Levels gerettet. Das wird hart zu schlagen "
+"sein... es sei denn dieses Spiel wird pornographisch."
+
+#: src/level_result.cxx:104
+msgid "Very impressive indeed."
+msgstr "In der Tat sehr eindrucksvoll."
+
+#: src/level_result.cxx:106
+msgid "Good work. Still room for improvement though."
+msgstr "Gute Arbeit. Aber �bung macht den Meiser!"
+
+#: src/level_result.cxx:108
+msgid "Not too shabby, not too shabby at all."
+msgstr "Nicht schlecht, nicht schlecht!"
+
+#: src/level_result.cxx:110
+msgid ""
+"That was OK, but Pingu life insurance premiums have just gotten more "
+"expensive."
+msgstr ""
+"Das war ok, aber die Lebensversicherungspr�mien f�r Pingus sind gerade "
+"gestiegen."
+
+#: src/level_result.cxx:112
+msgid "Maybe this level calls for a different strategy."
+msgstr "M�glicherweise verlangt dieser Level eine andere Strategie."
+
+#: src/level_result.cxx:114
+msgid "Exactly half. Are you saving only the female ones?"
+msgstr "Genau die H�lfte! Rettest du nur die Weibchen?"
+
+#: src/level_result.cxx:116
+msgid "If I were a Pingu, I never would have left that entrance."
+msgstr "Wenn ich ein Pingu w�re, h�tte ich den Eingang nie verlassen."
+
+#: src/level_result.cxx:118
+msgid "Maybe you would feel more at home playing Quake."
+msgstr "M�glicherweise w�re es besser Quake zu spielen?"
+
+#: src/level_result.cxx:120
+msgid ""
+"Maybe this level calls for a different strategy. Like attempting to save "
+"them, for example."
+msgstr ""
+"Es kann sein, dass wir etwas anderes versuchen sollten.  Vielleicht k�nnten "
+"wir ja die Pingus retten?"
+
+#: src/level_result.cxx:122
+msgid "Ever considered a career as a Pingu exterminator?"
+msgstr "Hast du mal �ber eine Karriere als Pingu Zerst�rer nachgedacht?"
+
+#: src/level_result.cxx:124
+msgid "You missed one! What's your excuse!?"
+msgstr "Du hast einen vergessen! Was ist deine Entschuldigung?"
+
+#: src/level_result.cxx:126
+msgid "Please reassure me that you hit the Armageddon button."
+msgstr "Best�tige mir bitte, dass das die Armageddon Taste war."
+
+#: src/level_result.cxx:128
+msgid "You've got a negative save/total value, something is buggy."
+msgstr "Ein negativer Wert? Hier liegt ein Fehler vor."
+
+#: src/menu_button.cxx:181
+msgid "..:: The people who brought this game to you ::.."
+msgstr "..:: Die Leute, die fuer dieses Spiel verantwortlich sind... ::.."
+
+#: src/menu_button.cxx:184
+msgid "Credits"
+msgstr "Mitwirkende"
+
+#: src/menu_button.cxx:216
+msgid "..:: Takes you to the options menu ::.."
+msgstr "..:: Einstellungen, Cheats und Debugging stuff ::.."
+
+#: src/menu_button.cxx:219
+msgid "Options"
+msgstr "Einstellungen"
+
+#: src/menu_button.cxx:252
+msgid "..:: Bye, bye ::.."
+msgstr "..:: Auf Wiedersehen ::.."
+
+#: src/menu_button.cxx:255
+msgid "Exit"
+msgstr "Beenden"
+
+#: src/menu_button.cxx:306
+msgid "..:: Launch the level editor ::.."
+msgstr "..:: Erstelle deinen eigenen Level ::.."
+
+#: src/menu_button.cxx:309
+msgid "Create a"
+msgstr "Bau einen"
+
+#: src/menu_button.cxx:310
+msgid "Level"
+msgstr "Level"
+
+#: src/menu_button.cxx:344
+msgid "..:: Start the game ::.."
+msgstr "..:: das Spiel starten ::.."
+
+#: src/menu_button.cxx:345
+msgid "Start"
+msgstr "Start"
+
+#: src/menu_button.cxx:375
+msgid "..:: Start a contrib level ::.."
+msgstr "..:: Contrib level Spielen ::.."
+
+#: src/menu_button.cxx:377
+msgid "Contrib"
+msgstr "Levels"
+
+#: src/menu_button.cxx:399
+msgid "..:: Multiplayer Modes... experimental stuff ::.."
+msgstr "..:: Mehrspieler Modus ::.. Experimentelles Zeug ::.."
+
+#: src/menu_button.cxx:401
+msgid "Multi"
+msgstr "Multi"
+
+#: src/pingu_enums.cxx:35
+msgid "Angel"
+msgstr "Angel"
+
+#: src/pingu_enums.cxx:36
+msgid "Basher"
+msgstr "Basher"
+
+#: src/pingu_enums.cxx:37
+msgid "Blocker"
+msgstr "Blocker"
+
+#: src/pingu_enums.cxx:38
+msgid "Boarder"
+msgstr "Boarder"
+
+#: src/pingu_enums.cxx:39
+msgid "Bomber"
+msgstr "Bomber"
+
+#: src/pingu_enums.cxx:41
+msgid "Climber"
+msgstr "Climber"
+
+#: src/pingu_enums.cxx:42
+msgid "Digger"
+msgstr "Digger"
+
+#: src/pingu_enums.cxx:43
+msgid "Drown"
+msgstr "Drown"
+
+#: src/pingu_enums.cxx:44
+msgid "Exiter"
+msgstr "Exiter"
+
+#: src/pingu_enums.cxx:45
+msgid "Faller"
+msgstr "Faller"
+
+#: src/pingu_enums.cxx:46
+msgid "Floater"
+msgstr "Floater"
+
+#: src/pingu_enums.cxx:47
+msgid "Jumper"
+msgstr "Jumper"
+
+#: src/pingu_enums.cxx:48
+msgid "Laserkill"
+msgstr "Laserkill"
+
+#: src/pingu_enums.cxx:49
+msgid "Miner"
+msgstr "Miner"
+
+#: src/pingu_enums.cxx:50
+msgid "Rocketlauncher"
+msgstr "Rocketlauncher"
+
+#: src/pingu_enums.cxx:51
+msgid "Slider"
+msgstr "Slider"
+
+#: src/pingu_enums.cxx:52
+msgid "Smashed"
+msgstr "Smashed"
+
+#: src/pingu_enums.cxx:53
+msgid "Splashed"
+msgstr "Splashed"
+
+#: src/pingu_enums.cxx:54
+msgid "Superman"
+msgstr "Superman"
+
+#: src/pingu_enums.cxx:55
+msgid "Teleported"
+msgstr "Teleported"
+
+#: src/pingu_enums.cxx:56
+msgid "Waiter"
+msgstr "Waiter"
+
+#: src/pingu_enums.cxx:57
+msgid "Walker"
+msgstr "Walker"
+
+#: src/pingus_counter.cxx:52
+#, c-format
+msgid "Released:%3d/%-3d   Out:%3d   Saved:%3d/%-3d"
+msgstr "Rein: %3d/%-3d  Raus: %3d Gerettet: %3d/%-3d"
+
+#: src/pingus_main.cxx:90
+msgid "| segfault_handler: catched a SIGSEGV."
+msgstr "| segfault_handler: SIGSEGV abgefangen."
+
+#: src/pingus_main.cxx:92
+msgid "| Woops, Pingus just crashed, congratulations you've found a bug."
+msgstr ""
+"| Woops, Pingus ist abgest�rzt. Gratuliere, du hast einen Bug gefunden."
+
+#: src/pingus_main.cxx:93
+msgid ""
+"| Please write a little bug report to <grumbel@gmx.de>, include informations"
+msgstr ""
+"| Bitte schreibe einen kleinen Report an <pingus-devel@nongnu.org, mit "
+"Informationen,"
+
+#: src/pingus_main.cxx:94
+msgid "| where exacly the SIGSEGV occured and how to reproduce it."
+msgstr "| wo genau der SIGSEGV auftrat und wie man ihn reproduziert."
+
+#: src/pingus_main.cxx:95
+msgid "| Also try include a backtrace, you can get it like this:"
+msgstr "| Versuche auch einen backtrace zu erstellen, du bekommst ihn so:"
+
+#: src/pingus_main.cxx:101
+msgid "| If that doesn't work, try this:"
+msgstr "| Wenn das nicht geht, versuche dies:"
+
+#: src/pingus_main.cxx:105
+msgid "| [play until it crashes again]"
+msgstr "| [spiele bis es wieder crasht]"
+
+#: src/pingus_main.cxx:113
+msgid "| Warning: Pingus recieved a SIGINT, exiting now."
+msgstr "| Warnung: Pingus erhielt einen SIGINT, beende jetzt."
+
+#: src/pingus_main.cxx:301
+msgid "Warning: Larger resolution than 800x600 will result in visual problems"
+msgstr ""
+"Warnung: Aufl�sungen gr�sser als 800x600 k�nnen zu visuellen Problemen f�hren"
+
+#: src/pingus_main.cxx:488
+msgid "Unknow char: "
+msgstr "Unbekannter Buchstabe: "
+
+#: src/pingus_main.cxx:489
+msgid "Usage: "
+msgstr "Benutzung: "
+
+#: src/pingus_main.cxx:489
+msgid " [OPTIONS]... [LEVELFILE]"
+msgstr "[OPTIONEN]... [LEVELDATEI]"
+
+#: src/pingus_main.cxx:492
+msgid "Options:"
+msgstr "Einstellungen"
+
+#: src/pingus_main.cxx:494
+msgid "Set the resolution for pingus (default: 800x600)"
+msgstr "Setze die Aufl�sung f�r Pingus (Standard: 800x600)"
+
+#: src/pingus_main.cxx:495
+msgid "Displays this help"
+msgstr "Hilfe Anzeigen"
+
+#: src/pingus_main.cxx:496
+msgid "Disable intro"
+msgstr "Intro abschalten"
+
+#: src/pingus_main.cxx:497
+msgid "Use OpenGL"
+msgstr "OpenGL benutzen"
+
+#: src/pingus_main.cxx:499
+msgid "Start in Window Mode"
+msgstr "Pingus im Fenster starten"
+
+#: src/pingus_main.cxx:500
+msgid "Start in Fullscreen"
+msgstr "Pingus im Vollbild starten"
+
+#: src/pingus_main.cxx:504
+msgid "FILE      "
+msgstr "Datei     "
+
+#: src/pingus_main.cxx:504
+msgid "Load a custom level from FILE"
+msgstr "Einen Level aus DATEI laden"
+
+#: src/pingus_main.cxx:505
+msgid "FILE        "
+msgstr "Datei      "
+
+#: src/pingus_main.cxx:505
+msgid "Load a custom worldmap from FILE"
+msgstr "Eine Weltkarte aus DATEI laden"
+
+#: src/pingus_main.cxx:506
+msgid "Print some more messages to stdout, can be set"
+msgstr "Gibt mehr Nachrichten auf stdout aus, kann"
+
+#: src/pingus_main.cxx:507
+msgid "multiple times to increase verbosity"
+msgstr "mehrmals gesetzt werden, um die Genauigkeit zu erh�hen"
+
+#: src/pingus_main.cxx:508
+msgid "Prints version number and exit"
+msgstr "Version ausgeben und beenden"
+
+#: src/pingus_main.cxx:509
+msgid "Launch the Level editor (experimental)"
+msgstr "Level Editor starten (Experimentell)"
+
+#: src/pingus_main.cxx:510
+msgid "Disable automatic scrolling"
+msgstr "Automatisches Scrollen abschalten"
+
+#: src/pingus_main.cxx:512
+msgid "Enable software cursor"
+msgstr "Aktiviere Software Cursor"
+
+#: src/pingus_main.cxx:515
+msgid "Don't read ~/.pingus/config"
+msgstr "~/.pingus/config nicht einlesen"
+
+#: src/pingus_main.cxx:516
+msgid "FILE       "
+msgstr "Datei      "
+
+#: src/pingus_main.cxx:516
+msgid "Read config from FILE (default: ~/.pingus/config)"
+msgstr "Konfiguration aus DATEI lesen"
+
+#: src/pingus_main.cxx:517
+msgid "reduce CPU usage, might speed up the game on slower machines"
+msgstr ""
+"reduziere CPU Belastung, k�nnte das Spiel auf langsamen Rechnern "
+"beschleunigen"
+
+#: src/pingus_main.cxx:518
+msgid "Uses the controller given in FILE"
+msgstr "Controller aus FILE benutzen"
+
+#: src/pingus_main.cxx:520
+msgid "Debugging and experimental stuff:"
+msgstr "Debug und Experimentelles Zeug"
+
+#: src/pingus_main.cxx:521
+msgid "Enables some features, only interesting programmers"
+msgstr "Aktiviere einige Funktionen, nur f�r Programmierer"
+
+#: src/pingus_main.cxx:522
+msgid "Enable the output of debugging infos, possible"
+msgstr "Aktiviere die Ausgabe von Debug Informationen, m�gliche"
+
+#: src/pingus_main.cxx:523
+msgid "OPTION's are tiles, gametime, actions, sound, resources, gui,"
+msgstr "Optionen sind tiles, gametime, actions, sound, resources, gui,"
+
+#: src/pingus_main.cxx:525
+msgid "Skip at least N frames, larger values speed the game up"
+msgstr ""
+"�berspringe mindestens N Bilder, gr��ere Werte erh�hen die Geschwindigkeit"
+
+#: src/pingus_main.cxx:526
+msgid "Skip at most N frames"
+msgstr "�berspringe maximal N Bilder"
+
+#: src/pingus_main.cxx:527
+msgid "Set both min and max frameskip to N"
+msgstr "Setze sowohl minimalen als auch maximalen Bildsprung auf N"
+
+#: src/pingus_main.cxx:528
+msgid "Set the game speed (0=fastest, >0=slower)"
+msgstr "Setze die Geschwindigkeit (0=schnellste, >0=langsamer)"
+
+#: src/pingus_main.cxx:529
+msgid "Prints the fps to stdout"
+msgstr "Schreibe die fps auf stdout"
+
+#: src/pingus_main.cxx:530
+msgid "Set the size of the map tiles (default: 32)"
+msgstr "Setze die Gr��e der Kartenteile (Standard: 32)"
+
+#: src/pingus_main.cxx:531
+msgid "Disable some cpu intensive features"
+msgstr "Deaktivere einige CPU intensive Funktionen"
+
+#: src/pingus_main.cxx:532
+msgid "Reduces the CPU usage by issuing sleep()"
+msgstr "Reduziert die CPU Belastung durch Verwendung von sleep()"
+
+#: src/pingus_main.cxx:534
+msgid "Demo playing and recording:"
+msgstr "Demo aufzeichnung und wiedergabe:"
+
+#: src/pingus_main.cxx:535
+msgid "FILE     "
+msgstr "Datei    "
+
+#: src/pingus_main.cxx:535
+msgid "Plays a demo session from FILE"
+msgstr "Spielt eine Demo Sitzung aus FILE"
+
+#: src/pingus_main.cxx:537
+msgid "Record demos for each played level"
+msgstr "Nehme Demos f�r jeden gespielten Level auf"
+
+#: src/pingus_main.cxx:539
+msgid "Sound:"
+msgstr "Sound"
+
+#: src/pingus_main.cxx:540
+msgid "Disable sound"
+msgstr "Sound deaktivieren"
+
+#: src/pingus_main.cxx:541
+msgid "Disable music"
+msgstr "Musik deaktivieren"
+
+#: src/pingus_main.cxx:720
+msgid "clanVorbis support:           ok"
+msgstr "clanVorbis Unterst�tzung:    ok"
+
+#: src/pingus_main.cxx:722
+msgid "clanVoribs support:  missing (.ogg music files will not be playable)"
+msgstr ""
+"clanVorbis Unterst�tzung: fehlt (.ogg Musik Datein k�nnen nicht abgespielt "
+"werden)"
+
+#: src/pingus_main.cxx:726
+msgid "clanMikMod support:           ok"
+msgstr "clanMikMod Unterst�tzung:    ok"
+
+#: src/pingus_main.cxx:728
+msgid "clanMikMod support:  missing (music files will not be playable)"
+msgstr ""
+"clanMikMod Unters�tzung: fehlt (Musikdateien k�nnen nicht abgespielt werden)"
+
+#: src/pingus_main.cxx:732
+msgid "getext support:               ok"
+msgstr "gettext Unterst�tzung:       ok"
+
+#: src/pingus_main.cxx:733
+msgid "gettext language:        english"
+msgstr "gettext Sprache:        deutsch"
+
+#: src/pingus_main.cxx:739
+msgid "sound support:           enabled"
+msgstr "Sound Unterst�tzung:         an"
+
+#: src/pingus_main.cxx:741
+msgid "sound support:          disabled"
+msgstr "Sound Unterst�tzung:        aus"
+
+#: src/pingus_main.cxx:744
+msgid "music support:           enabled"
+msgstr "Musik Unterst�tzung:         an"
+
+#: src/pingus_main.cxx:746
+msgid "music support:          disabled"
+msgstr "Musik Unterst�tzung:        aus"
+
+#: src/pingus_main.cxx:748
+msgid "resolution set to:       "
+msgstr "Aufl�sung:              "
+
+#: src/pingus_main.cxx:749
+msgid "fullscreen:              "
+msgstr "Vollbild:           "
+
+#: src/pingus_main.cxx:750
+msgid " enabled"
+msgstr "aktiviert"
+
+#: src/pingus_main.cxx:750
+msgid "disabled"
+msgstr "d�ktiviert"
+
+
+#: src/pingus_main.cxx:751
+msgid "reenabled"
+msgstr ""
Index: libraries/source/tinygettext/test/po/de_AT.po
===================================================================
--- libraries/source/tinygettext/test/po/de_AT.po	(revision 0)
+++ libraries/source/tinygettext/test/po/de_AT.po	(working copy)
@@ -0,0 +1,33 @@
+# SOME DESCRIPTIVE TITLE.
+# Copyright (C) YEAR Free Software Foundation, Inc.
+# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
+#
+#, fuzzy
+msgid ""
+msgstr ""
+"Project-Id-Version: PACKAGE VERSION\n"
+"PO-Revision-Date: 2009-02-02 12:07+0100\n"
+"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
+"Language-Team: LANGUAGE <LL@li.org>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=( n != 1);\n"
+
+msgid "umlaut"
+msgstr "ÄÖÜäöüß€¢"
+
+msgid "You got %d error."
+msgid_plural "You got %d error."
+msgstr[0] "Du hast %d fehler"
+msgstr[1] "Du hast %d fehlers"
+
+msgid "found %d fatal error"
+msgid_plural "found %d fatal errors"
+msgstr[0] "s'ha trobat %d error fätal"
+msgstr[1] "s'han trobat %d errors fätals"
+
+
+msgid "I ate %d pizza."
+msgid_plural "I ate %d pizzas."
+msgstr[0] ""
Index: libraries/source/tinygettext/test/po/fr.po
===================================================================
--- libraries/source/tinygettext/test/po/fr.po	(revision 0)
+++ libraries/source/tinygettext/test/po/fr.po	(working copy)
@@ -0,0 +1,20 @@
+# SOME DESCRIPTIVE TITLE.
+# Copyright (C) YEAR Free Software Foundation, Inc.
+# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
+#
+#, fuzzy
+msgid ""
+msgstr ""
+"Project-Id-Version: PACKAGE VERSION\n"
+"PO-Revision-Date: 2009-01-28 08:45+0100\n"
+"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
+"Language-Team: LANGUAGE <LL@li.org>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=utf-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+#: src/actions/bridger.cxx:48 src/actions/bridger.cxx:232
+#: src/pingu_enums.cxx:40
+msgid "invalid"
+msgstr "ungütig"
+
Index: libraries/source/tinygettext/test/po_parser_test.cpp
===================================================================
--- libraries/source/tinygettext/test/po_parser_test.cpp	(revision 0)
+++ libraries/source/tinygettext/test/po_parser_test.cpp	(working copy)
@@ -0,0 +1,71 @@
+//  tinygettext - A gettext replacement that works directly on .po files
+//  Copyright (C) 2009 Ingo Ruhnke <grumbel@gmx.de>
+//
+//  This program is free software; you can redistribute it and/or
+//  modify it under the terms of the GNU General Public License
+//  as published by the Free Software Foundation; either version 2
+//  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 General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with this program; if not, write to the Free Software
+//  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+#include <errno.h>
+#include <string.h>
+#include <iostream>
+#include <fstream>
+#include <stdexcept>
+
+#include "tinygettext/po_parser.hpp"
+#include "tinygettext/tinygettext.hpp"
+#include "tinygettext/log.hpp"
+
+void my_log_callback(const std::string& err)
+{
+  std::cerr << err;
+}
+
+int main(int argc, char** argv)
+{
+  if (argc < 2)
+  {
+    std::cout << argv[0] << " FILENAME..." << std::endl;
+  }
+  else
+  {
+    tinygettext::Log::set_log_info_callback(my_log_callback);
+    tinygettext::Log::set_log_warning_callback(my_log_callback);
+    tinygettext::Log::set_log_error_callback(my_log_callback);
+
+    for(int i = 1; i < argc; ++i)
+    {
+      std::ifstream in(argv[i]);
+      if (!in)
+      {
+        std::cerr << argv[0] << ": cannot access " << argv[i] << ": " << strerror(errno) << std::endl;
+      }
+      else
+      {
+        try 
+        {
+          tinygettext::Dictionary dict1;
+          tinygettext::POParser::parse(argv[i], in, dict1);
+
+          //tinygettext::Dictionary dict2;
+          //tinygettext::POFileReader::read(in, dict2);
+        }
+        catch(std::runtime_error& err)
+        {
+          std::cout << argv[i] << ": exception: " << err.what() << std::endl;
+        }
+      }
+    }
+  }  
+}
+
+/* EOF */
Index: libraries/source/tinygettext/test/test.sh
===================================================================
--- libraries/source/tinygettext/test/test.sh	(revision 0)
+++ libraries/source/tinygettext/test/test.sh	(working copy)
@@ -0,0 +1,8 @@
+#!/bin/sh
+
+./tinygettext_test translate po/fr.po  "invalid"
+./tinygettext_test directory po/ umlaut Deutsch
+./tinygettext_test directory po/ umlaut deutsch
+./tinygettext_test directory po/ umlaut de
+
+# EOF #

Property changes on: libraries/source/tinygettext/test/test.sh
___________________________________________________________________
Added: svn:executable
## -0,0 +1 ##
+*
\ No newline at end of property
Index: libraries/source/tinygettext/test/tinygettext_test.cpp
===================================================================
--- libraries/source/tinygettext/test/tinygettext_test.cpp	(revision 0)
+++ libraries/source/tinygettext/test/tinygettext_test.cpp	(working copy)
@@ -0,0 +1,204 @@
+//  TinyGetText
+//  Copyright (C) 2009 Ingo Ruhnke <grumbel@gmx.de>
+//
+//  This program is free software; you can redistribute it and/or
+//  modify it under the terms of the GNU General Public License
+//  as published by the Free Software Foundation; either version 2
+//  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 General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with this program; if not, write to the Free Software
+//  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+#include <iostream>
+#include <string.h>
+#include <fstream>
+#include <stdlib.h>
+#include <iostream>
+#include <stdexcept>
+#include "tinygettext/po_parser.hpp"
+#include "tinygettext/tinygettext.hpp"
+
+using namespace tinygettext;
+
+void print_msg(const std::string& msgid, const std::vector<std::string>& msgstrs)
+{
+  std::cout << "Msgid: " << msgid << std::endl;
+  for(std::vector<std::string>::const_iterator i = msgstrs.begin(); i != msgstrs.end(); ++i)
+    {
+      std::cout << *i << std::endl;
+    }
+}
+
+void print_msg_ctxt(const std::string& ctxt, const std::string& msgid, const std::vector<std::string>& msgstrs) 
+{
+  std::cout << "Msgctxt: " << ctxt << std::endl;
+  std::cout << "Msgid: " << msgid << std::endl;
+  for(std::vector<std::string>::const_iterator i = msgstrs.begin(); i != msgstrs.end(); ++i)
+    {
+      std::cout << *i << std::endl;
+    }
+}
+
+void print_usage(int /*argc*/, char** argv)
+{
+  std::cout << "Usage: " << argv[0] << " translate FILE MESSAGE" << std::endl;
+  std::cout << "       " << argv[0] << " translate FILE MESSAGE_S MESSAGE_P NUM" << std::endl;
+  std::cout << "       " << argv[0] << " directory DIRECTORY MESSAGE [LANG]" << std::endl;
+  std::cout << "       " << argv[0] << " language LANGUAGE" << std::endl;
+  std::cout << "       " << argv[0] << " language-dir DIR" << std::endl;
+  std::cout << "       " << argv[0] << " list-msgstrs FILE" << std::endl;
+}
+
+void read_dictionary(const std::string& filename, Dictionary& dict)
+{
+  std::ifstream in(filename.c_str());
+  
+  if (!in)
+    {
+      throw std::runtime_error("Couldn't open " + filename);
+    }
+  else
+    {
+      POParser::parse(filename, in, dict);
+      in.close();
+    }
+}
+
+int main(int argc, char** argv)
+{
+  try 
+  {
+    if (argc == 3 && strcmp(argv[1], "language-dir") == 0)
+    {
+      DictionaryManager dictionary_manager;
+      dictionary_manager.add_directory(argv[2]);
+      const std::set<Language>& languages = dictionary_manager.get_languages();
+      std::cout << "Number of languages: " << languages.size() << std::endl;
+      for (std::set<Language>::const_iterator i = languages.begin(); i != languages.end(); ++i)
+      {
+        const Language& language = *i;
+        std::cout << "Env:       " << language.str()           << std::endl
+                  << "Name:      " << language.get_name()      << std::endl
+                  << "Language:  " << language.get_language()  << std::endl
+                  << "Country:   " << language.get_country()   << std::endl
+                  << "Modifier:  " << language.get_modifier()  << std::endl
+                  << std::endl;
+      }
+    }
+    else if (argc == 3 && strcmp(argv[1], "language") == 0)
+    {
+      Language language = Language::from_name(argv[2]);
+
+      if (language)
+        std::cout << "Env:       " << language.str()           << std::endl
+                  << "Name:      " << language.get_name()      << std::endl
+                  << "Language:  " << language.get_language()  << std::endl
+                  << "Country:   " << language.get_country()   << std::endl
+                  << "Modifier:  " << language.get_modifier()  << std::endl;
+      else
+        std::cout << "not found" << std::endl;
+    }
+    else if (argc == 4 && strcmp(argv[1], "translate") == 0)
+    {
+      const char* filename = argv[2];
+      const char* message  = argv[3];
+
+      Dictionary dict;
+      read_dictionary(filename, dict);
+      std::cout << "TRANSLATION: \"\"\"" << dict.translate(message) << "\"\"\""<< std::endl;
+    }
+    else if (argc == 5 && strcmp(argv[1], "translate") == 0)
+    {
+      const char* filename = argv[2];
+      const char* context  = argv[3];
+      const char* message  = argv[4];
+
+      Dictionary dict;
+      read_dictionary(filename, dict);
+      std::cout << dict.translate_ctxt(context, message) << std::endl;
+    }
+    else if (argc == 6 && strcmp(argv[1], "translate") == 0)
+    {
+      const char* filename = argv[2];
+      const char* message_singular = argv[3];
+      const char* message_plural   = argv[4];
+      int num = atoi(argv[5]);
+
+      Dictionary dict;
+      read_dictionary(filename, dict);
+      std::cout << dict.translate_plural(message_singular, message_plural, num) << std::endl;
+    }
+    else if (argc == 7 && strcmp(argv[1], "translate") == 0)
+    {
+      const char* filename = argv[2];
+      const char* context  = argv[3];
+      const char* message_singular = argv[4];
+      const char* message_plural   = argv[5];
+      int num = atoi(argv[6]);
+
+      Dictionary dict;
+      read_dictionary(filename, dict);
+      std::cout << dict.translate_ctxt_plural(context, message_singular, message_plural, num) << std::endl;
+    }
+    else if ((argc == 4 || argc == 5) && strcmp(argv[1], "directory") == 0)
+    {
+      const char* directory = argv[2];
+      const char* message   = argv[3];
+      const char* language  = (argc == 5) ? argv[4] : NULL;
+          
+      DictionaryManager manager;
+      manager.add_directory(directory);
+          
+      if (language)
+      {
+        Language lang = Language::from_name(language);
+        if (lang)
+        {
+          manager.set_language(lang);
+        }
+        else
+        {
+          std::cout << "Unknown language: " << language << std::endl;
+          exit(EXIT_FAILURE);
+        }
+      }
+
+      std::cout << "Directory:   '" << directory << "'"  << std::endl;
+      std::cout << "Message:     '" << message << "'" << std::endl;
+      std::cout << "Language:    '" << manager.get_language().str() << "' (name: '" 
+                << manager.get_language().get_name() << "', language: '"
+                << manager.get_language().get_language() << "', country: '"
+                << manager.get_language().get_country() << "', modifier: '"
+                << manager.get_language().get_modifier() << "')"
+                << std::endl;
+      std::cout << "Translation: '" << manager.get_dictionary().translate(message) << "'" << std::endl;
+    }
+    else if ((argc == 3) && strcmp(argv[1], "list-msgstrs") == 0)
+    {
+      const char* filename = argv[2];
+
+      Dictionary dict;
+      read_dictionary(filename, dict);
+      dict.foreach(print_msg);
+      dict.foreach_ctxt(print_msg_ctxt);
+    }
+    else
+    {
+      print_usage(argc, argv);
+    }
+  }
+  catch(std::exception& err) 
+  {
+    std::cout << "Exception: " << err.what() << std::endl;
+  }
+  
+  return 0;
+}
+
+/* EOF */
Index: libraries/source/tinygettext/tinygettext/dictionary.cpp
===================================================================
--- libraries/source/tinygettext/tinygettext/dictionary.cpp	(revision 0)
+++ libraries/source/tinygettext/tinygettext/dictionary.cpp	(working copy)
@@ -0,0 +1,208 @@
+//  tinygettext - A gettext replacement that works directly on .po files
+//  Copyright (C) 2006 Ingo Ruhnke <grumbel@gmx.de>
+//
+//  This program is free software; you can redistribute it and/or
+//  modify it under the terms of the GNU General Public License
+//  as published by the Free Software Foundation; either version 2
+//  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 General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with this program; if not, write to the Free Software
+//  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+#include <assert.h>
+#include "log_stream.hpp"
+#include "dictionary.hpp"
+
+namespace tinygettext {
+
+Dictionary::Dictionary(const std::string& charset_) :
+  entries(),
+  ctxt_entries(),
+  charset(charset_),
+  plural_forms()
+{
+}
+
+Dictionary::~Dictionary()
+{
+}
+
+std::string
+Dictionary::get_charset() const
+{
+  return charset;
+}
+
+void
+Dictionary::set_plural_forms(const PluralForms& plural_forms_)
+{
+  plural_forms = plural_forms_;
+}
+
+PluralForms
+Dictionary::get_plural_forms() const
+{
+  return plural_forms;
+}
+
+std::string
+Dictionary::translate_plural(const std::string& msgid, const std::string& msgid_plural, int num)
+{
+  return translate_plural(entries, msgid, msgid_plural, num);
+}
+
+std::string
+Dictionary::translate_plural(const Entries& dict, const std::string& msgid, const std::string& msgid_plural, int count)
+{
+  Entries::const_iterator i = dict.find(msgid);
+  const std::vector<std::string>& msgstrs = i->second;
+
+  if (i != dict.end())
+  {
+    unsigned int n = 0;
+    n = plural_forms.get_plural(count);
+    assert(/*n >= 0 &&*/ n < msgstrs.size());
+
+    if (!msgstrs[n].empty())
+      return msgstrs[n];
+    else
+      if (count == 1) // default to english rules
+        return msgid;
+      else
+        return msgid_plural;
+  }
+  else
+  {
+    log_info << "Couldn't translate: " << msgid << std::endl;
+    log_info << "Candidates: " << std::endl;
+    for (i = dict.begin(); i != dict.end(); ++i)
+      log_info << "'" << i->first << "'" << std::endl;
+
+    if (count == 1) // default to english rules
+      return msgid;
+    else
+      return msgid_plural;
+  }
+}
+
+std::string
+Dictionary::translate(const std::string& msgid)
+{
+  return translate(entries, msgid);
+}
+
+std::string
+Dictionary::translate(const Entries& dict, const std::string& msgid)
+{
+  Entries::const_iterator i = dict.find(msgid);
+  if (i != dict.end() && !i->second.empty())
+  {
+    return i->second[0];
+  }
+  else
+  {
+    log_info << "Couldn't translate: " << msgid << std::endl;
+    return msgid;
+  } 
+}
+
+std::string
+Dictionary::translate_ctxt(const std::string& msgctxt, const std::string& msgid)
+{
+  CtxtEntries::iterator i = ctxt_entries.find(msgctxt);
+  if (i != ctxt_entries.end())
+  {
+    return translate(i->second, msgid);
+  }
+  else
+  {
+    log_info << "Couldn't translate: " << msgid << std::endl;
+    return msgid;
+  }
+}
+
+std::string
+Dictionary::translate_ctxt_plural(const std::string& msgctxt, 
+                                  const std::string& msgid, const std::string& msgidplural, int num)
+{
+  CtxtEntries::iterator i = ctxt_entries.find(msgctxt);
+  if (i != ctxt_entries.end())
+  {
+    return translate_plural(i->second, msgid, msgidplural, num);
+  }
+  else
+  {
+    log_info << "Couldn't translate: " << msgid << std::endl;
+    if (num != 1) // default to english
+      return msgidplural;
+    else
+      return msgid;
+  }
+}
+
+void
+Dictionary::add_translation(const std::string& msgid, const std::string& ,
+                            const std::vector<std::string>& msgstrs)
+{
+  // Do we need msgid2 for anything? its after all supplied to the
+  // translate call, so we just throw it away here
+  entries[msgid] = msgstrs;
+}
+
+void
+Dictionary::add_translation(const std::string& msgid, const std::string& msgstr)
+{
+  std::vector<std::string>& vec = entries[msgid];
+  if (vec.empty())
+  {
+    vec.push_back(msgstr);
+  }
+  else
+  {
+    log_warning << "collision in add_translation: '" 
+                << msgid << "' -> '" << msgstr << "' vs '" << vec[0] << "'" << std::endl;
+    vec[0] = msgstr;
+  }
+}
+
+void
+Dictionary::add_translation(const std::string& msgctxt, 
+                            const std::string& msgid, const std::string& msgid_plural,
+                            const std::vector<std::string>& msgstrs)
+{
+  std::vector<std::string>& vec = ctxt_entries[msgctxt][msgid];
+  if (vec.empty())
+  {
+    vec = msgstrs;
+  }
+  else
+  {
+    log_warning << "collision in add_translation(\"" << msgctxt << "\", \"" << msgid << "\", \"" << msgid_plural << "\")" << std::endl;
+    vec = msgstrs;
+  }
+}
+
+void
+Dictionary::add_translation(const std::string& msgctxt, const std::string& msgid, const std::string& msgstr)
+{
+  std::vector<std::string>& vec = ctxt_entries[msgctxt][msgid];
+  if (vec.empty())
+  {
+    vec.push_back(msgstr);
+  }
+  else
+  {
+    log_warning << "collision in add_translation(\"" << msgctxt << "\", \"" << msgid << "\")" << std::endl;
+    vec[0] = msgstr;
+  }
+}
+
+} // namespace tinygettext
+
+/* EOF */
Index: libraries/source/tinygettext/tinygettext/dictionary.hpp
===================================================================
--- libraries/source/tinygettext/tinygettext/dictionary.hpp	(revision 0)
+++ libraries/source/tinygettext/tinygettext/dictionary.hpp	(working copy)
@@ -0,0 +1,123 @@
+//  tinygettext - A gettext replacement that works directly on .po files
+//  Copyright (C) 2006 Ingo Ruhnke <grumbel@gmx.de>
+//
+//  This program is free software; you can redistribute it and/or
+//  modify it under the terms of the GNU General Public License
+//  as published by the Free Software Foundation; either version 2
+//  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 General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with this program; if not, write to the Free Software
+//  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+#ifndef HEADER_TINYGETTEXT_DICTIONARY_HPP
+#define HEADER_TINYGETTEXT_DICTIONARY_HPP
+
+#include <map>
+#include <vector>
+#include <string>
+#include "plural_forms.hpp"
+
+namespace tinygettext {
+
+/** A simple dictionary class that mimics gettext() behaviour. Each
+    Dictionary only works for a single language, for managing multiple
+    languages and .po files at once use the DictionaryManager. */
+class Dictionary
+{
+private:
+  typedef std::map<std::string, std::vector<std::string> > Entries;
+  Entries entries;
+
+  typedef std::map<std::string, Entries> CtxtEntries;
+  CtxtEntries ctxt_entries;
+
+  std::string charset;
+  PluralForms plural_forms;
+
+  std::string translate(const Entries& dict, const std::string& msgid);
+  std::string translate_plural(const Entries& dict, const std::string& msgid, const std::string& msgidplural, int num);
+
+public:
+  /** Constructs a dictionary converting to the specified \a charset (default UTF-8) */
+  Dictionary(const std::string& charset = "UTF-8");
+  ~Dictionary();
+
+  /** Return the charset used for this dictionary */
+  std::string get_charset() const;
+
+  void set_plural_forms(const PluralForms&);
+  PluralForms get_plural_forms() const;
+
+
+  /** Translate the string \a msgid. */
+  std::string translate(const std::string& msgid);
+
+  /** Translate the string \a msgid to its correct plural form, based
+      on the number of items given by \a num. \a msgid_plural is \a msgid in
+      plural form. */
+  std::string translate_plural(const std::string& msgid, const std::string& msgidplural, int num);
+
+  /** Translate the string \a msgid that is in context \a msgctx. A
+      context is a way to disambiguate msgids that contain the same
+      letters, but different meaning. For example "exit" might mean to
+      quit doing something or it might refer to a door that leads
+      outside (i.e. 'Ausgang' vs 'Beenden' in german) */
+  std::string translate_ctxt(const std::string& msgctxt, const std::string& msgid);
+
+  std::string translate_ctxt_plural(const std::string& msgctxt, const std::string& msgid, const std::string& msgidplural, int num);
+
+  /** Add a translation from \a msgid to \a msgstr to the dictionary,
+      where \a msgid is the singular form of the message, msgid_plural the
+      plural form and msgstrs a table of translations. The right
+      translation will be calculated based on the \a num argument to
+      translate(). */
+  void add_translation(const std::string& msgid, const std::string& msgid_plural,
+                       const std::vector<std::string>& msgstrs);
+  void add_translation(const std::string& msgctxt, 
+                       const std::string& msgid, const std::string& msgid_plural,
+                       const std::vector<std::string>& msgstrs);
+
+  /** Add a translation from \a msgid to \a msgstr to the
+      dictionary */
+  void add_translation(const std::string& msgid, const std::string& msgstr);
+  void add_translation(const std::string& msgctxt, const std::string& msgid, const std::string& msgstr);
+
+  /** Iterate over all messages, Func is of type:
+      void func(const std::string& msgid, const std::vector<std::string>& msgstrs) */
+  template<class Func>
+  Func foreach(Func func) 
+  {
+    for(Entries::iterator i = entries.begin(); i != entries.end(); ++i)
+    {
+      func(i->first, i->second);
+    }
+    return func;
+  }
+
+  /** Iterate over all messages with a context, Func is of type:
+      void func(const std::string& ctxt, const std::string& msgid, const std::vector<std::string>& msgstrs) */
+  template<class Func>
+  Func foreach_ctxt(Func func) 
+  {
+    for(CtxtEntries::iterator i = ctxt_entries.begin(); i != ctxt_entries.end(); ++i)
+    {
+      for(Entries::iterator j = i->second.begin(); j != i->second.end(); ++j)
+      {
+        func(i->first, j->first, j->second);
+      }
+    }
+    return func;
+  }
+};
+
+} // namespace tinygettext
+
+#endif
+
+/* EOF */
Index: libraries/source/tinygettext/tinygettext/dictionary_manager.cpp
===================================================================
--- libraries/source/tinygettext/tinygettext/dictionary_manager.cpp	(revision 0)
+++ libraries/source/tinygettext/tinygettext/dictionary_manager.cpp	(working copy)
@@ -0,0 +1,242 @@
+//  tinygettext - A gettext replacement that works directly on .po files
+//  Copyright (C) 2006 Ingo Ruhnke <grumbel@gmx.de>
+//
+//  This program is free software; you can redistribute it and/or
+//  modify it under the terms of the GNU General Public License
+//  as published by the Free Software Foundation; either version 2
+//  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 General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with this program; if not, write to the Free Software
+//  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+#include "dictionary_manager.hpp"
+
+#include <memory>
+#include <assert.h>
+#include <stdlib.h>
+#include <string.h>
+#include <fstream>
+#include <algorithm>
+
+#include "log_stream.hpp"
+#include "po_parser.hpp"
+#include "unix_file_system.hpp"
+
+namespace tinygettext {
+
+static bool has_suffix(const std::string& lhs, const std::string rhs)
+{
+  if (lhs.length() < rhs.length())
+    return false;
+  else
+    return lhs.compare(lhs.length() - rhs.length(), rhs.length(), rhs) == 0;
+}
+
+DictionaryManager::DictionaryManager(const std::string& charset_) :
+  dictionaries(),
+  search_path(),
+  charset(charset_),
+  use_fuzzy(true),
+  current_language(),
+  current_dict(0),
+  empty_dict(),
+  filesystem(new UnixFileSystem)
+{
+}
+
+DictionaryManager::~DictionaryManager()
+{
+  for(Dictionaries::iterator i = dictionaries.begin(); i != dictionaries.end(); ++i)
+  {
+    delete i->second;
+  }
+}
+
+void
+DictionaryManager::clear_cache()
+{
+  for(Dictionaries::iterator i = dictionaries.begin(); i != dictionaries.end(); ++i)
+  {
+    delete i->second;
+  }
+  dictionaries.clear();
+
+  current_dict = 0;
+}
+
+Dictionary&
+DictionaryManager::get_dictionary()
+{
+  if (current_dict)
+  {
+    return *current_dict; 
+  }
+  else
+  {
+    if (current_language)
+    {
+      current_dict = &get_dictionary(current_language);
+      return *current_dict;
+    }
+    else
+    {
+      return empty_dict;
+    }
+  }
+}
+
+Dictionary&
+DictionaryManager::get_dictionary(const Language& language)
+{
+  //log_debug << "Dictionary for language \"" << spec << "\" requested" << std::endl;
+  //log_debug << "...normalized as \"" << lang << "\"" << std::endl;
+  assert(language);
+
+  Dictionaries::iterator i = dictionaries.find(language); 
+  if (i != dictionaries.end())
+  {
+    return *i->second;
+  }
+  else // Dictionary for languages lang isn't loaded, so we load it
+  {
+    //log_debug << "get_dictionary: " << lang << std::endl;
+    Dictionary* dict = new Dictionary(charset);
+
+    dictionaries[language] = dict;
+
+    for (SearchPath::reverse_iterator p = search_path.rbegin(); p != search_path.rend(); ++p)
+    {
+      std::vector<std::string> files = filesystem->open_directory(*p);
+
+      std::string best_filename;
+      int best_score = 0;
+
+      for(std::vector<std::string>::iterator filename = files.begin(); filename != files.end(); filename++)
+      {
+        // check if filename matches requested language
+        if (has_suffix(*filename, ".po"))
+        { // ignore anything that isn't a .po file
+          Language po_language = Language::from_env(filename->substr(0, filename->size()-3));
+
+          if (!po_language)
+          {
+            log_warning << *filename << ": warning: ignoring, unknown language" << std::endl;
+          }
+          else
+          {
+            int score = Language::match(language, po_language);
+                          
+            if (score > best_score)
+            {
+              best_score = score;
+              best_filename = *filename;
+            }
+          }
+        }
+      }
+              
+      if (!best_filename.empty())
+      {
+        std::string pofile = *p + "/" + best_filename;
+        try 
+        {
+          std::auto_ptr<std::istream> in = filesystem->open_file(pofile);
+          if (!in.get())
+          {
+            log_error << "error: failure opening: " << pofile << std::endl;
+          }
+          else
+          {
+            POParser::parse(pofile, *in, *dict);
+          }
+        }
+        catch(std::exception& e) 
+        {
+          log_error << "error: failure parsing: " << pofile << std::endl;
+          log_error << e.what() << "" << std::endl;
+        }
+      }
+    }
+
+    return *dict;
+  }
+}
+
+std::set<Language>
+DictionaryManager::get_languages()
+{
+  std::set<Language> languages;
+
+  for (SearchPath::iterator p = search_path.begin(); p != search_path.end(); ++p)
+  {
+    std::vector<std::string> files = filesystem->open_directory(*p);
+
+    for(std::vector<std::string>::iterator file = files.begin(); file != files.end(); ++file)
+    {
+      if (has_suffix(*file, ".po")) 
+      {
+        languages.insert(Language::from_env(file->substr(0, file->size()-3)));
+      }
+    }
+  }
+  return languages;
+}
+
+void
+DictionaryManager::set_language(const Language& language)
+{
+  if (current_language != language)
+  {
+    current_language = language;
+    current_dict     = 0;
+  }
+}
+
+Language
+DictionaryManager::get_language() const
+{
+  return current_language;
+}
+
+void
+DictionaryManager::set_charset(const std::string& charset_)
+{
+  clear_cache(); // changing charset invalidates cache
+  charset = charset_;
+}
+
+void
+DictionaryManager::set_use_fuzzy(bool t)
+{
+  clear_cache();
+  use_fuzzy = t;
+}
+
+bool
+DictionaryManager::get_use_fuzzy() const
+{
+  return use_fuzzy;
+}
+
+void
+DictionaryManager::add_directory(const std::string& pathname)
+{
+  clear_cache(); // adding directories invalidates cache
+  search_path.push_back(pathname);
+}
+
+void
+DictionaryManager::set_filesystem(std::auto_ptr<FileSystem> filesystem_)
+{
+  filesystem = filesystem_;
+}
+
+} // namespace tinygettext
+
+/* EOF */
Index: libraries/source/tinygettext/tinygettext/dictionary_manager.hpp
===================================================================
--- libraries/source/tinygettext/tinygettext/dictionary_manager.hpp	(revision 0)
+++ libraries/source/tinygettext/tinygettext/dictionary_manager.hpp	(working copy)
@@ -0,0 +1,99 @@
+//  tinygettext - A gettext replacement that works directly on .po files
+//  Copyright (C) 2006 Ingo Ruhnke <grumbel@gmx.de>
+//
+//  This program is free software; you can redistribute it and/or
+//  modify it under the terms of the GNU General Public License
+//  as published by the Free Software Foundation; either version 2
+//  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 General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with this program; if not, write to the Free Software
+//  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+#ifndef HEADER_TINYGETTEXT_DICTIONARY_MANAGER_HPP
+#define HEADER_TINYGETTEXT_DICTIONARY_MANAGER_HPP
+
+#include <map>
+#include <set>
+#include <string>
+#include <vector>
+#include <memory>
+
+#include "dictionary.hpp"
+#include "language.hpp"
+
+namespace tinygettext {
+
+class FileSystem;
+
+/** Manager class for dictionaries, you give it a bunch of directories
+    with .po files and it will then automatically load the right file
+    on demand depending on which language was set. */
+class DictionaryManager
+{
+private:
+  typedef std::map<Language, Dictionary*> Dictionaries;
+  Dictionaries dictionaries;
+
+  typedef std::vector<std::string> SearchPath;
+  SearchPath search_path;
+
+  std::string charset;
+  bool        use_fuzzy;
+  
+  Language    current_language;
+  Dictionary* current_dict;
+
+  Dictionary  empty_dict;
+
+  std::auto_ptr<FileSystem> filesystem;
+
+  void clear_cache();
+
+public:
+  DictionaryManager(const std::string& charset_ = "UTF-8");
+  ~DictionaryManager();
+
+  /** Return the currently active dictionary, if none is set, an empty
+      dictionary is returned. */
+  Dictionary& get_dictionary();
+
+  /** Get dictionary for language */
+  Dictionary& get_dictionary(const Language& language);
+
+  /** Set a language based on a four? letter country code */
+  void set_language(const Language& language);
+
+  /** returns the (normalized) country code of the currently used language */
+  Language get_language() const;
+
+  void set_use_fuzzy(bool t);
+  bool get_use_fuzzy() const;
+
+  /** Set a charset that will be set on the returned dictionaries */
+  void set_charset(const std::string& charset);
+
+  /** Add a directory to the search path for dictionaries, earlier
+      added directories have higher priority then later added ones */
+  void add_directory(const std::string& pathname);
+
+  /** Return a set of the available languages in their country code */
+  std::set<Language> get_languages();
+
+  void set_filesystem(std::auto_ptr<FileSystem> filesystem);
+
+private:
+  DictionaryManager (const DictionaryManager&);
+  DictionaryManager& operator= (const DictionaryManager&);
+};
+
+} // namespace tinygettext
+
+#endif
+
+/* EOF */
Index: libraries/source/tinygettext/tinygettext/file_system.hpp
===================================================================
--- libraries/source/tinygettext/tinygettext/file_system.hpp	(revision 0)
+++ libraries/source/tinygettext/tinygettext/file_system.hpp	(working copy)
@@ -0,0 +1,42 @@
+//  tinygettext - A gettext replacement that works directly on .po files
+//  Copyright (C) 2009 Ingo Ruhnke <grumbel@gmx.de>
+//
+//  This program is free software; you can redistribute it and/or
+//  modify it under the terms of the GNU General Public License
+//  as published by the Free Software Foundation; either version 2
+//  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 General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with this program; if not, write to the Free Software
+//  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+#ifndef HEADER_TINYGETTEXT_FILE_SYSTEM_HPP
+#define HEADER_TINYGETTEXT_FILE_SYSTEM_HPP
+
+#include <vector>
+#include <memory>
+#include <iosfwd>
+#include <string>
+
+namespace tinygettext {
+
+class FileSystem 
+{
+public:
+  virtual ~FileSystem() {}
+
+  virtual std::vector<std::string>    open_directory(const std::string& pathname) =0;
+  virtual std::auto_ptr<std::istream> open_file(const std::string& filename)      =0;
+};
+
+} // namespace tinygettext
+
+#endif
+
+/* EOF */
+
Index: libraries/source/tinygettext/tinygettext/iconv.cpp
===================================================================
--- libraries/source/tinygettext/tinygettext/iconv.cpp	(revision 0)
+++ libraries/source/tinygettext/tinygettext/iconv.cpp	(working copy)
@@ -0,0 +1,148 @@
+//  tinygettext - A gettext replacement that works directly on .po files
+//  Copyright (C) 2009 Ingo Ruhnke <grumbel@gmx.de>
+//
+//  This program is free software; you can redistribute it and/or
+//  modify it under the terms of the GNU General Public License
+//  as published by the Free Software Foundation; either version 2
+//  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 General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with this program; if not, write to the Free Software
+//  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+#include <ctype.h>
+#include <assert.h>
+#include <sstream>
+#include <errno.h>
+#include <stdexcept>
+#include <string.h>
+#include <stdlib.h>
+
+#include "iconv.hpp"
+#include "log_stream.hpp"
+
+namespace tinygettext {
+
+#ifndef tinygettext_ICONV_CONST
+#  define tinygettext_ICONV_CONST 
+#endif
+
+IConv::IConv() 
+  : to_charset(),
+    from_charset(),
+    cd(0)
+{}
+ 
+IConv::IConv(const std::string& from_charset_, const std::string& to_charset_)
+  : to_charset(),
+    from_charset(),
+    cd(0)
+{
+  set_charsets(from_charset_, to_charset_);
+}
+ 
+IConv::~IConv()
+{
+  if (cd)
+    tinygettext_iconv_close(cd);
+}
+ 
+void
+IConv::set_charsets(const std::string& from_charset_, const std::string& to_charset_)
+{
+  if (cd)
+    tinygettext_iconv_close(cd);
+
+  from_charset = from_charset_;
+  to_charset   = to_charset_;
+
+  for(std::string::iterator i = to_charset.begin(); i != to_charset.end(); ++i)
+    *i = static_cast<char>(toupper(*i));
+
+  for(std::string::iterator i = from_charset.begin(); i != from_charset.end(); ++i)
+    *i = static_cast<char>(toupper(*i));
+
+  if (to_charset == from_charset)
+  {
+    cd = 0;
+  }
+  else
+  {
+    cd = tinygettext_iconv_open(to_charset.c_str(), from_charset.c_str());
+    if (cd == reinterpret_cast<tinygettext_iconv_t>(-1))
+    {
+      if(errno == EINVAL)
+      {
+        std::ostringstream str;
+        str << "IConv construction failed: conversion from '" << from_charset
+            << "' to '" << to_charset << "' not available";
+        throw std::runtime_error(str.str());
+      }
+      else
+      {
+        std::ostringstream str;
+        str << "IConv: construction failed: " << strerror(errno);
+        throw std::runtime_error(str.str());
+      }
+    }
+  }
+}
+
+/// Convert a string from encoding to another.
+std::string
+IConv::convert(const std::string& text)
+{
+  if (!cd)
+  {
+    return text;
+  }
+  else
+  {
+    size_t inbytesleft  = text.size();
+    size_t outbytesleft = 4*inbytesleft; // Worst case scenario: ASCII -> UTF-32?
+
+    // We try to avoid to much copying around, so we write directly into
+    // a std::string
+    tinygettext_ICONV_CONST char* inbuf = const_cast<char*>(&text[0]);
+    std::string result(outbytesleft, 'X');
+    char* outbuf = &result[0]; 
+  
+    // Try to convert the text.
+    size_t ret = tinygettext_iconv(cd, &inbuf, &inbytesleft, &outbuf, &outbytesleft);
+    if (ret == static_cast<size_t>(-1))
+    {
+      if (errno == EILSEQ || errno == EINVAL)
+      { // invalid multibyte sequence
+        tinygettext_iconv(cd, NULL, NULL, NULL, NULL); // reset state
+
+        // FIXME: Could try to skip the invalid byte and continue
+        log_error << "error: tinygettext:iconv: invalid multibyte sequence in:  \"" << text << "\"" << std::endl;
+      }
+      else if (errno == E2BIG)
+      { // output buffer to small
+        assert(!"tinygettext/iconv.cpp: E2BIG: This should never be reached");
+      }
+      else if (errno == EBADF)
+      {
+        assert(!"tinygettext/iconv.cpp: EBADF: This should never be reached");
+      }
+      else
+      {
+        assert(!"tinygettext/iconv.cpp: <unknown>: This should never be reached");
+      }
+    }
+
+    result.resize(4*text.size() - outbytesleft);
+
+    return result;
+  }
+}
+
+} // namespace tinygettext
+
+/* EOF */
Index: libraries/source/tinygettext/tinygettext/iconv.hpp
===================================================================
--- libraries/source/tinygettext/tinygettext/iconv.hpp	(revision 0)
+++ libraries/source/tinygettext/tinygettext/iconv.hpp	(working copy)
@@ -0,0 +1,71 @@
+//  tinygettext - A gettext replacement that works directly on .po files
+//  Copyright (C) 2006 Ingo Ruhnke <grumbel@gmx.de>
+//
+//  This program is free software: you can redistribute it and/or modify
+//  it under the terms of the GNU General Public License as published by
+//  the Free Software Foundation, either version 3 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 General Public License for more details.
+//  
+//  You should have received a copy of the GNU General Public License
+//  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+#ifndef HEADER_TINYGETTEXT_ICONV_HPP
+#define HEADER_TINYGETTEXT_ICONV_HPP
+
+#include <string>
+
+#ifdef HAVE_SDL
+#  include "SDL.h"
+
+#  define tinygettext_ICONV_CONST const
+#  define tinygettext_iconv_t     SDL_iconv_t
+#  define tinygettext_iconv       SDL_iconv
+#  define tinygettext_iconv_open  SDL_iconv_open
+#  define tinygettext_iconv_close SDL_iconv_close 
+#else
+#  include <iconv.h>
+
+#  ifdef HAVE_ICONV_CONST
+#    define tinygettext_ICONV_CONST ICONV_CONST
+#  else
+#    define tinygettext_ICONV_CONST 
+#  endif
+
+#  define tinygettext_iconv_t     iconv_t
+#  define tinygettext_iconv       iconv
+#  define tinygettext_iconv_open  iconv_open
+#  define tinygettext_iconv_close iconv_close 
+#endif
+
+namespace tinygettext {
+
+class IConv
+{
+private:
+  std::string to_charset;
+  std::string from_charset;
+  tinygettext_iconv_t cd;
+
+public:
+  IConv();
+  IConv(const std::string& fromcode, const std::string& tocode);
+  ~IConv();
+
+  void set_charsets(const std::string& fromcode, const std::string& tocode);
+  std::string convert(const std::string& text);
+
+private:
+  IConv (const IConv&);
+  IConv& operator= (const IConv&);
+};
+
+} // namespace tinygettext
+
+#endif
+
+/* EOF */
Index: libraries/source/tinygettext/tinygettext/language.cpp
===================================================================
--- libraries/source/tinygettext/tinygettext/language.cpp	(revision 0)
+++ libraries/source/tinygettext/tinygettext/language.cpp	(working copy)
@@ -0,0 +1,568 @@
+//  tinygettext - A gettext replacement that works directly on .po files
+//  Copyright (C) 2006 Ingo Ruhnke <grumbel@gmx.de>
+//
+//  This program is free software; you can redistribute it and/or
+//  modify it under the terms of the GNU General Public License
+//  as published by the Free Software Foundation; either version 2
+//  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 General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with this program; if not, write to the Free Software
+//  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+#include "language.hpp"
+
+#include <map>
+#include <assert.h>
+#include <vector>
+
+namespace tinygettext {
+
+struct LanguageSpec {
+  /** Language code: "de", "en", ... */
+  const char* language;
+
+  /** Country code: "BR", "DE", ..., can be 0 */
+  const char* country;
+
+  /** Modifier/Varint: "Latn", "ije", "latin"..., can be 0 */
+  const char* modifier;
+
+  /** Language name: "German", "English", "French", ... */
+  const char* name;
+};
+
+/** Language Definitions */
+//*{
+LanguageSpec languages[] = {
+  { "aa", 0,    0, "Afar"                        },
+  { "af", 0,    0, "Afrikaans"                   },
+  { "af", "ZA", 0, "Afrikaans (South Africa)"    },
+  { "am", 0,    0, "Amharic"                     },
+  { "ar", 0,    0, "Arabic"                      },
+  { "ar", "AR", 0, "Arabic (Argentina)"          },
+  { "ar", "OM", 0, "Arabic (Oman)"               },
+  { "ar", "SA", 0, "Arabic (Saudi Arabia)"       },
+  { "ar", "SY", 0, "Arabic (Syrian Arab Republic)" },
+  { "ar", "TN", 0, "Arabic (Tunisia)"            },
+  { "as", 0,    0, "Assamese"                    },
+  { "ast",0,    0, "Asturian"                    },
+  { "ay", 0,    0, "Aymara"                      },
+  { "az", 0,    0, "Azerbaijani"                 },
+  { "az", "IR", 0, "Azerbaijani (Iran)"          },
+  { "be", 0,    0, "Belarusian"                  },
+  { "be", 0, "latin", "Belarusian"               },
+  { "bg", 0,    0, "Bulgarian"                   },
+  { "bg", "BG", 0, "Bulgarian (Bulgaria)"        },
+  { "bn", 0,    0, "Bengali"                     },
+  { "bn", "BD", 0, "Bengali (Bangladesh)"        },
+  { "bn", "IN", 0, "Bengali (India)"             },
+  { "bo", 0,    0, "Tibetan"                     },
+  { "br", 0,    0, "Breton"                      },
+  { "bs", 0,    0, "Bosnian"                     },
+  { "bs", "BA", 0, "Bosnian (Bosnia/Herzegovina)"},
+  { "bs", "BS", 0, "Bosnian (Bahamas)"           },
+  { "ca", "ES", "valencia", "Catalan (valencia)" },
+  { "ca", "ES", 0, "Catalan (Spain)"             },
+  { "ca", 0,    "valencia", "Catalan (valencia)" },
+  { "ca", 0,    0, "Catalan"                     },
+  { "co", 0,    0, "Corsican"                    },
+  { "cs", 0,    0, "Czech"                       },
+  { "cs", "CZ", 0, "Czech (Czech Republic)"      },
+  { "cy", 0,    0, "Welsh"                       },
+  { "cy", "GB", 0, "Welsh (Great Britain)"       },
+  { "cz", 0,    0, "Unknown language"            },
+  { "da", 0,    0, "Danish"                      },
+  { "da", "DK", 0, "Danish (Denmark)"            },
+  { "de", 0,    0, "German"                      },
+  { "de", "AT", 0, "German (Austria)"            },
+  { "de", "CH", 0, "German (Switzerland)"        },
+  { "de", "DE", 0, "German (Germany)"            },
+  { "dk", 0,    0, "Unknown language"            },
+  { "dz", 0,    0, "Dzongkha"                    },
+  { "el", 0,    0, "Greek"                       },
+  { "el", "GR", 0, "Greek (Greece)"              },
+  { "en", 0,    0, "English"                     },
+  { "en", "AU", 0, "English (Australia)"         },
+  { "en", "CA", 0, "English (Canada)"            },
+  { "en", "GB", 0, "English (Great Britain)"     },
+  { "en", "US", 0, "English (United States)"     },
+  { "en", "ZA", 0, "English (South Africa)"      },
+  { "en", 0, "boldquot", "English"               },
+  { "en", 0, "quot", "English"                   },
+  { "en", "US", "piglatin", "English"            },
+  { "eo", 0,    0, "Esperanto"                   },
+  { "es", 0,    0, "Spanish"                     },
+  { "es", "AR", 0, "Spanish (Argentina)"         },
+  { "es", "CL", 0, "Spanish (Chile)"             },
+  { "es", "CO", 0, "Spanish (Colombia)"          },
+  { "es", "CR", 0, "Spanish (Costa Rica)"        },
+  { "es", "DO", 0, "Spanish (Dominican Republic)"},
+  { "es", "EC", 0, "Spanish (Ecuador)"           },
+  { "es", "ES", 0, "Spanish (Spain)"             },
+  { "es", "GT", 0, "Spanish (Guatemala)"         },
+  { "es", "HN", 0, "Spanish (Honduras)"          },
+  { "es", "LA", 0, "Spanish (Laos)"              },
+  { "es", "MX", 0, "Spanish (Mexico)"            },
+  { "es", "NI", 0, "Spanish (Nicaragua)"         },
+  { "es", "PA", 0, "Spanish (Panama)"            },
+  { "es", "PE", 0, "Spanish (Peru)"              },
+  { "es", "PR", 0, "Spanish (Puerto Rico)"       },
+  { "es", "SV", 0, "Spanish (El Salvador)"       },
+  { "es", "UY", 0, "Spanish (Uruguay)"           },
+  { "es", "VE", 0, "Spanish (Venezuela)"         },
+  { "et", 0,    0, "Estonian"                    },
+  { "et", "EE", 0, "Estonian (Estonia)"          },
+  { "et", "ET", 0, "Estonian (Ethiopia)"         },
+  { "eu", 0,    0, "Basque"                      },
+  { "eu", "ES", 0, "Basque (Spain)"              },
+  { "fa", 0,    0, "Persian"                     },
+  { "fa", "AF", 0, "Persian (Afghanistan)"       },
+  { "fa", "IR", 0, "Persian (Iran)"              },
+  { "fi", 0,    0, "Finnish"                     },
+  { "fi", "FI", 0, "Finnish (Finland)"           },
+  { "fo", 0,    0, "Faroese"                     },
+  { "fo", "FO", 0, "Faeroese (Faroe Islands)"    },
+  { "fr", 0,    0, "French"                      },
+  { "fr", "CA", 0, "French (Canada)"             },
+  { "fr", "CH", 0, "French (Switzerland)"        },
+  { "fr", "FR", 0, "French (France)"             },
+  { "fr", "LU", 0, "French (Luxembourg)"         },
+  { "fy", 0,    0, "Frisian"                     },
+  { "ga", 0,    0, "Irish"                       },
+  { "gd", 0,    0, "Gaelic Scots"                },
+  { "gl", 0,    0, "Galician"                    },
+  { "gl", "ES", 0, "Galician (Spain)"            },
+  { "gn", 0,    0, "Guarani"                     },
+  { "gu", 0,    0, "Gujarati"                    },
+  { "gv", 0,    0, "Manx"                        },
+  { "ha", 0,    0, "Hausa"                       },
+  { "he", 0,    0, "Hebrew"                      },
+  { "he", "IL", 0, "Hebrew (Israel)"             },
+  { "hi", 0,    0, "Hindi"                       },
+  { "hr", 0,    0, "Croatian"                    },
+  { "hr", "HR", 0, "Croatian (Croatia)"          },
+  { "hu", 0,    0, "Hungarian"                   },
+  { "hu", "HU", 0, "Hungarian (Hungary)"         },
+  { "hy", 0,    0, "Armenian"                    },
+  { "ia", 0,    0, "Interlingua"                 },
+  { "id", 0,    0, "Indonesian"                  },
+  { "id", "ID", 0, "Indonesian (Indonesia)"      },
+  { "is", 0,    0, "Icelandic"                   },
+  { "is", "IS", 0, "Icelandic (Iceland)"         },
+  { "it", 0,    0, "Italian"                     },
+  { "it", "CH", 0, "Italian (Switzerland)"       },
+  { "it", "IT", 0, "Italian (Italy)"             },
+  { "iu", 0,    0, "Inuktitut"                   },
+  { "ja", 0,    0, "Japanese"                    },
+  { "ja", "JP", 0, "Japanese (Japan)"            },
+  { "ka", 0,    0, "Georgian"                    },
+  { "kk", 0,    0, "Kazakh"                      },
+  { "kl", 0,    0, "Kalaallisut"                 },
+  { "km", 0,    0, "Khmer"                       },
+  { "km", "KH", 0, "Khmer (Cambodia)"            },
+  { "kn", 0,    0, "Kannada"                     },
+  { "ko", 0,    0, "Korean"                      },
+  { "ko", "KR", 0, "Korean (Korea)"              },
+  { "ku", 0,    0, "Kurdish"                     },
+  { "kw", 0,    0, "Cornish"                     },
+  { "ky", 0,    0, "Kirghiz"                     },
+  { "la", 0,    0, "Latin"                       },
+  { "lo", 0,    0, "Lao"                         },
+  { "lt", 0,    0, "Lithuanian"                  },
+  { "lt", "LT", 0, "Lithuanian (Lithuania)"      },
+  { "lv", 0,    0, "Latvian"                     },
+  { "lv", "LV", 0, "Latvian (Latvia)"            },
+  { "mg", 0,    0, "Malagasy"                    },
+  { "mi", 0,    0, "Maori"                       },
+  { "mk", 0,    0, "Macedonian"                  },
+  { "mk", "MK", 0, "Macedonian (Macedonia)"      },
+  { "ml", 0,    0, "Malayalam"                   },
+  { "mn", 0,    0, "Mongolian"                   },
+  { "mr", 0,    0, "Marathi"                     },
+  { "ms", 0,    0, "Malay"                       },
+  { "ms", "MY", 0, "Malay (Malaysia)"            },
+  { "mt", 0,    0, "Maltese"                     },
+  { "my", 0,    0, "Burmese"                     },
+  { "my", "MM", 0, "Burmese (Myanmar)"           },
+  { "nb", 0,    0, "Norwegian Bokmal"            },
+  { "nb", "NO", 0, "Norwegian Bokm�l (Norway)"   },
+  { "ne", 0,    0, "Nepali"                      },
+  { "nl", 0,    0, "Dutch"                       },
+  { "nl", "BE", 0, "Dutch (Belgium)"             },
+  { "nl", "NL", 0, "Dutch (Netherlands)"         },
+  { "nn", 0,    0, "Norwegian Nynorsk"           },
+  { "nn", "NO", 0, "Norwegian Nynorsk (Norway)"  },
+  { "no", 0,    0, "Norwegian"                   },
+  { "no", "NO", 0, "Norwegian (Norway)"          },
+  { "no", "NY", 0, "Norwegian (NY)"              },
+  { "nr", 0,    0, "Ndebele, South"              },
+  { "oc", 0,    0, "Occitan post 1500"           },
+  { "om", 0,    0, "Oromo"                       },
+  { "or", 0,    0, "Oriya"                       },
+  { "pa", 0,    0, "Punjabi"                     },
+  { "pl", 0,    0, "Polish"                      },
+  { "pl", "PL", 0, "Polish (Poland)"             },
+  { "ps", 0,    0, "Pashto"                      },
+  { "pt", 0,    0, "Portuguese"                  },
+  { "pt", "BR", 0, "Brazilian"                   },
+  { "pt", "PT", 0, "Portuguese (Portugal)"       },
+  { "qu", 0,    0, "Quechua"                     },
+  { "rm", 0,    0, "Rhaeto-Romance"              },
+  { "ro", 0,    0, "Romanian"                    },
+  { "ro", "RO", 0, "Romanian (Romania)"          },
+  { "ru", 0,    0, "Russian"                     },
+  { "ru", "RU", 0, "Russian (Russia"             },
+  { "rw", 0,    0, "Kinyarwanda"                 },
+  { "sa", 0,    0, "Sanskrit"                    },
+  { "sd", 0,    0, "Sindhi"                      },
+  { "se", 0,    0, "Sami"                        },
+  { "se", "NO", 0, "Sami (Norway)"               },
+  { "si", 0,    0, "Sinhalese"                   },
+  { "sk", 0,    0, "Slovak"                      },
+  { "sk", "SK", 0, "Slovak (Slovakia)"           },
+  { "sl", 0,    0, "Slovenian"                   },
+  { "sl", "SI", 0, "Slovenian (Slovenia)"        },
+  { "sl", "SL", 0, "Slovenian (Sierra Leone)"    },
+  { "sm", 0,    0, "Samoan"                      },
+  { "so", 0,    0, "Somali"                      },
+  { "sp", 0,    0, "Unknown language"            },
+  { "sq", 0,    0, "Albanian"                    },
+  { "sq", "AL", 0, "Albanian (Albania)"          },
+  { "sr", 0,    0, "Serbian"                     },
+  { "sr", "YU", 0, "Serbian (Yugoslavia)"        },
+  { "sr", 0,"ije", "Serbian"                     },
+  { "sr", 0, "latin", "Serbian"                  },
+  { "sr", 0, "Latn",  "Serbian"                  },
+  { "ss", 0,    0, "Swati"                       },
+  { "st", 0,    0, "Sotho"                       },
+  { "sv", 0,    0, "Swedish"                     },
+  { "sv", "SE", 0, "Swedish (Sweden)"            },
+  { "sv", "SV", 0, "Swedish (El Salvador)"       },
+  { "sw", 0,    0, "Swahili"                     },
+  { "ta", 0,    0, "Tamil"                       },
+  { "te", 0,    0, "Telugu"                      },
+  { "tg", 0,    0, "Tajik"                       },
+  { "th", 0,    0, "Thai"                        },
+  { "th", "TH", 0, "Thai (Thailand)"             },
+  { "ti", 0,    0, "Tigrinya"                    },
+  { "tk", 0,    0, "Turkmen"                     },
+  { "tl", 0,    0, "Tagalog"                     },
+  { "to", 0,    0, "Tonga"                       },
+  { "tr", 0,    0, "Turkish"                     },
+  { "tr", "TR", 0, "Turkish (Turkey)"            },
+  { "ts", 0,    0, "Tsonga"                      },
+  { "tt", 0,    0, "Tatar"                       },
+  { "ug", 0,    0, "Uighur"                      },
+  { "uk", 0,    0, "Ukrainian"                   },
+  { "uk", "UA", 0, "Ukrainian (Ukraine)"         },
+  { "ur", 0,    0, "Urdu"                        },
+  { "ur", "PK", 0, "Urdu (Pakistan)"             },
+  { "uz", 0,    0, "Uzbek"                       },
+  { "uz", 0, "cyrillic", "Uzbek"                 },
+  { "vi", 0,    0, "Vietnamese"                  },
+  { "vi", "VN", 0, "Vietnamese (Vietnam)"        },
+  { "wa", 0,    0, "Walloon"                     },
+  { "wo", 0,    0, "Wolof"                       },
+  { "xh", 0,    0, "Xhosa"                       },
+  { "yi", 0,    0, "Yiddish"                     },
+  { "yo", 0,    0, "Yoruba"                      },
+  { "zh", 0,    0, "Chinese"                     },
+  { "zh", "CN", 0, "Chinese (simplified)"        },
+  { "zh", "HK", 0, "Chinese (Hong Kong)"         },
+  { "zh", "TW", 0, "Chinese (traditional)"       },
+  { "zu", 0,    0, "Zulu"                        },
+  { NULL, 0,    0, NULL                          }
+};
+//*}
+
+std::string
+resolve_language_alias(const std::string& name)
+{
+  typedef std::map<std::string, std::string> Aliases;
+  static Aliases language_aliases;
+  if (language_aliases.empty())
+  {
+    // FIXME: Many of those are not useful for us, since we leave
+    // encoding to the app, not to the language, we could/should
+    // also match against all language names, not just aliases from
+    // locale.alias
+
+    // Aliases taken from /etc/locale.alias
+    language_aliases["bokmal"]           = "nb_NO.ISO-8859-1";
+    language_aliases["bokm�l"]           = "nb_NO.ISO-8859-1";
+    language_aliases["catalan"]          = "ca_ES.ISO-8859-1";
+    language_aliases["croatian"]         = "hr_HR.ISO-8859-2";
+    language_aliases["czech"]            = "cs_CZ.ISO-8859-2";
+    language_aliases["danish"]           = "da_DK.ISO-8859-1";
+    language_aliases["dansk"]            = "da_DK.ISO-8859-1";
+    language_aliases["deutsch"]          = "de_DE.ISO-8859-1";
+    language_aliases["dutch"]            = "nl_NL.ISO-8859-1";
+    language_aliases["eesti"]            = "et_EE.ISO-8859-1";
+    language_aliases["estonian"]         = "et_EE.ISO-8859-1";
+    language_aliases["finnish"]          = "fi_FI.ISO-8859-1";
+    language_aliases["fran�ais"]         = "fr_FR.ISO-8859-1";
+    language_aliases["french"]           = "fr_FR.ISO-8859-1";
+    language_aliases["galego"]           = "gl_ES.ISO-8859-1";
+    language_aliases["galician"]         = "gl_ES.ISO-8859-1";
+    language_aliases["german"]           = "de_DE.ISO-8859-1";
+    language_aliases["greek"]            = "el_GR.ISO-8859-7";
+    language_aliases["hebrew"]           = "he_IL.ISO-8859-8";
+    language_aliases["hrvatski"]         = "hr_HR.ISO-8859-2";
+    language_aliases["hungarian"]        = "hu_HU.ISO-8859-2";
+    language_aliases["icelandic"]        = "is_IS.ISO-8859-1";
+    language_aliases["italian"]          = "it_IT.ISO-8859-1";
+    language_aliases["japanese"]         = "ja_JP.eucJP";
+    language_aliases["japanese.euc"]     = "ja_JP.eucJP";
+    language_aliases["ja_JP"]            = "ja_JP.eucJP";
+    language_aliases["ja_JP.ujis"]       = "ja_JP.eucJP";
+    language_aliases["japanese.sjis"]    = "ja_JP.SJIS";
+    language_aliases["korean"]           = "ko_KR.eucKR";
+    language_aliases["korean.euc"]       = "ko_KR.eucKR";
+    language_aliases["ko_KR"]            = "ko_KR.eucKR";
+    language_aliases["lithuanian"]       = "lt_LT.ISO-8859-13";
+    language_aliases["no_NO"]            = "nb_NO.ISO-8859-1";
+    language_aliases["no_NO.ISO-8859-1"] = "nb_NO.ISO-8859-1";
+    language_aliases["norwegian"]        = "nb_NO.ISO-8859-1";
+    language_aliases["nynorsk"]          = "nn_NO.ISO-8859-1";
+    language_aliases["polish"]           = "pl_PL.ISO-8859-2";
+    language_aliases["portuguese"]       = "pt_PT.ISO-8859-1";
+    language_aliases["romanian"]         = "ro_RO.ISO-8859-2";
+    language_aliases["russian"]          = "ru_RU.ISO-8859-5";
+    language_aliases["slovak"]           = "sk_SK.ISO-8859-2";
+    language_aliases["slovene"]          = "sl_SI.ISO-8859-2";
+    language_aliases["slovenian"]        = "sl_SI.ISO-8859-2";
+    language_aliases["spanish"]          = "es_ES.ISO-8859-1";
+    language_aliases["swedish"]          = "sv_SE.ISO-8859-1";
+    language_aliases["thai"]             = "th_TH.TIS-620";
+    language_aliases["turkish"]          = "tr_TR.ISO-8859-9";
+  }
+
+  std::string name_lowercase;
+  name_lowercase.resize(name.size());
+  for(std::string::size_type i = 0; i < name.size(); ++i)
+    name_lowercase[i] = static_cast<char>(tolower(name[i]));
+
+  Aliases::iterator i = language_aliases.find(name_lowercase);
+  if (i != language_aliases.end()) 
+  {
+    return i->second;
+  }
+  else
+  {
+    return name;
+  }
+}
+
+Language
+Language::from_spec(const std::string& language, const std::string& country, const std::string& modifier)
+{
+  static std::map<std::string, std::vector<LanguageSpec*> > language_map;
+
+  if (language_map.empty())
+  { // Init language_map
+    for(int i = 0; languages[i].language != NULL; ++i)
+      language_map[languages[i].language].push_back(&languages[i]);
+  }
+  
+  std::map<std::string, std::vector<LanguageSpec*> >::iterator i = language_map.find(language);
+  if (i != language_map.end())
+  {
+    std::vector<LanguageSpec*>& lst = i->second;
+
+    LanguageSpec tmpspec;
+    tmpspec.language = language.c_str();
+    tmpspec.country  = country.c_str();
+    tmpspec.modifier = modifier.c_str();
+    Language tmplang(&tmpspec);
+      
+    LanguageSpec* best_match = 0;
+    int best_match_score = 0;
+    for(std::vector<LanguageSpec*>::iterator j = lst.begin(); j != lst.end(); ++j)
+    { // Search for the language that best matches the given spec, value country more then modifier
+      int score = Language::match(Language(*j), tmplang);
+
+      if (score > best_match_score)
+      {
+        best_match = *j;
+        best_match_score = score;
+      }
+    }
+    assert(best_match);
+    return Language(best_match);
+  }
+  else
+  {
+    return Language();
+  }
+}
+
+Language
+Language::from_name(const std::string& spec_str)
+{
+  return from_env(resolve_language_alias(spec_str));
+}
+
+Language
+Language::from_env(const std::string& env)
+{
+  // Split LANGUAGE_COUNTRY.CODESET@MODIFIER into parts
+  std::string::size_type ln = env.find('_');
+  std::string::size_type dt = env.find('.');
+  std::string::size_type at = env.find('@');
+
+  std::string language;
+  std::string country;
+  std::string codeset;
+  std::string modifier;
+
+  //std::cout << ln << " " << dt << " " << at << std::endl;
+
+  language = env.substr(0, std::min(std::min(ln, dt), at));
+
+  if (ln != std::string::npos && ln+1 < env.size()) // _
+  {
+    country = env.substr(ln+1, (std::min(dt, at) == std::string::npos) ? std::string::npos : std::min(dt, at) - (ln+1));
+  }
+
+  if (dt != std::string::npos && dt+1 < env.size()) // .
+  {
+    codeset = env.substr(dt+1, (at == std::string::npos) ? std::string::npos : (at - (dt+1)));
+  }
+
+  if (at != std::string::npos && at+1 < env.size()) // @
+  {
+    modifier = env.substr(at+1);
+  }
+
+  return from_spec(language, country, modifier);
+}
+
+Language::Language(LanguageSpec* language_spec_)
+  : language_spec(language_spec_)
+{
+}
+
+Language::Language()
+  : language_spec(0)
+{
+}
+
+int
+Language::match(const Language& lhs, const Language& rhs)
+{
+  if (lhs.get_language() != rhs.get_language())
+  {
+    return 0;
+  }
+  else
+  {
+    static int match_tbl[3][3] = {
+      // modifier match, wildchard, miss
+      { 9, 8, 5 }, // country match
+      { 7, 6, 3 }, // country wildcard
+      { 4, 2, 1 }, // country miss
+    };
+  
+    int c;
+    if (lhs.get_country() == rhs.get_country())
+      c = 0;
+    else if (lhs.get_country().empty() || rhs.get_country().empty())
+      c = 1;
+    else
+      c = 2;
+  
+    int m;
+    if (lhs.get_modifier() == rhs.get_modifier())
+      m = 0;
+    else if (lhs.get_modifier().empty() || rhs.get_modifier().empty())
+      m = 1;
+    else
+      m = 2;
+
+    return match_tbl[c][m];
+  }
+}
+
+std::string
+Language::get_language() const
+{
+  if (language_spec)
+    return language_spec->language;
+  else
+    return "";
+}
+
+std::string
+Language::get_country()  const
+{
+  if (language_spec && language_spec->country)
+    return language_spec->country;
+  else
+    return "";
+}
+
+std::string
+Language::get_modifier() const
+{
+  if (language_spec && language_spec->modifier)
+    return language_spec->modifier;
+  else
+    return "";
+}
+
+std::string
+Language::get_name()  const
+{
+  if (language_spec)
+    return language_spec->name;
+  else
+    return "";
+}
+
+std::string
+Language::str() const
+{
+  if (language_spec)
+  {
+    std::string var;
+    var += language_spec->language;
+    if (language_spec->country)
+    {
+      var += "_";
+      var += language_spec->country;
+    }
+
+    if (language_spec->modifier)
+    {
+      var += "@";
+      var += language_spec->modifier;
+    }
+    return var;
+  }
+  else
+  {
+    return "";
+  }
+}
+
+bool
+Language::operator==(const Language& rhs) const
+{
+  return language_spec == rhs.language_spec;
+}
+
+bool
+Language::operator!=(const Language& rhs) const
+{
+  return language_spec != rhs.language_spec;
+}
+
+} // namespace tinygettext
+
+/* EOF */
Index: libraries/source/tinygettext/tinygettext/language.hpp
===================================================================
--- libraries/source/tinygettext/tinygettext/language.hpp	(revision 0)
+++ libraries/source/tinygettext/tinygettext/language.hpp	(working copy)
@@ -0,0 +1,91 @@
+//  tinygettext - A gettext replacement that works directly on .po files
+//  Copyright (C) 2006 Ingo Ruhnke <grumbel@gmx.de>
+//
+//  This program is free software; you can redistribute it and/or
+//  modify it under the terms of the GNU General Public License
+//  as published by the Free Software Foundation; either version 2
+//  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 General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with this program; if not, write to the Free Software
+//  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+#ifndef HEADER_TINYGETTEXT_LANGUAGE_HPP
+#define HEADER_TINYGETTEXT_LANGUAGE_HPP
+
+#include <string>
+
+namespace tinygettext {
+
+struct LanguageSpec;
+
+/** Lightweight wrapper around LanguageSpec */
+class Language
+{
+private:
+  LanguageSpec* language_spec;
+
+  Language(LanguageSpec* language_spec);
+
+public:
+  /** Create a language from language and country code:
+      Example: Languge("de", "DE"); */
+  static Language from_spec(const std::string& language, 
+                            const std::string& country = std::string(), 
+                            const std::string& modifier = std::string());
+
+  /** Create a language from language and country code:
+      Example: Languge("deutsch"); 
+      Example: Languge("de_DE"); */
+  static Language from_name(const std::string& str);
+
+  /** Create a language from an environment variable style string (e.g de_DE.UTF-8@modifier) */
+  static Language from_env(const std::string& env);
+
+  /** Compares two Languages, returns 0 on missmatch and a score
+      between 1 and 9 on match, the higher the score the better the
+      match */
+  static int match(const Language& lhs, const Language& rhs);
+
+  /** Create an undefined Language object */
+  Language();
+  
+  operator bool() const { return language_spec; }
+
+  /** Returns the language code (i.e. de, en, fr) */
+  std::string get_language() const;
+
+  /** Returns the country code (i.e. DE, AT, US) */
+  std::string get_country()  const;
+
+  /** Returns the modifier of the language (i.e. latn or Latn for
+      Serbian with non-cyrilic characters) */
+  std::string get_modifier()  const;
+
+  /** Returns the human readable name of the Language */
+  std::string get_name() const;
+
+  /** Returns the Language as string in the form of an environment
+      variable: {language}_{country}@{modifier} */
+  std::string str() const;
+
+  bool operator==(const Language& rhs) const;
+  bool operator!=(const Language& rhs) const;
+
+  friend bool operator<(const Language& lhs, const Language& rhs);
+};
+
+inline bool operator<(const Language& lhs, const Language& rhs) {
+  return lhs.language_spec < rhs.language_spec;
+}
+
+} // namespace tinygettext
+
+#endif
+
+/* EOF */
Index: libraries/source/tinygettext/tinygettext/log.cpp
===================================================================
--- libraries/source/tinygettext/tinygettext/log.cpp	(revision 0)
+++ libraries/source/tinygettext/tinygettext/log.cpp	(working copy)
@@ -0,0 +1,70 @@
+//  tinygettext - A gettext replacement that works directly on .po files
+//  Copyright (C) 2009 Ingo Ruhnke <grumbel@gmx.de>
+//
+//  This program is free software; you can redistribute it and/or
+//  modify it under the terms of the GNU General Public License
+//  as published by the Free Software Foundation; either version 2
+//  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 General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with this program; if not, write to the Free Software
+//  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+#include <iostream>
+#include "log.hpp"
+
+namespace tinygettext {
+
+Log::log_callback_t Log::log_info_callback    = &Log::default_log_callback;
+Log::log_callback_t Log::log_warning_callback = &Log::default_log_callback;
+Log::log_callback_t Log::log_error_callback   = &Log::default_log_callback;
+
+void
+Log::default_log_callback(const std::string& str)
+{
+  std::cerr << "tinygettext: " << str;
+}
+
+void
+Log::set_log_info_callback(log_callback_t callback)
+{
+  log_info_callback = callback;
+}
+
+void
+Log::set_log_warning_callback(log_callback_t callback)
+{
+  log_warning_callback = callback;
+}
+
+void
+Log::set_log_error_callback(log_callback_t callback)
+{
+  log_error_callback = callback;
+}
+
+Log::Log(log_callback_t callback_) :
+  callback(callback_),
+  out()
+{
+}
+
+Log::~Log() 
+{
+  callback(out.str());
+}
+
+std::ostream&
+Log::get() 
+{
+  return out; 
+}
+
+} // namespace tinygettext
+
+/* EOF */
Index: libraries/source/tinygettext/tinygettext/log.hpp
===================================================================
--- libraries/source/tinygettext/tinygettext/log.hpp	(revision 0)
+++ libraries/source/tinygettext/tinygettext/log.hpp	(working copy)
@@ -0,0 +1,56 @@
+//  tinygettext - A gettext replacement that works directly on .po files
+//  Copyright (C) 2009 Ingo Ruhnke <grumbel@gmx.de>
+//
+//  This program is free software; you can redistribute it and/or
+//  modify it under the terms of the GNU General Public License
+//  as published by the Free Software Foundation; either version 2
+//  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 General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with this program; if not, write to the Free Software
+//  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+#ifndef HEADER_TINYGETTEXT_LOG_HPP
+#define HEADER_TINYGETTEXT_LOG_HPP
+
+#include <sstream>
+
+namespace tinygettext {
+
+class Log
+{
+public:
+  typedef void (*log_callback_t)(const std::string&);
+
+  static log_callback_t log_info_callback;
+  static log_callback_t log_warning_callback;
+  static log_callback_t log_error_callback;
+
+
+  static void default_log_callback(const std::string& str);
+
+  static void set_log_info_callback(log_callback_t callback);
+  static void set_log_warning_callback(log_callback_t callback);
+  static void set_log_error_callback(log_callback_t callback);
+
+private:
+  log_callback_t callback;
+  std::ostringstream out;
+
+public:
+  Log(log_callback_t callback);
+  ~Log();
+  
+  std::ostream& get();
+};
+
+} // namespace tinygettext
+
+#endif
+
+/* EOF */
Index: libraries/source/tinygettext/tinygettext/log_stream.hpp
===================================================================
--- libraries/source/tinygettext/tinygettext/log_stream.hpp	(revision 0)
+++ libraries/source/tinygettext/tinygettext/log_stream.hpp	(working copy)
@@ -0,0 +1,34 @@
+//  tinygettext - A gettext replacement that works directly on .po files
+//  Copyright (C) 2009 Ingo Ruhnke <grumbel@gmx.de>
+//
+//  This program is free software; you can redistribute it and/or
+//  modify it under the terms of the GNU General Public License
+//  as published by the Free Software Foundation; either version 2
+//  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 General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with this program; if not, write to the Free Software
+//  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+#ifndef HEADER_TINYGETTEXT_LOG_STREAM_HPP
+#define HEADER_TINYGETTEXT_LOG_STREAM_HPP
+
+#include "log.hpp"
+
+namespace tinygettext {
+
+// FIXME: very bad to have such things in the API
+#define log_error   if (!Log::log_error_callback);   else (Log(Log::log_error_callback)).get()
+#define log_warning if (!Log::log_warning_callback); else (Log(Log::log_warning_callback)).get()
+#define log_info    if (!Log::log_info_callback);    else (Log(Log::log_warning_callback)).get()
+
+} // namespace tinygettext
+
+#endif
+
+/* EOF */
Index: libraries/source/tinygettext/tinygettext/plural_forms.cpp
===================================================================
--- libraries/source/tinygettext/tinygettext/plural_forms.cpp	(revision 0)
+++ libraries/source/tinygettext/tinygettext/plural_forms.cpp	(working copy)
@@ -0,0 +1,89 @@
+//  tinygettext - A gettext replacement that works directly on .po files
+//  Copyright (C) 2006 Ingo Ruhnke <grumbel@gmx.de>
+//
+//  This program is free software; you can redistribute it and/or
+//  modify it under the terms of the GNU General Public License
+//  as published by the Free Software Foundation; either version 2
+//  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 General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with this program; if not, write to the Free Software
+//  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+#include "plural_forms.hpp"
+
+#include <map>
+
+namespace tinygettext {
+
+/** 
+ *  Plural functions are used to select a string that matches a given
+ *  count. \a n is the count and the return value is the string index
+ *  used in the .po file, for example:
+ *   
+ *   msgstr[0] = "You got %d error";
+ *   msgstr[1] = "You got %d errors";        
+ *          ^-- return value of plural function 
+ */
+unsigned int plural1(int )     { return 0; }
+unsigned int plural2_1(int n)  { return (n != 1); }
+unsigned int plural2_2(int n)  { return (n > 1); }
+unsigned int plural2_mk(int n) { return n==1 || n%10==1 ? 0 : 1; }
+unsigned int plural3_lv(int n) { return static_cast<unsigned int>(n%10==1 && n%100!=11 ? 0 : n != 0 ? 1 : 2); }
+unsigned int plural3_ga(int n) { return static_cast<unsigned int>(n==1 ? 0 : n==2 ? 1 : 2); }
+unsigned int plural3_lt(int n) { return static_cast<unsigned int>(n%10==1 && n%100!=11 ? 0 : n%10>=2 && (n%100<10 || n%100>=20) ? 1 : 2); }
+unsigned int plural3_1(int n)  { return static_cast<unsigned int>(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2); }
+unsigned int plural3_sk(int n) { return static_cast<unsigned int>( (n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2 ); }
+unsigned int plural3_pl(int n) { return static_cast<unsigned int>(n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2); }
+unsigned int plural3_sl(int n) { return static_cast<unsigned int>(n%100==1 ? 0 : n%100==2 ? 1 : n%100==3 || n%100==4 ? 2 : 3); }
+unsigned int plural4_ar(int n) { return static_cast<unsigned int>( n==1 ? 0 : n==2 ? 1 : n>=3 && n<=10 ? 2 : 3 ); }
+
+PluralForms
+PluralForms::from_string(const std::string& str)
+{
+  static std::map<std::string, struct PluralForms> plural_forms;
+    
+  if (plural_forms.empty())
+  {
+    // Note that the plural forms here shouldn't contain any spaces
+    plural_forms["Plural-Forms:nplurals=1;plural=0;"] = PluralForms(1, plural1);
+    plural_forms["Plural-Forms:nplurals=2;plural=(n!=1);"] = PluralForms(2, plural2_1);
+    plural_forms["Plural-Forms:nplurals=2;plural=n!=1;"] = PluralForms(2, plural2_1);
+    plural_forms["Plural-Forms:nplurals=2;plural=(n>1);"] = PluralForms(2, plural2_2);
+    plural_forms["Plural-Forms:nplurals=2;plural=n==1||n%10==1?0:1;"] = PluralForms(2, plural2_mk);
+    plural_forms["Plural-Forms:nplurals=3;plural=n%10==1&&n%100!=11?0:n!=0?1:2);"] = PluralForms(2, plural3_lv);
+    plural_forms["Plural-Forms:nplurals=3;plural=n==1?0:n==2?1:2;"] = PluralForms(3, plural3_ga);
+    plural_forms["Plural-Forms:nplurals=3;plural=(n%10==1&&n%100!=11?0:n%10>=2&&(n%100<10||n%100>=20)?1:2);"] = PluralForms(3, plural3_lt);
+    plural_forms["Plural-Forms:nplurals=3;plural=(n%10==1&&n%100!=11?0:n%10>=2&&n%10<=4&&(n%100<10||n%100>=20)?1:2);"] = PluralForms(3, plural3_1);
+    plural_forms["Plural-Forms:nplurals=3;plural=(n==1)?0:(n>=2&&n<=4)?1:2;"] = PluralForms(3, plural3_sk);
+    plural_forms["Plural-Forms:nplurals=3;plural=(n==1?0:n%10>=2&&n%10<=4&&(n%100<10||n%100>=20)?1:2);"] = PluralForms(3, plural3_pl);
+    plural_forms["Plural-Forms:nplurals=3;plural=(n%100==1?0:n%100==2?1:n%100==3||n%100==4?2:3);"] = PluralForms(3, plural3_sl);
+
+    plural_forms["Plural-Forms:nplurals=4;plural=n==1?0:n==2?1:n>=3&&n<=10?2:3;"]=PluralForms(4, plural4_ar);
+  }
+  
+  // Remove spaces from string before lookup
+  std::string space_less_str;
+  for(std::string::size_type i = 0; i < str.size(); ++i)
+    if (!isspace(str[i]))
+      space_less_str += str[i];
+  
+  std::map<std::string, struct PluralForms>::const_iterator it= plural_forms.find(space_less_str);
+  if (it != plural_forms.end())
+  {
+    return it->second;
+  }
+  else
+  {
+    return PluralForms();
+  }
+}
+
+} // namespace tinygettext
+
+/* EOF */
Index: libraries/source/tinygettext/tinygettext/plural_forms.hpp
===================================================================
--- libraries/source/tinygettext/tinygettext/plural_forms.hpp	(revision 0)
+++ libraries/source/tinygettext/tinygettext/plural_forms.hpp	(working copy)
@@ -0,0 +1,61 @@
+//  tinygettext - A gettext replacement that works directly on .po files
+//  Copyright (C) 2006 Ingo Ruhnke <grumbel@gmx.de>
+//
+//  This program is free software; you can redistribute it and/or
+//  modify it under the terms of the GNU General Public License
+//  as published by the Free Software Foundation; either version 2
+//  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 General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with this program; if not, write to the Free Software
+//  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+#ifndef HEADER_TINYGETTEXT_PLURAL_FORMS_HPP
+#define HEADER_TINYGETTEXT_PLURAL_FORMS_HPP
+
+#include <string>
+
+namespace tinygettext {
+
+typedef unsigned int (*PluralFunc)(int n);
+
+class PluralForms
+{
+private:
+  unsigned int nplural;
+  PluralFunc   plural;
+
+public:
+  static PluralForms from_string(const std::string& str);
+
+  PluralForms()
+    : nplural(0),
+      plural(0)
+  {}
+
+  PluralForms(unsigned int nplural_, PluralFunc plural_)
+    : nplural(nplural_), 
+      plural(plural_)
+  {}
+
+  unsigned int get_nplural() const { return nplural; }
+  unsigned int get_plural(int n) const { if (plural) return plural(n); else return 0; }
+
+  bool operator==(const PluralForms& other) { return nplural == other.nplural && plural == other.plural; }
+  bool operator!=(const PluralForms& other) { return !(*this == other); }
+
+  operator bool() const {
+    return plural;
+  }
+};
+
+} // namespace tinygettext
+
+#endif 
+
+/* EOF */
Index: libraries/source/tinygettext/tinygettext/po_parser.cpp
===================================================================
--- libraries/source/tinygettext/tinygettext/po_parser.cpp	(revision 0)
+++ libraries/source/tinygettext/tinygettext/po_parser.cpp	(working copy)
@@ -0,0 +1,496 @@
+//  tinygettext - A gettext replacement that works directly on .po files
+//  Copyright (C) 2009 Ingo Ruhnke <grumbel@gmx.de>
+//
+//  This program is free software; you can redistribute it and/or
+//  modify it under the terms of the GNU General Public License
+//  as published by the Free Software Foundation; either version 2
+//  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 General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with this program; if not, write to the Free Software
+//  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+#include "po_parser.hpp"
+
+#include <iostream>
+#include <ctype.h>
+#include <string>
+#include <istream>
+#include <string.h>
+#include <map>
+#include <stdlib.h>
+
+#include "language.hpp"
+#include "log_stream.hpp"
+#include "iconv.hpp"
+#include "dictionary.hpp"
+#include "plural_forms.hpp"
+
+namespace tinygettext {
+
+bool POParser::pedantic = true;
+
+void
+POParser::parse(const std::string& filename, std::istream& in, Dictionary& dict)
+{
+  POParser parser(filename, in, dict);
+  parser.parse();
+}
+
+class POParserError {};
+
+POParser::POParser(const std::string& filename_, std::istream& in_, Dictionary& dict_, bool use_fuzzy_) :
+  filename(filename_), 
+  in(in_), 
+  dict(dict_), 
+  use_fuzzy(use_fuzzy_),
+  running(false), 
+  eof(false), 
+  big5(false),
+  line_number(0), 
+  current_line(), 
+  conv()
+{
+}
+
+POParser::~POParser()
+{
+}
+
+void
+POParser::warning(const std::string& msg)
+{
+  log_warning << filename << ":" << line_number << ": warning: " << msg << ": " << current_line << std::endl;
+  //log_warning << "Line: " << current_line << std::endl;
+}
+
+void
+POParser::error(const std::string& msg)
+{
+  log_error << filename << ":" << line_number << ": error: " << msg  << ": " << current_line << std::endl;
+
+  // Try to recover from an error by searching for start of another entry
+  do
+    next_line();
+  while(!eof && !is_empty_line());
+
+  throw POParserError();
+}
+
+void
+POParser::next_line()
+{
+  line_number += 1;
+  if (!std::getline(in, current_line))
+    eof = true;
+}
+
+void
+POParser::get_string_line(std::ostringstream& out,std::string::size_type skip)
+{
+  if (skip+1 >= static_cast<std::string::size_type>(current_line.size()))
+    error("unexpected end of line");
+
+  if (current_line[skip] != '"')
+    error("expected start of string '\"'");
+  
+  std::string::size_type i;
+  for(i = skip+1; current_line[i] != '\"'; ++i)
+  {
+    if (big5 && static_cast<unsigned char>(current_line[i]) >= 0x81 && static_cast<unsigned char>(current_line[i]) <= 0xfe)
+    {
+      out << current_line[i];
+
+      i += 1;
+          
+      if (i >= current_line.size())
+        error("invalid big5 encoding");
+          
+      out << current_line[i];
+    }
+    else if (i >= current_line.size())
+    {
+      error("unexpected end of string");
+    }
+    else if (current_line[i] == '\\')
+    {
+      i += 1;
+
+      if (i >= current_line.size())
+        error("unexpected end of string in handling '\\'");
+
+      switch (current_line[i])
+      {
+        case 'a':  out << '\a'; break;
+        case 'b':  out << '\b'; break;
+        case 'v':  out << '\v'; break;
+        case 'n':  out << '\n'; break;
+        case 't':  out << '\t'; break;
+        case 'r':  out << '\r'; break;
+        case '"':  out << '"'; break;
+        case '\\': out << '\\'; break;
+        default: 
+          std::ostringstream err;
+          err << "unhandled escape '\\" << current_line[i] << "'";
+          warning(err.str());
+
+          out << current_line[i-1] << current_line[i];
+          break;
+      }
+    }
+    else
+    {
+      out << current_line[i];
+    }
+  }
+
+  // process trailing garbage in line and warn if there is any
+  for(i = i+1; i < current_line.size(); ++i)
+    if (!isspace(current_line[i]))
+    {
+      warning("unexpected garbage after string ignoren");
+      break;
+    }
+}
+
+std::string
+POParser::get_string(std::string::size_type skip)
+{
+  std::ostringstream out;
+
+  if (skip+1 >= static_cast<std::string::size_type>(current_line.size()))
+    error("unexpected end of line");
+
+  if (current_line[skip] == ' ' && current_line[skip+1] == '"')
+  {
+    get_string_line(out, skip+1);
+  }
+  else
+  {
+    if (pedantic)
+      warning("keyword and string must be seperated by a single space");
+
+    for(;;)
+    {
+      if (skip >= static_cast<std::string::size_type>(current_line.size()))
+        error("unexpected end of line");
+      else if (current_line[skip] == '\"')
+      {
+        get_string_line(out, skip);
+        break;
+      }
+      else if (!isspace(current_line[skip]))
+      {
+        error("string must start with '\"'");
+      }
+      else
+      {
+        // skip space
+      }
+
+      skip += 1;
+    }
+  }
+  
+next:
+  next_line();
+  for(std::string::size_type i = 0; i < current_line.size(); ++i)
+  {
+    if (current_line[i] == '"')
+    {
+      if (i == 1)
+        if (pedantic)
+          warning("leading whitespace before string");
+
+      get_string_line(out, i);
+      goto next;
+    }
+    else if (isspace(current_line[i]))
+    {
+      // skip
+    }
+    else
+    {
+      break;
+    }
+  }
+
+  return out.str();
+}
+
+static bool has_prefix(const std::string& lhs, const std::string rhs)
+{
+  if (lhs.length() < rhs.length())
+    return false;
+  else
+    return lhs.compare(0, rhs.length(), rhs) == 0;
+}
+
+void
+POParser::parse_header(const std::string& header)
+{
+  std::string from_charset;
+  std::string::size_type start = 0;
+  for(std::string::size_type i = 0; i < header.length(); ++i)
+  {
+    if (header[i] == '\n')
+    {
+      std::string line = header.substr(start, i - start);
+
+      if (has_prefix(line, "Content-Type:"))
+      {
+        // from_charset = line.substr(len);
+        std::string::size_type len = strlen("Content-Type: text/plain; charset=");
+        if (line.compare(0, len, "Content-Type: text/plain; charset=") == 0)
+        {
+          from_charset = line.substr(len);
+
+          for(std::string::iterator ch = from_charset.begin(); ch != from_charset.end(); ++ch)
+            *ch = static_cast<char>(toupper(*ch));
+        }
+        else
+        {
+          warning("malformed Content-Type header");
+        }
+      }
+      else if (has_prefix(line, "Plural-Forms:"))
+      {
+        PluralForms plural_forms = PluralForms::from_string(line);
+        if (!plural_forms)
+        {
+          warning("unknown Plural-Forms given");
+        }
+        else
+        {
+          if (!dict.get_plural_forms())
+          {
+            dict.set_plural_forms(plural_forms);
+          }
+          else
+          {
+            if (dict.get_plural_forms() != plural_forms)
+            {
+              warning("Plural-Forms missmatch between .po file and dictionary");
+            }
+          }
+        }
+      }
+      start = i+1;
+    }
+  }
+
+  if (from_charset.empty() || from_charset == "CHARSET")
+  {
+    warning("charset not specified for .po, fallback to utf-8");
+    from_charset = "UTF-8";
+  }
+  else if (from_charset == "BIG5")
+  {
+    big5 = true;
+  }
+
+  conv.set_charsets(from_charset, dict.get_charset());
+}
+
+bool
+POParser::is_empty_line()
+{
+  if (current_line.empty())
+  {
+    return true;
+  }
+  else if (current_line[0] == '#')
+  { // handle comments as empty lines
+    if (current_line.size() == 1 || (current_line.size() >= 2 && isspace(current_line[1])))
+      return true;
+    else
+      return false;
+  }
+  else
+  {
+    for(std::string::iterator i = current_line.begin(); i != current_line.end(); ++i)
+    {
+      if (!isspace(*i))
+        return false;
+    }
+  }
+  return true;
+}
+
+bool
+POParser::prefix(const char* prefix_str)
+{
+  return current_line.compare(0, strlen(prefix_str), prefix_str) == 0;
+}
+
+void
+POParser::parse()
+{
+  next_line();
+
+  // skip UTF-8 intro that some text editors produce
+  // see http://en.wikipedia.org/wiki/Byte-order_mark
+  if (current_line.size() >= 3 &&
+      current_line[0] == static_cast<char>(0xef) &&
+      current_line[1] == static_cast<char>(0xbb) &&
+      current_line[2] == static_cast<char>(0xbf))
+  {
+    current_line = current_line.substr(3);
+  }
+
+  // Parser structure
+  while(!eof)
+  {
+    try 
+    {
+      bool fuzzy =  false;
+      bool has_msgctxt = false;
+      std::string msgctxt;
+      std::string msgid;
+
+      while(prefix("#"))
+      {
+        if (current_line.size() >= 2 && current_line[1] == ',')
+        {
+          // FIXME: Rather simplistic hunt for fuzzy flag
+          if (current_line.find("fuzzy", 2) != std::string::npos)
+            fuzzy = true;
+        }
+
+        next_line();
+      }
+
+      if (!is_empty_line())
+      {
+        if (prefix("msgctxt"))
+        {
+          has_msgctxt = true;
+          msgctxt = get_string(7);
+        }
+
+        if (prefix("msgid"))
+          msgid = get_string(5);
+        else
+          error("expected 'msgid'");
+
+        if (prefix("msgid_plural"))
+        {
+          std::string msgid_plural = get_string(12);
+          std::vector<std::string> msgstr_num;
+	  bool saw_nonempty_msgstr = false;
+
+        next:
+          if (is_empty_line())
+          {
+            if (msgstr_num.empty())
+              error("expected 'msgstr[N] (0 <= N <= 9)'");
+          }
+          else if (prefix("msgstr[") &&
+                   current_line.size() > 8 && 
+                   isdigit(current_line[7]) && current_line[8] == ']')
+          {
+            std::string::size_type number = static_cast<std::string::size_type>(current_line[7] - '0');
+	    std::string msgstr = get_string(9);
+
+	    if(!msgstr.empty())
+	      saw_nonempty_msgstr = true;
+
+            if (number >= msgstr_num.size())
+              msgstr_num.resize(number+1);
+
+            msgstr_num[number] = conv.convert(msgstr);
+            goto next;
+          }
+          else 
+          {
+            error("expected 'msgstr[N]'");
+          }
+
+          if (!is_empty_line())
+            error("expected 'msgstr[N]' or empty line");
+
+	  if (saw_nonempty_msgstr)
+	  {
+	    if (use_fuzzy || !fuzzy)
+            {
+	      if (!dict.get_plural_forms())
+	      {
+		warning("msgstr[N] seen, but no Plural-Forms given");
+	      }
+	      else
+	      {
+		if (msgstr_num.size() != dict.get_plural_forms().get_nplural())
+		{
+		  warning("msgstr[N] count doesn't match Plural-Forms.nplural");
+		}
+	      }
+
+	      if (has_msgctxt)
+		dict.add_translation(msgctxt, msgid, msgid_plural, msgstr_num);
+	      else
+		dict.add_translation(msgid, msgid_plural, msgstr_num);
+	    }
+
+	    if (0)
+	    {
+	      std::cout << (fuzzy?"fuzzy":"not-fuzzy") << std::endl;
+	      std::cout << "msgid \"" << msgid << "\"" << std::endl;
+	      std::cout << "msgid_plural \"" << msgid_plural << "\"" << std::endl;
+	      for(std::vector<std::string>::size_type i = 0; i < msgstr_num.size(); ++i)
+		std::cout << "msgstr[" << i << "] \"" << conv.convert(msgstr_num[i]) << "\"" << std::endl;
+	      std::cout << std::endl;
+	    }
+	  }
+        }
+        else if (prefix("msgstr"))
+        {
+          std::string msgstr = get_string(6);
+
+          if (msgid.empty())
+          {
+            parse_header(msgstr);
+          }
+          else if(!msgstr.empty())
+          {
+            if (use_fuzzy || !fuzzy)
+            {
+              if (has_msgctxt)
+                dict.add_translation(msgctxt, msgid, conv.convert(msgstr));
+              else
+                dict.add_translation(msgid, conv.convert(msgstr));
+            }
+
+            if (0)
+            {
+              std::cout << (fuzzy?"fuzzy":"not-fuzzy") << std::endl;
+              std::cout << "msgid \"" << msgid << "\"" << std::endl;
+              std::cout << "msgstr \"" << conv.convert(msgstr) << "\"" << std::endl;
+              std::cout << std::endl;
+            }
+          }
+        }
+        else
+        {
+          error("expected 'msgstr' or 'msgid_plural'");
+        }
+      }
+      
+      if (!is_empty_line())
+        error("expected empty line");
+
+      next_line();
+    }
+    catch(POParserError&)
+    {          
+    }
+  }
+}
+
+} // namespace tinygettext
+
+/* EOF */
Index: libraries/source/tinygettext/tinygettext/po_parser.hpp
===================================================================
--- libraries/source/tinygettext/tinygettext/po_parser.hpp	(revision 0)
+++ libraries/source/tinygettext/tinygettext/po_parser.hpp	(working copy)
@@ -0,0 +1,75 @@
+//  tinygettext - A gettext replacement that works directly on .po files
+//  Copyright (C) 2009 Ingo Ruhnke <grumbel@gmx.de>
+//
+//  This program is free software; you can redistribute it and/or
+//  modify it under the terms of the GNU General Public License
+//  as published by the Free Software Foundation; either version 2
+//  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 General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with this program; if not, write to the Free Software
+//  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+#ifndef HEADER_TINYGETTEXT_PO_PARSER_HPP
+#define HEADER_TINYGETTEXT_PO_PARSER_HPP
+
+#include <iosfwd>
+
+#include "iconv.hpp"
+
+namespace tinygettext {
+
+class Dictionary;
+
+class POParser
+{
+private:
+  std::string filename;
+  std::istream& in;
+  Dictionary& dict;
+  bool  use_fuzzy;
+
+  bool running;
+  bool eof;
+  bool big5;
+
+  int line_number;
+  std::string current_line;
+
+  IConv conv;
+  
+  POParser(const std::string& filename, std::istream& in_, Dictionary& dict_, bool use_fuzzy = true);
+  ~POParser();
+
+  void parse_header(const std::string& header);
+  void parse();
+  void next_line();
+  std::string get_string(std::string::size_type skip);
+  void get_string_line(std::ostringstream& str,std::string::size_type skip);
+  bool is_empty_line();
+  bool prefix(const char* );
+  void error(const std::string& msg) __attribute__((__noreturn__));
+  void warning(const std::string& msg);
+
+public:
+  /** @param filename name of the istream, only used in error messages
+      @param in stream from which the PO file is read.
+      @param dict dictionary to which the strings are written */
+  static void parse(const std::string& filename, std::istream& in, Dictionary& dict);
+  static bool pedantic;
+
+private:
+  POParser (const POParser&);
+  POParser& operator= (const POParser&);
+};
+
+} // namespace tinygettext
+
+#endif
+
+/* EOF */
Index: libraries/source/tinygettext/tinygettext/tinygettext.cpp
===================================================================
--- libraries/source/tinygettext/tinygettext/tinygettext.cpp	(revision 0)
+++ libraries/source/tinygettext/tinygettext/tinygettext.cpp	(working copy)
@@ -0,0 +1,22 @@
+//  tinygettext - A gettext replacement that works directly on .po files
+//  Copyright (C) 2006 Ingo Ruhnke <grumbel@gmx.de>
+//
+//  This program is free software; you can redistribute it and/or
+//  modify it under the terms of the GNU General Public License
+//  as published by the Free Software Foundation; either version 2
+//  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 General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with this program; if not, write to the Free Software
+//  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+namespace tinygettext {
+
+} // namespace tinygettext
+
+/* EOF */
Index: libraries/source/tinygettext/tinygettext/tinygettext.hpp
===================================================================
--- libraries/source/tinygettext/tinygettext/tinygettext.hpp	(revision 0)
+++ libraries/source/tinygettext/tinygettext/tinygettext.hpp	(working copy)
@@ -0,0 +1,27 @@
+//  tinygettext - A gettext replacement that works directly on .po files
+//  Copyright (C) 2006 Ingo Ruhnke <grumbel@gmx.de>
+//
+//  This program is free software; you can redistribute it and/or
+//  modify it under the terms of the GNU General Public License
+//  as published by the Free Software Foundation; either version 2
+//  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 General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with this program; if not, write to the Free Software
+//  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+#ifndef HEADER_TINYGETTEXT_TINYGETTEXT_HPP
+#define HEADER_TINYGETTEXT_TINYGETTEXT_HPP
+
+#include "dictionary.hpp"
+#include "dictionary_manager.hpp"
+#include "language.hpp"
+
+#endif
+
+/* EOF */
Index: libraries/source/tinygettext/tinygettext/unix_file_system.cpp
===================================================================
--- libraries/source/tinygettext/tinygettext/unix_file_system.cpp	(revision 0)
+++ libraries/source/tinygettext/tinygettext/unix_file_system.cpp	(working copy)
@@ -0,0 +1,65 @@
+//  tinygettext - A gettext replacement that works directly on .po files
+//  Copyright (C) 2009 Ingo Ruhnke <grumbel@gmx.de>
+//
+//  This program is free software; you can redistribute it and/or
+//  modify it under the terms of the GNU General Public License
+//  as published by the Free Software Foundation; either version 2
+//  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 General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with this program; if not, write to the Free Software
+//  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+#include "unix_file_system.hpp"
+
+#include <sys/types.h>
+#include <fstream>
+#include <dirent.h>
+#include <stdlib.h>
+#include <dirent.h>
+#include <string.h>
+
+namespace tinygettext {
+
+UnixFileSystem::UnixFileSystem()
+{
+}
+
+std::vector<std::string>
+UnixFileSystem::open_directory(const std::string& pathname)
+{
+  DIR* dir = opendir(pathname.c_str());
+  if (!dir)
+  {
+    // FIXME: error handling
+    return std::vector<std::string>();
+  }
+  else
+  {
+    std::vector<std::string> files;
+
+    struct dirent* dp;
+    while((dp = readdir(dir)) != 0)
+    {
+      files.push_back(dp->d_name);
+    }
+    closedir(dir);
+
+    return files;
+  }
+}
+  
+std::auto_ptr<std::istream>
+UnixFileSystem::open_file(const std::string& filename)
+{
+  return std::auto_ptr<std::istream>(new std::ifstream(filename.c_str()));
+}
+
+} // namespace tinygettext
+
+/* EOF */
Index: libraries/source/tinygettext/tinygettext/unix_file_system.hpp
===================================================================
--- libraries/source/tinygettext/tinygettext/unix_file_system.hpp	(revision 0)
+++ libraries/source/tinygettext/tinygettext/unix_file_system.hpp	(working copy)
@@ -0,0 +1,38 @@
+//  tinygettext - A gettext replacement that works directly on .po files
+//  Copyright (C) 2009 Ingo Ruhnke <grumbel@gmx.de>
+//
+//  This program is free software; you can redistribute it and/or
+//  modify it under the terms of the GNU General Public License
+//  as published by the Free Software Foundation; either version 2
+//  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 General Public License for more details.
+//
+//  You should have received a copy of the GNU General Public License
+//  along with this program; if not, write to the Free Software
+//  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+
+#ifndef HEADER_TINYGETTEXT_UNIX_FILE_SYSTEM_HPP
+#define HEADER_TINYGETTEXT_UNIX_FILE_SYSTEM_HPP
+
+#include "file_system.hpp"
+
+namespace tinygettext {
+
+class UnixFileSystem : public FileSystem
+{
+public:
+  UnixFileSystem();
+
+  std::vector<std::string>    open_directory(const std::string& pathname);
+  std::auto_ptr<std::istream> open_file(const std::string& filename);
+};
+
+} // namespace tinygettext
+
+#endif
+
+/* EOF */
Index: libraries/source/tinygettext/tinygettext.pc.in
===================================================================
--- libraries/source/tinygettext/tinygettext.pc.in	(revision 0)
+++ libraries/source/tinygettext/tinygettext.pc.in	(working copy)
@@ -0,0 +1,16 @@
+# Unfortunately, since this project is built with cmake,
+# these variables can't properly be set.
+
+prefix=@CMAKE_INSTALL_PREFIX@
+exec_prefix=${prefix}
+libdir=${exec_prefix}/@LIB_SUBDIR@
+includedir=${prefix}/include
+
+Name: @PROJECT_NAME@
+Description: tiny, minimal gettext replacement
+Version: @VERSION@
+URL: http://tinygettext.googlecode.com/
+Requires:
+Libs: -L${libdir} -ltinygettext
+Libs.private:
+Cflags: -I${includedir}
Index: localization/gui.its
===================================================================
--- localization/gui.its	(revision 0)
+++ localization/gui.its	(working copy)
@@ -0,0 +1,15 @@
+<its:rules
+    xmlns:its="http://www.w3.org/2005/11/its"
+    version="1.0">
+  
+  <its:translateRule selector="//objects" translate="no" />
+  <its:translateRule selector="//page" translate="no" />
+  <its:translateRule selector="//setup" translate="no" />
+  <its:translateRule selector="//sprites" translate="no" />
+  <its:translateRule selector="//styles" translate="no" />
+  
+  <!-- Translate the value of these elements only. -->
+  <its:translateRule selector="//localizableAttribute" translate="yes" />
+  <its:translateRule selector="//localize" translate="yes" />
+  
+</its:rules>
Index: localization/update-pot.sh
===================================================================
--- localization/update-pot.sh	(revision 0)
+++ localization/update-pot.sh	(working copy)
@@ -0,0 +1,33 @@
+#!/bin/bash
+
+basedir="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
+
+# Go to the 0ad root, so that the paths in the POT file go from there.
+pushd $basedir/.. &> /dev/null
+
+for modFolderPath in binaries/data/mods/*
+do    
+    modName=$(basename $modFolderPath)
+    
+    if [ -d "$modFolderPath/gui" ]; then
+        
+        declare -a guiXmlFiles
+        for guiXmlFile in $(find $modFolderPath/gui -name "*.xml")
+        do
+            guiXmlFiles=("${guiXmlFiles[@]}" "$guiXmlFile")
+        done
+        
+        outputPot=$modFolderPath/po/${modName}.pot
+
+        itstool -o ${outputPot} -i $basedir/gui.its ${guiXmlFiles[@]}
+        unset guiXmlFiles
+
+        sed -e "s/\&amp;/\&/g" -i ${outputPot}
+    fi
+
+done
+
+popd &> /dev/null
+
+
+
Index: source/gui/CGUI.cpp
===================================================================
--- source/gui/CGUI.cpp	(revision 13483)
+++ source/gui/CGUI.cpp	(working copy)
@@ -45,8 +45,10 @@
 #include "graphics/TextRenderer.h"
 #include "lib/input.h"
 #include "lib/bits.h"
+#include "lib/localization.h"
 #include "lib/timer.h"
 #include "lib/sysdep/sysdep.h"
+#include <lib/utf8.h>
 #include "ps/CLogger.h"
 #include "ps/Filesystem.h"
 #include "ps/Font.h"
@@ -1178,15 +1180,20 @@
 	#define ELMT(x) int elmt_##x = pFile->GetElementID(#x)
 	#define ATTR(x) int attr_##x = pFile->GetAttributeID(#x)
 	ELMT(object);
-	ELMT(action);
+    ELMT(action);
 	ELMT(repeat);
+	ELMT(localizableAttribute);
+	ELMT(localize);
+	ELMT(attribute);
+	ELMT(keep);
 	ATTR(style);
 	ATTR(type);
 	ATTR(name);
 	ATTR(hotkey);
 	ATTR(z);
-	ATTR(on);
-	ATTR(file);
+    ATTR(on);
+    ATTR(file);
+    ATTR(id);
 
 	//
 	//	Read Style and set defaults
@@ -1327,8 +1334,27 @@
 				code = scriptfile.DecodeUTF8(); // assume it's UTF-8
 			}
 
-			// Read the inline code (concatenating to the file code, if both are specified)
-			code += CStr(child.GetText());
+			XMBElementList grandchildren = child.GetChildNodes();
+			if (grandchildren.Count > 0) // The <action> element contains <keep> and <localize> tags.
+			{
+				for (int i = 0; i < grandchildren.Count; ++i)
+				{
+					XMBElement grandchild = grandchildren.Item(i);
+					if (grandchild.GetNodeName() == elmt_localize)
+					{
+						code += Localization::getInstance().localize(grandchild.GetText());
+					}
+					else if (grandchild.GetNodeName() == elmt_keep)
+					{
+						code += grandchild.GetText();
+					}
+				}
+			}
+			else // It’s pure JavaScript code.
+			{
+				// Read the inline code (concatenating to the file code, if both are specified)
+				code += CStr(child.GetText());
+			}
 
 			CStr action = CStr(child.GetAttributes().GetNamedItem(attr_on));
 			object->RegisterScriptHandler(action.LowerCase(), code, this);
@@ -1337,6 +1363,53 @@
 		{
 			Xeromyces_ReadRepeat(child, pFile, object, Paths);
 		}
+		else if (element_name == elmt_localizableAttribute)
+		{
+			// This is an element in the form “<localizableAttribute id="attributeName">attributeValue</localizableAttribute>”.
+			CStr attributeName(child.GetAttributes().GetNamedItem(attr_id)); // Read the attribute name.
+			if (!attributeName.empty())
+			{
+				CStr value(child.GetText());
+				if (!value.empty())
+				{
+					CStr localizedValue(Localization::getInstance().localize(value));
+					object->SetSetting(attributeName, localizedValue.UnescapeBackslashes().FromUTF8(), true);
+				}
+			}
+			else // Ignore.
+			{
+				LOGERROR(L"GUI: ‘attribute’ XML element with empty ‘id’ XML attribute found. (object: %hs)", object->GetPresentableName().c_str());
+			}
+		}
+		else if (element_name == elmt_attribute)
+		{
+			// This is an element in the form “<attribute id="attributeName"><keep>Don’t translate this part
+			// </keep><localize>but translate this one.</localize></attribute>”.
+			CStr attributeName(child.GetAttributes().GetNamedItem(attr_id)); // Read the attribute name.
+			if (!attributeName.empty())
+			{
+				CStr localizedValue;
+
+				XMBElementList grandchildren = child.GetChildNodes();
+				for (int i = 0; i < grandchildren.Count; ++i)
+				{
+					XMBElement grandchild = grandchildren.Item(i);
+					if (grandchild.GetNodeName() == elmt_localize)
+					{
+						localizedValue += Localization::getInstance().localize(grandchild.GetText());
+					}
+					else if (grandchild.GetNodeName() == elmt_keep)
+					{
+						localizedValue += grandchild.GetText();
+					}
+				}
+				object->SetSetting(attributeName, localizedValue.UnescapeBackslashes().FromUTF8(), true);
+			}
+			else // Ignore.
+			{
+				LOGERROR(L"GUI: ‘attribute’ XML element with empty ‘id’ XML attribute found. (object: %hs)", object->GetPresentableName().c_str());
+			}
+		}
 		else
 		{
 			// Try making the object read the tag.
Index: source/lib/external_libraries/tinygettext.h
===================================================================
--- source/lib/external_libraries/tinygettext.h	(revision 0)
+++ source/lib/external_libraries/tinygettext.h	(working copy)
@@ -0,0 +1,33 @@
+/* Copyright (c) 2011 Wildfire Games
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ * 
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/*
+ * Bring in the TinyGettext header file.
+ */
+
+#ifndef INCLUDED_TINYGETTEXT
+#define INCLUDED_TINYGETTEXT
+
+#include <tinygettext/tinygettext.hpp>
+#include <tinygettext/po_parser.hpp>
+
+#endif	// INCLUDED_TINYGETTEXT
Index: source/lib/localization.cpp
===================================================================
--- source/lib/localization.cpp	(revision 0)
+++ source/lib/localization.cpp	(working copy)
@@ -0,0 +1,230 @@
+/* Copyright (c) 2013 Wildfire Games
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ * 
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include "lib/localization.h"
+
+#include <iostream>
+#include <boost/concept_check.hpp>
+
+#include "lib/file/file_system.h"
+#include "lib/utf8.h"
+
+#include "ps/CLogger.h"
+#include "ps/Filesystem.h"
+
+
+static std::vector<std::string> split(const std::string& target, char separator)
+{
+	std::vector<std::string> result;
+
+	std::string::size_type start = 0;
+	while (start != std::string::npos && start < target.size())
+	{
+		std::string::size_type i = target.find(separator, start);
+		if (i!=std::string::npos)
+		{
+			result.push_back(std::string(target,start, i-start));
+			start = i+1;
+		}
+		else // End of string reached.
+		{
+			result.push_back(std::string(target,start));
+			start = i;
+		}
+	}
+	return result;
+}
+
+Localization& Localization::getInstance()
+{
+	static Localization instance;
+	return instance;
+}
+
+Localization::Localization()
+: currentLocaleIsOriginalGameLocale(false) // determineCurrentLocale() takes care of setting this value to true.
+{
+	loadListOfAvailableLocales();
+	determineCurrentLocale();
+	loadDictionaryFromCurrentLocale();
+}
+
+Localization::~Localization()
+{
+	delete dictionary;
+}
+
+std::string Localization::localize(const std::string& sourceString)
+{
+	if (!currentLocaleIsOriginalGameLocale)
+	{
+		return dictionary->translate(sourceString);
+	}
+	else
+	{
+		return sourceString;
+	}
+}
+
+void Localization::determineCurrentLocale()
+{
+	// LC_ALL does not work, sscanf will then not always be able
+	// to scan for example: s=-1.1,-2.3,-3.3 correctly, which is
+	// used in driveline files.
+#if defined(WIN32) && !defined(__CYGWIN__)
+	// Windows does not have LC_MESSAGES
+	setlocale(LC_CTYPE,    "");
+#else
+	setlocale(LC_MESSAGES, "");
+#endif
+
+//     m_dictionary_manager.add_directory( file_manager->getTranslationDir());
+
+	const char *p_language = getenv("LANGUAGE");
+	std::string language;
+
+	if(strlen(p_language))
+	{
+		language = p_language;
+	}
+	else
+	{
+		const char *p_lang = getenv("LANG");
+
+		if (p_lang)
+		{
+			language = p_lang;
+		}
+		else
+		{
+#ifdef WIN32
+			char characters[1024];
+			GetLocaleInfoA(LOCALE_USER_DEFAULT, LOCALE_SISO639LANGNAME, characters, 1024);
+			if(characters[0])
+			{
+				language = characters;
+				GetLocaleInfoA(LOCALE_USER_DEFAULT, LOCALE_SISO3166CTRYNAME, characters, 1024);
+				if (characters[0])
+				{
+					language += std::string("_")+characters;
+				}
+			}
+#endif
+		}   // neither LANGUAGE nor LANG defined
+
+	}
+
+	if (language != "")
+	{
+		if (language.find(":") != std::string::npos)
+		{
+			std::vector<std::string> locales = split(language, ':');
+
+			for (unsigned int i = 0; i < locales.size(); ++i)
+			{
+				tinygettext::Language locale = tinygettext::Language::from_env(locales[i]);
+				if (locale)
+				{
+					for(std::set<tinygettext::Language>::iterator it = availableLocales.begin(); it != availableLocales.end(); ++it) {
+						if (it->get_language() == locale.get_language())
+						{
+							currentLocale = locale;
+							currentLocaleIsOriginalGameLocale = false;
+							return;
+						}
+					}
+				}
+			}
+		}
+		else
+		{
+			tinygettext::Language locale = tinygettext::Language::from_env(language);
+			for(std::set<tinygettext::Language>::iterator it = availableLocales.begin(); it != availableLocales.end(); ++it) {
+				if (it->get_language() == locale.get_language())
+				{
+					currentLocale = locale;
+					currentLocaleIsOriginalGameLocale = false;
+					return;
+				}
+			}
+		}
+	}
+
+	currentLocale = tinygettext::Language::from_env("en");
+	currentLocaleIsOriginalGameLocale = true;
+}
+
+void Localization::loadDictionaryFromCurrentLocale()
+{
+	if (!currentLocaleIsOriginalGameLocale)
+	{
+		delete dictionary;
+		dictionary = new tinygettext::Dictionary();
+
+		VfsPaths filenames;
+		if (vfs::GetPathnames(g_VFS, L"po/", (wstring_from_utf8(currentLocale.get_language()) + L".*.po").c_str(), filenames) < 0)
+			return;
+
+		for (VfsPaths::iterator it = filenames.begin(); it != filenames.end(); ++it)
+		{
+			VfsPath filename = *it;
+			CVFSFile file;
+			file.Load(g_VFS, filename);
+			std::string content = file.DecodeUTF8();
+			readPoIntoDictionary(content, dictionary);
+		}
+	}
+}
+
+void Localization::loadListOfAvailableLocales()
+{
+	availableLocales.clear();
+	availableLocales.insert(tinygettext::Language::from_env("en")); // Always available.
+
+	VfsPaths filenames;
+	if (vfs::GetPathnames(g_VFS, L"po/", L"*.po", filenames) < 0)
+		return;
+
+	for (VfsPaths::iterator it = filenames.begin(); it != filenames.end(); ++it)
+	{
+		// Note: PO files follow this naming convention: “po/<language code>.<mod name>.po”. For example: “po/gl.public.po”.
+		VfsPath filepath = *it;
+		std::string filename = utf8_from_wstring(filepath.string()).substr(3);
+		std::size_t lengthToFirstDot = filename.find('.');
+		std::string localeCode = filename.substr(0, lengthToFirstDot);
+		tinygettext::Language locale = tinygettext::Language::from_env(localeCode);
+		availableLocales.insert(locale);
+	}
+}
+
+void Localization::readPoIntoDictionary(const std::string& poContent, tinygettext::Dictionary* dictionary)
+{
+	try
+	{
+		std::istringstream inputStream(poContent);
+		tinygettext::POParser::parse("virtual PO file", inputStream, *dictionary);
+	}
+	catch(std::exception& e)
+	{
+		LOGERROR(L"[Localization] Exception while reading virtual PO file");
+	}
+}
\ No newline at end of file
Index: source/lib/localization.h
===================================================================
--- source/lib/localization.h	(revision 0)
+++ source/lib/localization.h	(working copy)
@@ -0,0 +1,68 @@
+/* Copyright (c) 2013 Wildfire Games
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ * 
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef LOCALIZATION_H
+#define LOCALIZATION_H
+
+#include <string>
+#include <set>
+
+#include "lib/external_libraries/tinygettext.h"
+
+#include "lib/os_path.h"
+
+class Localization
+{
+public:
+
+	static Localization& getInstance();
+
+	Localization();
+	Localization(Localization const&); // Don’t implement.
+	void operator=(Localization const&); // Don’t implement.
+	~Localization();
+
+	std::string localize(const std::string& sourceString);
+
+// 	bool               isRTLLanguage() const;
+
+// 	std::string        getCurrentLanguageName();
+
+private:
+	tinygettext::Dictionary* dictionary;
+	bool isRtlLanguage;
+	tinygettext::Language currentLocale;
+	std::set<tinygettext::Language> availableLocales;
+	bool currentLocaleIsOriginalGameLocale;
+
+
+	void determineCurrentLocale();
+	void loadDictionaryFromCurrentLocale();
+	void loadListOfAvailableLocales();
+
+	void readPoIntoDictionary(const std::string& poContent, tinygettext::Dictionary* dictionary);
+};
+
+
+extern Localization* localization;
+
+#endif // LOCALIZATION_H
