add static import of tinygettext
authorChristoph Sommer <mail@christoph-sommer.de>
Sat, 21 Jan 2012 10:00:24 +0000 (11:00 +0100)
committerChristoph Sommer <mail@christoph-sommer.de>
Sat, 21 Jan 2012 10:09:13 +0000 (11:09 +0100)
39 files changed:
external/tinygettext/CMakeLists.txt [new file with mode: 0644]
external/tinygettext/FindICONV.cmake [new file with mode: 0644]
external/tinygettext/NEWS [new file with mode: 0644]
external/tinygettext/README [new file with mode: 0644]
external/tinygettext/SConstruct [new file with mode: 0644]
external/tinygettext/TODO [new file with mode: 0644]
external/tinygettext/test/broken.po [new file with mode: 0644]
external/tinygettext/test/game/de.po [new file with mode: 0644]
external/tinygettext/test/helloworld.cpp [new file with mode: 0644]
external/tinygettext/test/helloworld/de.po [new file with mode: 0644]
external/tinygettext/test/helloworld/helloworld.pot [new file with mode: 0644]
external/tinygettext/test/level/de.po [new file with mode: 0644]
external/tinygettext/test/po/de.po [new file with mode: 0644]
external/tinygettext/test/po/de_AT.po [new file with mode: 0644]
external/tinygettext/test/po/fr.po [new file with mode: 0644]
external/tinygettext/test/po_parser_test.cpp [new file with mode: 0644]
external/tinygettext/test/test.sh [new file with mode: 0755]
external/tinygettext/test/tinygettext_test.cpp [new file with mode: 0644]
external/tinygettext/tinygettext.pc.in [new file with mode: 0644]
external/tinygettext/tinygettext/dictionary.cpp [new file with mode: 0644]
external/tinygettext/tinygettext/dictionary.hpp [new file with mode: 0644]
external/tinygettext/tinygettext/dictionary_manager.cpp [new file with mode: 0644]
external/tinygettext/tinygettext/dictionary_manager.hpp [new file with mode: 0644]
external/tinygettext/tinygettext/file_system.hpp [new file with mode: 0644]
external/tinygettext/tinygettext/iconv.cpp [new file with mode: 0644]
external/tinygettext/tinygettext/iconv.hpp [new file with mode: 0644]
external/tinygettext/tinygettext/language.cpp [new file with mode: 0644]
external/tinygettext/tinygettext/language.hpp [new file with mode: 0644]
external/tinygettext/tinygettext/log.cpp [new file with mode: 0644]
external/tinygettext/tinygettext/log.hpp [new file with mode: 0644]
external/tinygettext/tinygettext/log_stream.hpp [new file with mode: 0644]
external/tinygettext/tinygettext/plural_forms.cpp [new file with mode: 0644]
external/tinygettext/tinygettext/plural_forms.hpp [new file with mode: 0644]
external/tinygettext/tinygettext/po_parser.cpp [new file with mode: 0644]
external/tinygettext/tinygettext/po_parser.hpp [new file with mode: 0644]
external/tinygettext/tinygettext/tinygettext.cpp [new file with mode: 0644]
external/tinygettext/tinygettext/tinygettext.hpp [new file with mode: 0644]
external/tinygettext/tinygettext/unix_file_system.cpp [new file with mode: 0644]
external/tinygettext/tinygettext/unix_file_system.hpp [new file with mode: 0644]

