From adc1067eeb6696a552f6738d9d394e619bf652f0 Mon Sep 17 00:00:00 2001 From: Christoph Sommer Date: Sat, 21 Jan 2012 11:00:24 +0100 Subject: [PATCH] add static import of tinygettext --- external/tinygettext/CMakeLists.txt | 177 +++ external/tinygettext/FindICONV.cmake | 100 ++ external/tinygettext/NEWS | 6 + external/tinygettext/README | 21 + external/tinygettext/SConstruct | 37 + external/tinygettext/TODO | 76 ++ external/tinygettext/test/broken.po | 57 + external/tinygettext/test/game/de.po | 1040 ++++++++++++++++ external/tinygettext/test/helloworld.cpp | 24 + external/tinygettext/test/helloworld/de.po | 56 + .../test/helloworld/helloworld.pot | 55 + external/tinygettext/test/level/de.po | 379 ++++++ external/tinygettext/test/po/de.po | 1047 +++++++++++++++++ external/tinygettext/test/po/de_AT.po | 33 + external/tinygettext/test/po/fr.po | 20 + external/tinygettext/test/po_parser_test.cpp | 71 ++ external/tinygettext/test/test.sh | 8 + .../tinygettext/test/tinygettext_test.cpp | 204 ++++ external/tinygettext/tinygettext.pc.in | 16 + .../tinygettext/tinygettext/dictionary.cpp | 208 ++++ .../tinygettext/tinygettext/dictionary.hpp | 123 ++ .../tinygettext/dictionary_manager.cpp | 242 ++++ .../tinygettext/dictionary_manager.hpp | 99 ++ .../tinygettext/tinygettext/file_system.hpp | 42 + external/tinygettext/tinygettext/iconv.cpp | 148 +++ external/tinygettext/tinygettext/iconv.hpp | 71 ++ external/tinygettext/tinygettext/language.cpp | 568 +++++++++ external/tinygettext/tinygettext/language.hpp | 91 ++ external/tinygettext/tinygettext/log.cpp | 70 ++ external/tinygettext/tinygettext/log.hpp | 56 + .../tinygettext/tinygettext/log_stream.hpp | 34 + .../tinygettext/tinygettext/plural_forms.cpp | 89 ++ .../tinygettext/tinygettext/plural_forms.hpp | 61 + .../tinygettext/tinygettext/po_parser.cpp | 496 ++++++++ .../tinygettext/tinygettext/po_parser.hpp | 75 ++ .../tinygettext/tinygettext/tinygettext.cpp | 22 + .../tinygettext/tinygettext/tinygettext.hpp | 27 + .../tinygettext/unix_file_system.cpp | 65 + .../tinygettext/unix_file_system.hpp | 38 + 39 files changed, 6052 insertions(+) create mode 100644 external/tinygettext/CMakeLists.txt create mode 100644 external/tinygettext/FindICONV.cmake create mode 100644 external/tinygettext/NEWS create mode 100644 external/tinygettext/README create mode 100644 external/tinygettext/SConstruct create mode 100644 external/tinygettext/TODO create mode 100644 external/tinygettext/test/broken.po create mode 100644 external/tinygettext/test/game/de.po create mode 100644 external/tinygettext/test/helloworld.cpp create mode 100644 external/tinygettext/test/helloworld/de.po create mode 100644 external/tinygettext/test/helloworld/helloworld.pot create mode 100644 external/tinygettext/test/level/de.po create mode 100644 external/tinygettext/test/po/de.po create mode 100644 external/tinygettext/test/po/de_AT.po create mode 100644 external/tinygettext/test/po/fr.po create mode 100644 external/tinygettext/test/po_parser_test.cpp create mode 100755 external/tinygettext/test/test.sh create mode 100644 external/tinygettext/test/tinygettext_test.cpp create mode 100644 external/tinygettext/tinygettext.pc.in create mode 100644 external/tinygettext/tinygettext/dictionary.cpp create mode 100644 external/tinygettext/tinygettext/dictionary.hpp create mode 100644 external/tinygettext/tinygettext/dictionary_manager.cpp create mode 100644 external/tinygettext/tinygettext/dictionary_manager.hpp create mode 100644 external/tinygettext/tinygettext/file_system.hpp create mode 100644 external/tinygettext/tinygettext/iconv.cpp create mode 100644 external/tinygettext/tinygettext/iconv.hpp create mode 100644 external/tinygettext/tinygettext/language.cpp create mode 100644 external/tinygettext/tinygettext/language.hpp create mode 100644 external/tinygettext/tinygettext/log.cpp create mode 100644 external/tinygettext/tinygettext/log.hpp create mode 100644 external/tinygettext/tinygettext/log_stream.hpp create mode 100644 external/tinygettext/tinygettext/plural_forms.cpp create mode 100644 external/tinygettext/tinygettext/plural_forms.hpp create mode 100644 external/tinygettext/tinygettext/po_parser.cpp create mode 100644 external/tinygettext/tinygettext/po_parser.hpp create mode 100644 external/tinygettext/tinygettext/tinygettext.cpp create mode 100644 external/tinygettext/tinygettext/tinygettext.hpp create mode 100644 external/tinygettext/tinygettext/unix_file_system.cpp create mode 100644 external/tinygettext/tinygettext/unix_file_system.hpp diff --git a/external/tinygettext/CMakeLists.txt b/external/tinygettext/CMakeLists.txt new file mode 100644 index 00000000000..6c1d78b8328 --- /dev/null +++ b/external/tinygettext/CMakeLists.txt @@ -0,0 +1,177 @@ +# +# TinyGetText build script +# Copyright (C) 2006 Christoph Sommer +# +# 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 + // 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 index 00000000000..0ac82b78903 --- /dev/null +++ b/external/tinygettext/FindICONV.cmake @@ -0,0 +1,100 @@ +# +# Copyright (c) 2006, Peter Kümmel, +# +# 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 index 00000000000..fcf6ef6381c --- /dev/null +++ b/external/tinygettext/NEWS @@ -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 index 00000000000..0eeabe93e23 --- /dev/null +++ b/external/tinygettext/README @@ -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 index 00000000000..92613fd47da --- /dev/null +++ b/external/tinygettext/SConstruct @@ -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 index 00000000000..29daf3fec4e --- /dev/null +++ b/external/tinygettext/TODO @@ -0,0 +1,76 @@ +tinygettext API related stuff: +============================== + +* translate, translate_ctxt, translate_ctxt_plural, ... could be + unified via overloading, not sure if that is a good idea. For the + same reason add_translation() could be de-overloaded, to + add_translation_ctxt, ... + +* iconv handling needs cleanup and more flexibility, since some + systems don't provide iconv or only through SDL + +* Customizability could use grouping and documentation or other means + to make it more obvious: + + - POParser::pedantic + - iconv (???) + - logging (log_callback(std::string)) + +* handle errors better, not with log_* stream, cases of errors: + + - couldn't translate + - collision while adding translation + - failure to open file or directory + - unknown language + - iconv failure to convert charset + +* ABI management/freezing. If tinygettext is to benefit other projects, + it should be able to provide a stable API (and, better, ABI). + + +tinygettext implementation details: +=================================== + +* with PluralForms moved into Dictionary a lot of the Langugae stuff + is pointless + +* get rid of goto + +* POParser can handle Big5, but needs testing. + Big5 is one byte for ASCII letters and two bytes for chinese ones, + this means some two byte characters collide with '\', some .po files + seem to escape the \ properly so that the string can be read as + usual, while others don't. + +* _() -> getext() (gettext default) + N_(id) -> gettext_noop(id) (gettext default) + C_(ctxt, id) -> pgettext(ctxt, id) (Gnome does this: http://library.gnome.org/devel/glib/2.16/glib-I18N.html#Q-:CAPS) + NC_(ctxt, id) -> pgettext(ctxt, id) (Gnome does this: http://library.gnome.org/devel/glib/2.16/glib-I18N.html#Q-:CAPS) + +* figure out how up-to-date other tinygettext implementations in the + wild are (LinCity): + + Pingus: + ------- + dictionary.hpp (synced with Pingus) + dictionary_manager.hpp (PhysFS vs opendir()) + language_def.hpp (synced with Pingus) + po_file_reader.hpp (UTF-8 0xef-'header', lots of stuff from mathner) + tinygettext.hpp (iconv vs convert) + + +Random Unimportant Stuff +======================== + +* a hashmap instead of std::map might be a good idea + +* support for .gmo files would be cool + +tinygettext Documentation: +========================== + +* recommend a way to handle translation of speech and other data files + +* document how to use tinygettext and make it work like gettext + +# EOF # diff --git a/external/tinygettext/test/broken.po b/external/tinygettext/test/broken.po new file mode 100644 index 00000000000..c841a73c2ff --- /dev/null +++ b/external/tinygettext/test/broken.po @@ -0,0 +1,57 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR Free Software Foundation, Inc. +# FIRST AUTHOR , 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 \n" +"Language-Team: LANGUAGE \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 index 00000000000..a92db3b3edd --- /dev/null +++ b/external/tinygettext/test/game/de.po @@ -0,0 +1,1040 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR Free Software Foundation, Inc. +# FIRST AUTHOR , 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 \n" +"Language-Team: David Philippi , Ingo Ruhnke , Giray Devlet \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: -.plf" +msgstr "Dateinamensvorgabe: -.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 , include informations" +msgstr "" +"| Bitte schreibe einen kleinen Report an 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 index 00000000000..071ab96ad9c --- /dev/null +++ b/external/tinygettext/test/helloworld.cpp @@ -0,0 +1,24 @@ +#include + +#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 index 00000000000..048acc63f50 --- /dev/null +++ b/external/tinygettext/test/helloworld/de.po @@ -0,0 +1,56 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR Free Software Foundation, Inc. +# FIRST AUTHOR , 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 \n" +"Language-Team: LANGUAGE \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 index 00000000000..a9174f81ef4 --- /dev/null +++ b/external/tinygettext/test/helloworld/helloworld.pot @@ -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 , 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 \n" +"Language-Team: LANGUAGE \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 index 00000000000..69e02060ce1 --- /dev/null +++ b/external/tinygettext/test/level/de.po @@ -0,0 +1,379 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR Free Software Foundation, Inc. +# FIRST AUTHOR , YEAR. +# +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: PACKAGE VERSION\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI +ZONE\n" +"Last-Translator: FULL NAME \n" +"Language-Team: LANGUAGE \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 index 00000000000..e863f81786e --- /dev/null +++ b/external/tinygettext/test/po/de.po @@ -0,0 +1,1047 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR Free Software Foundation, Inc. +# FIRST AUTHOR , 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 \n" +"Language-Team: David Philippi , Ingo Ruhnke , Giray Devlet \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: -.plf" +msgstr "Dateinamensvorgabe: -.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 , include informations" +msgstr "" +"| Bitte schreibe einen kleinen Report an 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 index 00000000000..f4c3d8163db --- /dev/null +++ b/external/tinygettext/test/po/de_AT.po @@ -0,0 +1,33 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR Free Software Foundation, Inc. +# FIRST AUTHOR , YEAR. +# +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: PACKAGE VERSION\n" +"PO-Revision-Date: 2009-02-02 12:07+0100\n" +"Last-Translator: FULL NAME \n" +"Language-Team: LANGUAGE \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 index 00000000000..0670f489a3e --- /dev/null +++ b/external/tinygettext/test/po/fr.po @@ -0,0 +1,20 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR Free Software Foundation, Inc. +# FIRST AUTHOR , YEAR. +# +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: PACKAGE VERSION\n" +"PO-Revision-Date: 2009-01-28 08:45+0100\n" +"Last-Translator: FULL NAME \n" +"Language-Team: LANGUAGE \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 index 00000000000..e8f0ffb78dc --- /dev/null +++ b/external/tinygettext/test/po_parser_test.cpp @@ -0,0 +1,71 @@ +// tinygettext - A gettext replacement that works directly on .po files +// Copyright (C) 2009 Ingo Ruhnke +// +// 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 +#include +#include +#include +#include + +#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 index 00000000000..a7b77898845 --- /dev/null +++ b/external/tinygettext/test/test.sh @@ -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 index 00000000000..c0edb52948a --- /dev/null +++ b/external/tinygettext/test/tinygettext_test.cpp @@ -0,0 +1,204 @@ +// TinyGetText +// Copyright (C) 2009 Ingo Ruhnke +// +// 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 +#include +#include +#include +#include +#include +#include "tinygettext/po_parser.hpp" +#include "tinygettext/tinygettext.hpp" + +using namespace tinygettext; + +void print_msg(const std::string& msgid, const std::vector& msgstrs) +{ + std::cout << "Msgid: " << msgid << std::endl; + for(std::vector::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& msgstrs) +{ + std::cout << "Msgctxt: " << ctxt << std::endl; + std::cout << "Msgid: " << msgid << std::endl; + for(std::vector::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& languages = dictionary_manager.get_languages(); + std::cout << "Number of languages: " << languages.size() << std::endl; + for (std::set::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 index 00000000000..ef82a934db7 --- /dev/null +++ b/external/tinygettext/tinygettext.pc.in @@ -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 index 00000000000..9765d751d6c --- /dev/null +++ b/external/tinygettext/tinygettext/dictionary.cpp @@ -0,0 +1,208 @@ +// tinygettext - A gettext replacement that works directly on .po files +// Copyright (C) 2006 Ingo Ruhnke +// +// 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 +#include "log_stream.hpp" +#include "dictionary.hpp" + +namespace tinygettext { + +Dictionary::Dictionary(const std::string& charset_) : + entries(), + ctxt_entries(), + charset(charset_), + plural_forms() +{ +} + +Dictionary::~Dictionary() +{ +} + +std::string +Dictionary::get_charset() const +{ + return charset; +} + +void +Dictionary::set_plural_forms(const PluralForms& plural_forms_) +{ + plural_forms = plural_forms_; +} + +PluralForms +Dictionary::get_plural_forms() const +{ + return plural_forms; +} + +std::string +Dictionary::translate_plural(const std::string& msgid, const std::string& msgid_plural, int num) +{ + return translate_plural(entries, msgid, msgid_plural, num); +} + +std::string +Dictionary::translate_plural(const Entries& dict, const std::string& msgid, const std::string& msgid_plural, int count) +{ + Entries::const_iterator i = dict.find(msgid); + const std::vector& msgstrs = i->second; + + if (i != dict.end()) + { + unsigned int n = 0; + n = plural_forms.get_plural(count); + assert(/*n >= 0 &&*/ n < msgstrs.size()); + + if (!msgstrs[n].empty()) + return msgstrs[n]; + else + if (count == 1) // default to english rules + return msgid; + else + return msgid_plural; + } + else + { + log_info << "Couldn't translate: " << msgid << std::endl; + log_info << "Candidates: " << std::endl; + for (i = dict.begin(); i != dict.end(); ++i) + log_info << "'" << i->first << "'" << std::endl; + + if (count == 1) // default to english rules + return msgid; + else + return msgid_plural; + } +} + +std::string +Dictionary::translate(const std::string& msgid) +{ + return translate(entries, msgid); +} + +std::string +Dictionary::translate(const Entries& dict, const std::string& msgid) +{ + Entries::const_iterator i = dict.find(msgid); + if (i != dict.end() && !i->second.empty()) + { + return i->second[0]; + } + else + { + log_info << "Couldn't translate: " << msgid << std::endl; + return msgid; + } +} + +std::string +Dictionary::translate_ctxt(const std::string& msgctxt, const std::string& msgid) +{ + CtxtEntries::iterator i = ctxt_entries.find(msgctxt); + if (i != ctxt_entries.end()) + { + return translate(i->second, msgid); + } + else + { + log_info << "Couldn't translate: " << msgid << std::endl; + return msgid; + } +} + +std::string +Dictionary::translate_ctxt_plural(const std::string& msgctxt, + const std::string& msgid, const std::string& msgidplural, int num) +{ + CtxtEntries::iterator i = ctxt_entries.find(msgctxt); + if (i != ctxt_entries.end()) + { + return translate_plural(i->second, msgid, msgidplural, num); + } + else + { + log_info << "Couldn't translate: " << msgid << std::endl; + if (num != 1) // default to english + return msgidplural; + else + return msgid; + } +} + +void +Dictionary::add_translation(const std::string& msgid, const std::string& , + const std::vector& 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& 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& msgstrs) +{ + std::vector& 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& vec = ctxt_entries[msgctxt][msgid]; + if (vec.empty()) + { + vec.push_back(msgstr); + } + else + { + log_warning << "collision in add_translation(\"" << msgctxt << "\", \"" << msgid << "\")" << std::endl; + vec[0] = msgstr; + } +} + +} // namespace tinygettext + +/* EOF */ diff --git a/external/tinygettext/tinygettext/dictionary.hpp b/external/tinygettext/tinygettext/dictionary.hpp new file mode 100644 index 00000000000..743e075a07d --- /dev/null +++ b/external/tinygettext/tinygettext/dictionary.hpp @@ -0,0 +1,123 @@ +// tinygettext - A gettext replacement that works directly on .po files +// Copyright (C) 2006 Ingo Ruhnke +// +// 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 +#include +#include +#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 > Entries; + Entries entries; + + typedef std::map 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& msgstrs); + void add_translation(const std::string& msgctxt, + const std::string& msgid, const std::string& msgid_plural, + const std::vector& 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& msgstrs) */ + template + 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& msgstrs) */ + template + 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 index 00000000000..f923470f740 --- /dev/null +++ b/external/tinygettext/tinygettext/dictionary_manager.cpp @@ -0,0 +1,242 @@ +// tinygettext - A gettext replacement that works directly on .po files +// Copyright (C) 2006 Ingo Ruhnke +// +// 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 +#include +#include +#include +#include +#include + +#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 files = filesystem->open_directory(*p); + + std::string best_filename; + int best_score = 0; + + for(std::vector::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 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 +DictionaryManager::get_languages() +{ + std::set languages; + + for (SearchPath::iterator p = search_path.begin(); p != search_path.end(); ++p) + { + std::vector files = filesystem->open_directory(*p); + + for(std::vector::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_; +} + +} // namespace tinygettext + +/* EOF */ diff --git a/external/tinygettext/tinygettext/dictionary_manager.hpp b/external/tinygettext/tinygettext/dictionary_manager.hpp new file mode 100644 index 00000000000..7c3d7f3bcbd --- /dev/null +++ b/external/tinygettext/tinygettext/dictionary_manager.hpp @@ -0,0 +1,99 @@ +// tinygettext - A gettext replacement that works directly on .po files +// Copyright (C) 2006 Ingo Ruhnke +// +// 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 +#include +#include +#include +#include + +#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 Dictionaries; + Dictionaries dictionaries; + + typedef std::vector SearchPath; + SearchPath search_path; + + std::string charset; + bool use_fuzzy; + + Language current_language; + Dictionary* current_dict; + + Dictionary empty_dict; + + std::auto_ptr 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 get_languages(); + + void set_filesystem(std::auto_ptr 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 index 00000000000..af47aaf966a --- /dev/null +++ b/external/tinygettext/tinygettext/file_system.hpp @@ -0,0 +1,42 @@ +// tinygettext - A gettext replacement that works directly on .po files +// Copyright (C) 2009 Ingo Ruhnke +// +// 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 +#include +#include +#include + +namespace tinygettext { + +class FileSystem +{ +public: + virtual ~FileSystem() {} + + virtual std::vector open_directory(const std::string& pathname) =0; + virtual std::auto_ptr 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 index 00000000000..c0b8b607228 --- /dev/null +++ b/external/tinygettext/tinygettext/iconv.cpp @@ -0,0 +1,148 @@ +// tinygettext - A gettext replacement that works directly on .po files +// Copyright (C) 2009 Ingo Ruhnke +// +// 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 +#include +#include +#include +#include +#include +#include + +#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(toupper(*i)); + + for(std::string::iterator i = from_charset.begin(); i != from_charset.end(); ++i) + *i = static_cast(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(-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(&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(-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: : 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 index 00000000000..1ae1750b976 --- /dev/null +++ b/external/tinygettext/tinygettext/iconv.hpp @@ -0,0 +1,71 @@ +// tinygettext - A gettext replacement that works directly on .po files +// Copyright (C) 2006 Ingo Ruhnke +// +// 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 . + +#ifndef HEADER_TINYGETTEXT_ICONV_HPP +#define HEADER_TINYGETTEXT_ICONV_HPP + +#include + +#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 + +# 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 index 00000000000..b9a1b46e312 --- /dev/null +++ b/external/tinygettext/tinygettext/language.cpp @@ -0,0 +1,568 @@ +// tinygettext - A gettext replacement that works directly on .po files +// Copyright (C) 2006 Ingo Ruhnke +// +// 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 +#include +#include + +namespace tinygettext { + +struct LanguageSpec { + /** Language code: "de", "en", ... */ + const char* language; + + /** Country code: "BR", "DE", ..., can be 0 */ + const char* country; + + /** Modifier/Varint: "Latn", "ije", "latin"..., can be 0 */ + const char* modifier; + + /** Language name: "German", "English", "French", ... */ + const char* name; +}; + +/** Language Definitions */ +//*{ +LanguageSpec languages[] = { + { "aa", 0, 0, "Afar" }, + { "af", 0, 0, "Afrikaans" }, + { "af", "ZA", 0, "Afrikaans (South Africa)" }, + { "am", 0, 0, "Amharic" }, + { "ar", 0, 0, "Arabic" }, + { "ar", "AR", 0, "Arabic (Argentina)" }, + { "ar", "OM", 0, "Arabic (Oman)" }, + { "ar", "SA", 0, "Arabic (Saudi Arabia)" }, + { "ar", "SY", 0, "Arabic (Syrian Arab Republic)" }, + { "ar", "TN", 0, "Arabic (Tunisia)" }, + { "as", 0, 0, "Assamese" }, + { "ast",0, 0, "Asturian" }, + { "ay", 0, 0, "Aymara" }, + { "az", 0, 0, "Azerbaijani" }, + { "az", "IR", 0, "Azerbaijani (Iran)" }, + { "be", 0, 0, "Belarusian" }, + { "be", 0, "latin", "Belarusian" }, + { "bg", 0, 0, "Bulgarian" }, + { "bg", "BG", 0, "Bulgarian (Bulgaria)" }, + { "bn", 0, 0, "Bengali" }, + { "bn", "BD", 0, "Bengali (Bangladesh)" }, + { "bn", "IN", 0, "Bengali (India)" }, + { "bo", 0, 0, "Tibetan" }, + { "br", 0, 0, "Breton" }, + { "bs", 0, 0, "Bosnian" }, + { "bs", "BA", 0, "Bosnian (Bosnia/Herzegovina)"}, + { "bs", "BS", 0, "Bosnian (Bahamas)" }, + { "ca", "ES", "valencia", "Catalan (valencia)" }, + { "ca", "ES", 0, "Catalan (Spain)" }, + { "ca", 0, "valencia", "Catalan (valencia)" }, + { "ca", 0, 0, "Catalan" }, + { "co", 0, 0, "Corsican" }, + { "cs", 0, 0, "Czech" }, + { "cs", "CZ", 0, "Czech (Czech Republic)" }, + { "cy", 0, 0, "Welsh" }, + { "cy", "GB", 0, "Welsh (Great Britain)" }, + { "cz", 0, 0, "Unknown language" }, + { "da", 0, 0, "Danish" }, + { "da", "DK", 0, "Danish (Denmark)" }, + { "de", 0, 0, "German" }, + { "de", "AT", 0, "German (Austria)" }, + { "de", "CH", 0, "German (Switzerland)" }, + { "de", "DE", 0, "German (Germany)" }, + { "dk", 0, 0, "Unknown language" }, + { "dz", 0, 0, "Dzongkha" }, + { "el", 0, 0, "Greek" }, + { "el", "GR", 0, "Greek (Greece)" }, + { "en", 0, 0, "English" }, + { "en", "AU", 0, "English (Australia)" }, + { "en", "CA", 0, "English (Canada)" }, + { "en", "GB", 0, "English (Great Britain)" }, + { "en", "US", 0, "English (United States)" }, + { "en", "ZA", 0, "English (South Africa)" }, + { "en", 0, "boldquot", "English" }, + { "en", 0, "quot", "English" }, + { "en", "US", "piglatin", "English" }, + { "eo", 0, 0, "Esperanto" }, + { "es", 0, 0, "Spanish" }, + { "es", "AR", 0, "Spanish (Argentina)" }, + { "es", "CL", 0, "Spanish (Chile)" }, + { "es", "CO", 0, "Spanish (Colombia)" }, + { "es", "CR", 0, "Spanish (Costa Rica)" }, + { "es", "DO", 0, "Spanish (Dominican Republic)"}, + { "es", "EC", 0, "Spanish (Ecuador)" }, + { "es", "ES", 0, "Spanish (Spain)" }, + { "es", "GT", 0, "Spanish (Guatemala)" }, + { "es", "HN", 0, "Spanish (Honduras)" }, + { "es", "LA", 0, "Spanish (Laos)" }, + { "es", "MX", 0, "Spanish (Mexico)" }, + { "es", "NI", 0, "Spanish (Nicaragua)" }, + { "es", "PA", 0, "Spanish (Panama)" }, + { "es", "PE", 0, "Spanish (Peru)" }, + { "es", "PR", 0, "Spanish (Puerto Rico)" }, + { "es", "SV", 0, "Spanish (El Salvador)" }, + { "es", "UY", 0, "Spanish (Uruguay)" }, + { "es", "VE", 0, "Spanish (Venezuela)" }, + { "et", 0, 0, "Estonian" }, + { "et", "EE", 0, "Estonian (Estonia)" }, + { "et", "ET", 0, "Estonian (Ethiopia)" }, + { "eu", 0, 0, "Basque" }, + { "eu", "ES", 0, "Basque (Spain)" }, + { "fa", 0, 0, "Persian" }, + { "fa", "AF", 0, "Persian (Afghanistan)" }, + { "fa", "IR", 0, "Persian (Iran)" }, + { "fi", 0, 0, "Finnish" }, + { "fi", "FI", 0, "Finnish (Finland)" }, + { "fo", 0, 0, "Faroese" }, + { "fo", "FO", 0, "Faeroese (Faroe Islands)" }, + { "fr", 0, 0, "French" }, + { "fr", "CA", 0, "French (Canada)" }, + { "fr", "CH", 0, "French (Switzerland)" }, + { "fr", "FR", 0, "French (France)" }, + { "fr", "LU", 0, "French (Luxembourg)" }, + { "fy", 0, 0, "Frisian" }, + { "ga", 0, 0, "Irish" }, + { "gd", 0, 0, "Gaelic Scots" }, + { "gl", 0, 0, "Galician" }, + { "gl", "ES", 0, "Galician (Spain)" }, + { "gn", 0, 0, "Guarani" }, + { "gu", 0, 0, "Gujarati" }, + { "gv", 0, 0, "Manx" }, + { "ha", 0, 0, "Hausa" }, + { "he", 0, 0, "Hebrew" }, + { "he", "IL", 0, "Hebrew (Israel)" }, + { "hi", 0, 0, "Hindi" }, + { "hr", 0, 0, "Croatian" }, + { "hr", "HR", 0, "Croatian (Croatia)" }, + { "hu", 0, 0, "Hungarian" }, + { "hu", "HU", 0, "Hungarian (Hungary)" }, + { "hy", 0, 0, "Armenian" }, + { "ia", 0, 0, "Interlingua" }, + { "id", 0, 0, "Indonesian" }, + { "id", "ID", 0, "Indonesian (Indonesia)" }, + { "is", 0, 0, "Icelandic" }, + { "is", "IS", 0, "Icelandic (Iceland)" }, + { "it", 0, 0, "Italian" }, + { "it", "CH", 0, "Italian (Switzerland)" }, + { "it", "IT", 0, "Italian (Italy)" }, + { "iu", 0, 0, "Inuktitut" }, + { "ja", 0, 0, "Japanese" }, + { "ja", "JP", 0, "Japanese (Japan)" }, + { "ka", 0, 0, "Georgian" }, + { "kk", 0, 0, "Kazakh" }, + { "kl", 0, 0, "Kalaallisut" }, + { "km", 0, 0, "Khmer" }, + { "km", "KH", 0, "Khmer (Cambodia)" }, + { "kn", 0, 0, "Kannada" }, + { "ko", 0, 0, "Korean" }, + { "ko", "KR", 0, "Korean (Korea)" }, + { "ku", 0, 0, "Kurdish" }, + { "kw", 0, 0, "Cornish" }, + { "ky", 0, 0, "Kirghiz" }, + { "la", 0, 0, "Latin" }, + { "lo", 0, 0, "Lao" }, + { "lt", 0, 0, "Lithuanian" }, + { "lt", "LT", 0, "Lithuanian (Lithuania)" }, + { "lv", 0, 0, "Latvian" }, + { "lv", "LV", 0, "Latvian (Latvia)" }, + { "mg", 0, 0, "Malagasy" }, + { "mi", 0, 0, "Maori" }, + { "mk", 0, 0, "Macedonian" }, + { "mk", "MK", 0, "Macedonian (Macedonia)" }, + { "ml", 0, 0, "Malayalam" }, + { "mn", 0, 0, "Mongolian" }, + { "mr", 0, 0, "Marathi" }, + { "ms", 0, 0, "Malay" }, + { "ms", "MY", 0, "Malay (Malaysia)" }, + { "mt", 0, 0, "Maltese" }, + { "my", 0, 0, "Burmese" }, + { "my", "MM", 0, "Burmese (Myanmar)" }, + { "nb", 0, 0, "Norwegian Bokmal" }, + { "nb", "NO", 0, "Norwegian Bokmål (Norway)" }, + { "ne", 0, 0, "Nepali" }, + { "nl", 0, 0, "Dutch" }, + { "nl", "BE", 0, "Dutch (Belgium)" }, + { "nl", "NL", 0, "Dutch (Netherlands)" }, + { "nn", 0, 0, "Norwegian Nynorsk" }, + { "nn", "NO", 0, "Norwegian Nynorsk (Norway)" }, + { "no", 0, 0, "Norwegian" }, + { "no", "NO", 0, "Norwegian (Norway)" }, + { "no", "NY", 0, "Norwegian (NY)" }, + { "nr", 0, 0, "Ndebele, South" }, + { "oc", 0, 0, "Occitan post 1500" }, + { "om", 0, 0, "Oromo" }, + { "or", 0, 0, "Oriya" }, + { "pa", 0, 0, "Punjabi" }, + { "pl", 0, 0, "Polish" }, + { "pl", "PL", 0, "Polish (Poland)" }, + { "ps", 0, 0, "Pashto" }, + { "pt", 0, 0, "Portuguese" }, + { "pt", "BR", 0, "Brazilian" }, + { "pt", "PT", 0, "Portuguese (Portugal)" }, + { "qu", 0, 0, "Quechua" }, + { "rm", 0, 0, "Rhaeto-Romance" }, + { "ro", 0, 0, "Romanian" }, + { "ro", "RO", 0, "Romanian (Romania)" }, + { "ru", 0, 0, "Russian" }, + { "ru", "RU", 0, "Russian (Russia" }, + { "rw", 0, 0, "Kinyarwanda" }, + { "sa", 0, 0, "Sanskrit" }, + { "sd", 0, 0, "Sindhi" }, + { "se", 0, 0, "Sami" }, + { "se", "NO", 0, "Sami (Norway)" }, + { "si", 0, 0, "Sinhalese" }, + { "sk", 0, 0, "Slovak" }, + { "sk", "SK", 0, "Slovak (Slovakia)" }, + { "sl", 0, 0, "Slovenian" }, + { "sl", "SI", 0, "Slovenian (Slovenia)" }, + { "sl", "SL", 0, "Slovenian (Sierra Leone)" }, + { "sm", 0, 0, "Samoan" }, + { "so", 0, 0, "Somali" }, + { "sp", 0, 0, "Unknown language" }, + { "sq", 0, 0, "Albanian" }, + { "sq", "AL", 0, "Albanian (Albania)" }, + { "sr", 0, 0, "Serbian" }, + { "sr", "YU", 0, "Serbian (Yugoslavia)" }, + { "sr", 0,"ije", "Serbian" }, + { "sr", 0, "latin", "Serbian" }, + { "sr", 0, "Latn", "Serbian" }, + { "ss", 0, 0, "Swati" }, + { "st", 0, 0, "Sotho" }, + { "sv", 0, 0, "Swedish" }, + { "sv", "SE", 0, "Swedish (Sweden)" }, + { "sv", "SV", 0, "Swedish (El Salvador)" }, + { "sw", 0, 0, "Swahili" }, + { "ta", 0, 0, "Tamil" }, + { "te", 0, 0, "Telugu" }, + { "tg", 0, 0, "Tajik" }, + { "th", 0, 0, "Thai" }, + { "th", "TH", 0, "Thai (Thailand)" }, + { "ti", 0, 0, "Tigrinya" }, + { "tk", 0, 0, "Turkmen" }, + { "tl", 0, 0, "Tagalog" }, + { "to", 0, 0, "Tonga" }, + { "tr", 0, 0, "Turkish" }, + { "tr", "TR", 0, "Turkish (Turkey)" }, + { "ts", 0, 0, "Tsonga" }, + { "tt", 0, 0, "Tatar" }, + { "ug", 0, 0, "Uighur" }, + { "uk", 0, 0, "Ukrainian" }, + { "uk", "UA", 0, "Ukrainian (Ukraine)" }, + { "ur", 0, 0, "Urdu" }, + { "ur", "PK", 0, "Urdu (Pakistan)" }, + { "uz", 0, 0, "Uzbek" }, + { "uz", 0, "cyrillic", "Uzbek" }, + { "vi", 0, 0, "Vietnamese" }, + { "vi", "VN", 0, "Vietnamese (Vietnam)" }, + { "wa", 0, 0, "Walloon" }, + { "wo", 0, 0, "Wolof" }, + { "xh", 0, 0, "Xhosa" }, + { "yi", 0, 0, "Yiddish" }, + { "yo", 0, 0, "Yoruba" }, + { "zh", 0, 0, "Chinese" }, + { "zh", "CN", 0, "Chinese (simplified)" }, + { "zh", "HK", 0, "Chinese (Hong Kong)" }, + { "zh", "TW", 0, "Chinese (traditional)" }, + { "zu", 0, 0, "Zulu" }, + { NULL, 0, 0, NULL } +}; +//*} + +std::string +resolve_language_alias(const std::string& name) +{ + typedef std::map 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(tolower(name[i])); + + Aliases::iterator i = language_aliases.find(name_lowercase); + if (i != language_aliases.end()) + { + return i->second; + } + else + { + return name; + } +} + +Language +Language::from_spec(const std::string& language, const std::string& country, const std::string& modifier) +{ + static std::map > 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 >::iterator i = language_map.find(language); + if (i != language_map.end()) + { + std::vector& 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::iterator j = lst.begin(); j != lst.end(); ++j) + { // Search for the language that best matches the given spec, value country more then modifier + int score = Language::match(Language(*j), tmplang); + + if (score > best_match_score) + { + best_match = *j; + best_match_score = score; + } + } + assert(best_match); + return Language(best_match); + } + else + { + return Language(); + } +} + +Language +Language::from_name(const std::string& spec_str) +{ + return from_env(resolve_language_alias(spec_str)); +} + +Language +Language::from_env(const std::string& env) +{ + // Split LANGUAGE_COUNTRY.CODESET@MODIFIER into parts + std::string::size_type ln = env.find('_'); + std::string::size_type dt = env.find('.'); + std::string::size_type at = env.find('@'); + + std::string language; + std::string country; + std::string codeset; + std::string modifier; + + //std::cout << ln << " " << dt << " " << at << std::endl; + + language = env.substr(0, std::min(std::min(ln, dt), at)); + + if (ln != std::string::npos && ln+1 < env.size()) // _ + { + country = env.substr(ln+1, (std::min(dt, at) == std::string::npos) ? std::string::npos : std::min(dt, at) - (ln+1)); + } + + if (dt != std::string::npos && dt+1 < env.size()) // . + { + codeset = env.substr(dt+1, (at == std::string::npos) ? std::string::npos : (at - (dt+1))); + } + + if (at != std::string::npos && at+1 < env.size()) // @ + { + modifier = env.substr(at+1); + } + + return from_spec(language, country, modifier); +} + +Language::Language(LanguageSpec* language_spec_) + : language_spec(language_spec_) +{ +} + +Language::Language() + : language_spec(0) +{ +} + +int +Language::match(const Language& lhs, const Language& rhs) +{ + if (lhs.get_language() != rhs.get_language()) + { + return 0; + } + else + { + static int match_tbl[3][3] = { + // modifier match, wildchard, miss + { 9, 8, 5 }, // country match + { 7, 6, 3 }, // country wildcard + { 4, 2, 1 }, // country miss + }; + + int c; + if (lhs.get_country() == rhs.get_country()) + c = 0; + else if (lhs.get_country().empty() || rhs.get_country().empty()) + c = 1; + else + c = 2; + + int m; + if (lhs.get_modifier() == rhs.get_modifier()) + m = 0; + else if (lhs.get_modifier().empty() || rhs.get_modifier().empty()) + m = 1; + else + m = 2; + + return match_tbl[c][m]; + } +} + +std::string +Language::get_language() const +{ + if (language_spec) + return language_spec->language; + else + return ""; +} + +std::string +Language::get_country() const +{ + if (language_spec && language_spec->country) + return language_spec->country; + else + return ""; +} + +std::string +Language::get_modifier() const +{ + if (language_spec && language_spec->modifier) + return language_spec->modifier; + else + return ""; +} + +std::string +Language::get_name() const +{ + if (language_spec) + return language_spec->name; + else + return ""; +} + +std::string +Language::str() const +{ + if (language_spec) + { + std::string var; + var += language_spec->language; + if (language_spec->country) + { + var += "_"; + var += language_spec->country; + } + + if (language_spec->modifier) + { + var += "@"; + var += language_spec->modifier; + } + return var; + } + else + { + return ""; + } +} + +bool +Language::operator==(const Language& rhs) +{ + return language_spec == rhs.language_spec; +} + +bool +Language::operator!=(const Language& rhs) +{ + return language_spec != rhs.language_spec; +} + +} // namespace tinygettext + +/* EOF */ diff --git a/external/tinygettext/tinygettext/language.hpp b/external/tinygettext/tinygettext/language.hpp new file mode 100644 index 00000000000..90eccc1d408 --- /dev/null +++ b/external/tinygettext/tinygettext/language.hpp @@ -0,0 +1,91 @@ +// tinygettext - A gettext replacement that works directly on .po files +// Copyright (C) 2006 Ingo Ruhnke +// +// 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 + +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 index 00000000000..be8e2e691a6 --- /dev/null +++ b/external/tinygettext/tinygettext/log.cpp @@ -0,0 +1,70 @@ +// tinygettext - A gettext replacement that works directly on .po files +// Copyright (C) 2009 Ingo Ruhnke +// +// 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 +#include "log.hpp" + +namespace tinygettext { + +Log::log_callback_t Log::log_info_callback = &Log::default_log_callback; +Log::log_callback_t Log::log_warning_callback = &Log::default_log_callback; +Log::log_callback_t Log::log_error_callback = &Log::default_log_callback; + +void +Log::default_log_callback(const std::string& str) +{ + std::cerr << "tinygettext: " << str; +} + +void +Log::set_log_info_callback(log_callback_t callback) +{ + log_info_callback = callback; +} + +void +Log::set_log_warning_callback(log_callback_t callback) +{ + log_warning_callback = callback; +} + +void +Log::set_log_error_callback(log_callback_t callback) +{ + log_error_callback = callback; +} + +Log::Log(log_callback_t callback_) : + callback(callback_), + out() +{ +} + +Log::~Log() +{ + callback(out.str()); +} + +std::ostream& +Log::get() +{ + return out; +} + +} // namespace tinygettext + +/* EOF */ diff --git a/external/tinygettext/tinygettext/log.hpp b/external/tinygettext/tinygettext/log.hpp new file mode 100644 index 00000000000..a8eadb461f5 --- /dev/null +++ b/external/tinygettext/tinygettext/log.hpp @@ -0,0 +1,56 @@ +// tinygettext - A gettext replacement that works directly on .po files +// Copyright (C) 2009 Ingo Ruhnke +// +// 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 + +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 index 00000000000..8ad4c022d67 --- /dev/null +++ b/external/tinygettext/tinygettext/log_stream.hpp @@ -0,0 +1,34 @@ +// tinygettext - A gettext replacement that works directly on .po files +// Copyright (C) 2009 Ingo Ruhnke +// +// 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 index 00000000000..8271437b7da --- /dev/null +++ b/external/tinygettext/tinygettext/plural_forms.cpp @@ -0,0 +1,89 @@ +// tinygettext - A gettext replacement that works directly on .po files +// Copyright (C) 2006 Ingo Ruhnke +// +// 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 + +namespace tinygettext { + +/** + * Plural functions are used to select a string that matches a given + * count. \a n is the count and the return value is the string index + * used in the .po file, for example: + * + * msgstr[0] = "You got %d error"; + * msgstr[1] = "You got %d errors"; + * ^-- return value of plural function + */ +unsigned int plural1(int ) { return 0; } +unsigned int plural2_1(int n) { return (n != 1); } +unsigned int plural2_2(int n) { return (n > 1); } +unsigned int plural2_mk(int n) { return n==1 || n%10==1 ? 0 : 1; } +unsigned int plural3_lv(int n) { return static_cast(n%10==1 && n%100!=11 ? 0 : n != 0 ? 1 : 2); } +unsigned int plural3_ga(int n) { return static_cast(n==1 ? 0 : n==2 ? 1 : 2); } +unsigned int plural3_lt(int n) { return static_cast(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(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( (n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2 ); } +unsigned int plural3_pl(int n) { return static_cast(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(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( n==1 ? 0 : n==2 ? 1 : n>=3 && n<=10 ? 2 : 3 ); } + +PluralForms +PluralForms::from_string(const std::string& str) +{ + static std::map 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::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 index 00000000000..0b064494b9b --- /dev/null +++ b/external/tinygettext/tinygettext/plural_forms.hpp @@ -0,0 +1,61 @@ +// tinygettext - A gettext replacement that works directly on .po files +// Copyright (C) 2006 Ingo Ruhnke +// +// 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 + +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 index 00000000000..5ceb3fd2635 --- /dev/null +++ b/external/tinygettext/tinygettext/po_parser.cpp @@ -0,0 +1,496 @@ +// tinygettext - A gettext replacement that works directly on .po files +// Copyright (C) 2009 Ingo Ruhnke +// +// 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 +#include +#include +#include +#include +#include +#include + +#include "language.hpp" +#include "log_stream.hpp" +#include "iconv.hpp" +#include "dictionary.hpp" +#include "plural_forms.hpp" + +namespace tinygettext { + +bool POParser::pedantic = true; + +void +POParser::parse(const std::string& filename, std::istream& in, Dictionary& dict) +{ + POParser parser(filename, in, dict); + parser.parse(); +} + +class POParserError {}; + +POParser::POParser(const std::string& filename_, std::istream& in_, Dictionary& dict_, bool use_fuzzy_) : + filename(filename_), + in(in_), + dict(dict_), + use_fuzzy(use_fuzzy_), + running(false), + eof(false), + big5(false), + line_number(0), + current_line(), + conv() +{ +} + +POParser::~POParser() +{ +} + +void +POParser::warning(const std::string& msg) +{ + log_warning << filename << ":" << line_number << ": warning: " << msg << ": " << current_line << std::endl; + //log_warning << "Line: " << current_line << std::endl; +} + +void +POParser::error(const std::string& msg) +{ + log_error << filename << ":" << line_number << ": error: " << msg << ": " << current_line << std::endl; + + // Try to recover from an error by searching for start of another entry + do + next_line(); + while(!eof && !is_empty_line()); + + throw POParserError(); +} + +void +POParser::next_line() +{ + line_number += 1; + if (!std::getline(in, current_line)) + eof = true; +} + +void +POParser::get_string_line(std::ostringstream& out,unsigned int skip) +{ + if (skip+1 >= static_cast(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(current_line[i]) >= 0x81 && static_cast(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(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(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(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(0xef) && + current_line[1] == static_cast(0xbb) && + current_line[2] == static_cast(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 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(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::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 index 00000000000..329af591324 --- /dev/null +++ b/external/tinygettext/tinygettext/po_parser.hpp @@ -0,0 +1,75 @@ +// tinygettext - A gettext replacement that works directly on .po files +// Copyright (C) 2009 Ingo Ruhnke +// +// 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 + +#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 index 00000000000..7f5adc8aef5 --- /dev/null +++ b/external/tinygettext/tinygettext/tinygettext.cpp @@ -0,0 +1,22 @@ +// tinygettext - A gettext replacement that works directly on .po files +// Copyright (C) 2006 Ingo Ruhnke +// +// 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 index 00000000000..19fd4c657b0 --- /dev/null +++ b/external/tinygettext/tinygettext/tinygettext.hpp @@ -0,0 +1,27 @@ +// tinygettext - A gettext replacement that works directly on .po files +// Copyright (C) 2006 Ingo Ruhnke +// +// 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 index 00000000000..5e14d17f14c --- /dev/null +++ b/external/tinygettext/tinygettext/unix_file_system.cpp @@ -0,0 +1,65 @@ +// tinygettext - A gettext replacement that works directly on .po files +// Copyright (C) 2009 Ingo Ruhnke +// +// 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 +#include +#include +#include +#include +#include + +namespace tinygettext { + +UnixFileSystem::UnixFileSystem() +{ +} + +std::vector +UnixFileSystem::open_directory(const std::string& pathname) +{ + DIR* dir = opendir(pathname.c_str()); + if (!dir) + { + // FIXME: error handling + return std::vector(); + } + else + { + std::vector files; + + struct dirent* dp; + while((dp = readdir(dir)) != 0) + { + files.push_back(dp->d_name); + } + closedir(dir); + + return files; + } +} + +std::auto_ptr +UnixFileSystem::open_file(const std::string& filename) +{ + return std::auto_ptr(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 index 00000000000..80f3e6db4f4 --- /dev/null +++ b/external/tinygettext/tinygettext/unix_file_system.hpp @@ -0,0 +1,38 @@ +// tinygettext - A gettext replacement that works directly on .po files +// Copyright (C) 2009 Ingo Ruhnke +// +// 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 open_directory(const std::string& pathname); + std::auto_ptr open_file(const std::string& filename); +}; + +} // namespace tinygettext + +#endif + +/* EOF */