diff --git a/external/tinygettext/CMakeLists.txt b/external/tinygettext/CMakeLists.txt
new file mode 100644 (file)
index 0000000..6c1d78b
--- /dev/null
@@ -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)
diff --git a/external/tinygettext/FindICONV.cmake b/external/tinygettext/FindICONV.cmake
new file mode 100644 (file)
index 0000000..0ac82b7
--- /dev/null
@@ -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)
diff --git a/external/tinygettext/NEWS b/external/tinygettext/NEWS
new file mode 100644 (file)
index 0000000..fcf6ef6
--- /dev/null
@@ -0,0 +1,6 @@
+tinygettext 0.0.1 - (??. Feb 2009)
+==================================
+
+* initial release
+
+# EOF #
diff --git a/external/tinygettext/README b/external/tinygettext/README
new file mode 100644 (file)
index 0000000..0eeabe9
--- /dev/null
@@ -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 #
diff --git a/external/tinygettext/SConstruct b/external/tinygettext/SConstruct
new file mode 100644 (file)
index 0000000..92613fd
--- /dev/null
@@ -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.StaticLibrary('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 #
diff --git a/external/tinygettext/TODO b/external/tinygettext/TODO
new file mode 100644 (file)
index 0000000..29daf3f
--- /dev/null
@@ -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)
+
+\f
+Random Unimportant Stuff
+========================
+
+* a hashmap instead of std::map might be a good idea
+
+* support for .gmo files would be cool
+\f
+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
+\f
+# EOF #
diff --git a/external/tinygettext/test/broken.po b/external/tinygettext/test/broken.po
new file mode 100644 (file)
index 0000000..c841a73
--- /dev/null
@@ -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"
diff --git a/external/tinygettext/test/game/de.po b/external/tinygettext/test/game/de.po
new file mode 100644 (file)
index 0000000..a92db3b
--- /dev/null
@@ -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"
+
diff --git a/external/tinygettext/test/helloworld.cpp b/external/tinygettext/test/helloworld.cpp
new file mode 100644 (file)
index 0000000..071ab96
--- /dev/null
@@ -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 */
diff --git a/external/tinygettext/test/helloworld/de.po b/external/tinygettext/test/helloworld/de.po
new file mode 100644 (file)
index 0000000..048acc6
--- /dev/null
@@ -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"
diff --git a/external/tinygettext/test/helloworld/helloworld.pot b/external/tinygettext/test/helloworld/helloworld.pot
new file mode 100644 (file)
index 0000000..a9174f8
--- /dev/null
@@ -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] ""
diff --git a/external/tinygettext/test/level/de.po b/external/tinygettext/test/level/de.po
new file mode 100644 (file)
index 0000000..69e0206
--- /dev/null
@@ -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"
+
diff --git a/external/tinygettext/test/po/de.po b/external/tinygettext/test/po/de.po
new file mode 100644 (file)
index 0000000..e863f81
--- /dev/null
@@ -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 ""
diff --git a/external/tinygettext/test/po/de_AT.po b/external/tinygettext/test/po/de_AT.po
new file mode 100644 (file)
index 0000000..f4c3d81
--- /dev/null
@@ -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] ""
diff --git a/external/tinygettext/test/po/fr.po b/external/tinygettext/test/po/fr.po
new file mode 100644 (file)
index 0000000..0670f48
--- /dev/null
@@ -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"
+
diff --git a/external/tinygettext/test/po_parser_test.cpp b/external/tinygettext/test/po_parser_test.cpp
new file mode 100644 (file)
index 0000000..e8f0ffb
--- /dev/null
@@ -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 */
diff --git a/external/tinygettext/test/test.sh b/external/tinygettext/test/test.sh
new file mode 100755 (executable)
index 0000000..a7b7789
--- /dev/null
@@ -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 #
diff --git a/external/tinygettext/test/tinygettext_test.cpp b/external/tinygettext/test/tinygettext_test.cpp
new file mode 100644 (file)
index 0000000..c0edb52
--- /dev/null
@@ -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 */
diff --git a/external/tinygettext/tinygettext.pc.in b/external/tinygettext/tinygettext.pc.in
new file mode 100644 (file)
index 0000000..ef82a93
--- /dev/null
@@ -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}
diff --git a/external/tinygettext/tinygettext/dictionary.cpp b/external/tinygettext/tinygettext/dictionary.cpp
new file mode 100644 (file)
index 0000000..9765d75
--- /dev/null
@@ -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 {
+\f
+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;
+  }
+}
+\f
+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;
+  }
+}
+\f
+} // namespace tinygettext
+
+/* EOF */
diff --git a/external/tinygettext/tinygettext/dictionary.hpp b/external/tinygettext/tinygettext/dictionary.hpp
new file mode 100644 (file)
index 0000000..743e075
--- /dev/null
@@ -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 */
diff --git a/external/tinygettext/tinygettext/dictionary_manager.cpp b/external/tinygettext/tinygettext/dictionary_manager.cpp
new file mode 100644 (file)
index 0000000..f923470
--- /dev/null
@@ -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 */
diff --git a/external/tinygettext/tinygettext/dictionary_manager.hpp b/external/tinygettext/tinygettext/dictionary_manager.hpp
new file mode 100644 (file)
index 0000000..7c3d7f3
--- /dev/null
@@ -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 */
diff --git a/external/tinygettext/tinygettext/file_system.hpp b/external/tinygettext/tinygettext/file_system.hpp
new file mode 100644 (file)
index 0000000..af47aaf
--- /dev/null
@@ -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 */
+
diff --git a/external/tinygettext/tinygettext/iconv.cpp b/external/tinygettext/tinygettext/iconv.cpp
new file mode 100644 (file)
index 0000000..c0b8b60
--- /dev/null
@@ -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 */
diff --git a/external/tinygettext/tinygettext/iconv.hpp b/external/tinygettext/tinygettext/iconv.hpp
new file mode 100644 (file)
index 0000000..1ae1750
--- /dev/null
@@ -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 */
diff --git a/external/tinygettext/tinygettext/language.cpp b/external/tinygettext/tinygettext/language.cpp
new file mode 100644 (file)
index 0000000..b9a1b46
--- /dev/null
@@ -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 {
+\f
+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;
+};
+\f
+/** 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                          }
+};
+//*}
+\f
+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;
+  }
+}
+\f
+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);
+}
+\f
+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)
+{
+  return language_spec == rhs.language_spec;
+}
+
+bool
+Language::operator!=(const Language& rhs)
+{
+  return language_spec != rhs.language_spec;
+}
+\f
+} // namespace tinygettext
+
+/* EOF */
diff --git a/external/tinygettext/tinygettext/language.hpp b/external/tinygettext/tinygettext/language.hpp
new file mode 100644 (file)
index 0000000..90eccc1
--- /dev/null
@@ -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);
+  bool operator!=(const Language& rhs);
+
+  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 */
diff --git a/external/tinygettext/tinygettext/log.cpp b/external/tinygettext/tinygettext/log.cpp
new file mode 100644 (file)
index 0000000..be8e2e6
--- /dev/null
@@ -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 {
+\f
+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;
+\f
+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;
+}
+\f
+Log::Log(log_callback_t callback_) :
+  callback(callback_),
+  out()
+{
+}
+
+Log::~Log() 
+{
+  callback(out.str());
+}
+
+std::ostream&
+Log::get() 
+{
+  return out; 
+}
+\f
+} // namespace tinygettext
+
+/* EOF */
diff --git a/external/tinygettext/tinygettext/log.hpp b/external/tinygettext/tinygettext/log.hpp
new file mode 100644 (file)
index 0000000..a8eadb4
--- /dev/null
@@ -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 */
diff --git a/external/tinygettext/tinygettext/log_stream.hpp b/external/tinygettext/tinygettext/log_stream.hpp
new file mode 100644 (file)
index 0000000..8ad4c02
--- /dev/null
@@ -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 */
diff --git a/external/tinygettext/tinygettext/plural_forms.cpp b/external/tinygettext/tinygettext/plural_forms.cpp
new file mode 100644 (file)
index 0000000..8271437
--- /dev/null
@@ -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 {
+\f
+/** 
+ *  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 ); }
+\f
+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 */
diff --git a/external/tinygettext/tinygettext/plural_forms.hpp b/external/tinygettext/tinygettext/plural_forms.hpp
new file mode 100644 (file)
index 0000000..0b06449
--- /dev/null
@@ -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 */
diff --git a/external/tinygettext/tinygettext/po_parser.cpp b/external/tinygettext/tinygettext/po_parser.cpp
new file mode 100644 (file)
index 0000000..5ceb3fd
--- /dev/null
@@ -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;
+\f
+void
+POParser::parse(const std::string& filename, std::istream& in, Dictionary& dict)
+{
+  POParser parser(filename, in, dict);
+  parser.parse();
+}
+\f
+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,unsigned int skip)
+{
+  if (skip+1 >= static_cast<unsigned int>(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(unsigned int skip)
+{
+  std::ostringstream out;
+
+  if (skip+1 >= static_cast<unsigned int>(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<unsigned int>(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);
+        unsigned int 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] == ']')
+          {
+            unsigned int number = static_cast<unsigned int>(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 */
diff --git a/external/tinygettext/tinygettext/po_parser.hpp b/external/tinygettext/tinygettext/po_parser.hpp
new file mode 100644 (file)
index 0000000..329af59
--- /dev/null
@@ -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(unsigned int skip);
+  void get_string_line(std::ostringstream& str,unsigned int 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 */
diff --git a/external/tinygettext/tinygettext/tinygettext.cpp b/external/tinygettext/tinygettext/tinygettext.cpp
new file mode 100644 (file)
index 0000000..7f5adc8
--- /dev/null
@@ -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 */
diff --git a/external/tinygettext/tinygettext/tinygettext.hpp b/external/tinygettext/tinygettext/tinygettext.hpp
new file mode 100644 (file)
index 0000000..19fd4c6
--- /dev/null
@@ -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 */
diff --git a/external/tinygettext/tinygettext/unix_file_system.cpp b/external/tinygettext/tinygettext/unix_file_system.cpp
new file mode 100644 (file)
index 0000000..5e14d17
--- /dev/null
@@ -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 */
diff --git a/external/tinygettext/tinygettext/unix_file_system.hpp b/external/tinygettext/tinygettext/unix_file_system.hpp
new file mode 100644 (file)
index 0000000..80f3e6d
--- /dev/null
@@ -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 */