Ticket #67: engine-i18n.patch

File engine-i18n.patch, 248.6 KB (added by Adrián Chaves, 11 years ago)

Engine internationalization (patch 1/3)

  • build/premake/extern_libs4.lua

    diff --git a/build/premake/extern_libs4.lua b/build/premake/extern_libs4.lua
    index 6101b5e..a336f74 100644
    a b extern_lib_defs = {  
    343343            })
    344344        end,
    345345    },
     346    icu = {
     347        compile_settings = function()
     348            if os.is("windows") then
     349                add_default_include_paths("u")
     350            end
     351        end,
     352        link_settings = function()
     353            if os.is("windows") then
     354                add_default_lib_paths("icu")
     355            end
     356            add_default_links({
     357                win_names  = { "icu" },
     358                unix_names = { "icui18n", "icuuc" },
     359            })
     360        end,
     361    },
    346362    libcurl = {
    347363        compile_settings = function()
    348364            if os.is("windows") then
    extern_lib_defs = {  
    567583            end
    568584        end,
    569585    },
     586    tinygettext = {
     587        compile_settings = function()
     588            includedirs { libraries_source_dir .. "tinygettext" }
     589        end,
     590        link_settings = function()
     591            add_source_lib_paths("tinygettext")
     592            add_default_links({
     593                win_names  = { "tinygettext" },
     594                unix_names = { "tinygettext" },
     595            })
     596        end,
     597    },
    570598    valgrind = {
    571599        compile_settings = function()
    572600            add_source_include_paths("valgrind")
  • build/premake/premake4.lua

    diff --git a/build/premake/premake4.lua b/build/premake/premake4.lua
    index a7336da..f232d3a 100644
    a b function setup_all_libs ()  
    591591        "scripting",
    592592        "maths",
    593593        "maths/scripting",
     594        "i18n"
    594595    }
    595596    extern_libs = {
    596597        "spidermonkey",
    function setup_all_libs ()  
    600601        "zlib",
    601602        "boost",
    602603        "enet",
    603         "libcurl"
     604        "libcurl",
     605        "tinygettext",
     606        "icu",
    604607    }
    605608   
    606609    if not _OPTIONS["without-audio"] then
    function setup_all_libs ()  
    644647
    645648    source_dirs = {
    646649        "gui",
    647         "gui/scripting"
     650        "gui/scripting",
     651        "i18n"
    648652    }
    649653    extern_libs = {
    650654        "spidermonkey",
    651655        "sdl",  -- key definitions
    652656        "opengl",
    653         "boost"
     657        "boost",
     658        "tinygettext",
     659        "icu",
    654660    }
    655661    setup_static_lib_project("gui", source_dirs, extern_libs, {})
    656662
    used_extern_libs = {  
    772778    "comsuppw",
    773779    "enet",
    774780    "libcurl",
     781    "tinygettext",
     782    "icu",
    775783
    776784    "valgrind",
    777785}
  • libraries/LICENSE.txt

    diff --git a/libraries/LICENSE.txt b/libraries/LICENSE.txt
    index 58654d2..c39cfd6 100644
    a b win32/ contains headers and precompiled static libs for Windows builds.  
    2323  source/spidermonkey
    2424    MPL / GPL / LGPL
    2525
     26  source/tinygettext
     27    GPLv2
     28
    2629  source/valgrind
    2730    BSD
    2831
  • new file libraries/source/tinygettext/CMakeLists.txt

    diff --git a/libraries/source/tinygettext/CMakeLists.txt b/libraries/source/tinygettext/CMakeLists.txt
    new file mode 100644
    index 0000000..6c1d78b
    - +  
     1#
     2# TinyGetText build script
     3# Copyright (C) 2006 Christoph Sommer <christoph.sommer@2006.expires.deltadevelopment.de>
     4#
     5# This program is free software; you can redistribute it and/or modify
     6# it under the terms of the GNU General Public License as published by
     7# the Free Software Foundation; either version 2 of the License, or
     8# (at your option) any later version.
     9#
     10# This program is distributed in the hope that it will be useful,
     11# but WITHOUT ANY WARRANTY; without even the implied warranty of
     12# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     13# GNU General Public License for more details.
     14#
     15# You should have received a copy of the GNU General Public License
     16# along with this program; if not, write to the Free Software
     17# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
     18#
     19
     20
     21#
     22# INSTRUCTIONS:
     23# -------------
     24#
     25# Create a directory build/ and change to it. Run
     26#
     27#   cmake ..
     28#
     29# This creates a set of Makefiles to build the project. Run
     30#
     31#   make
     32#
     33
     34
     35CMAKE_POLICY(SET CMP0005 NEW)
     36
     37## Project name to use as command prefix
     38
     39PROJECT(tinygettext)
     40SET(VERSION "0.1")
     41
     42### CMake configuration
     43
     44CMAKE_MINIMUM_REQUIRED(VERSION 2.4)
     45IF(COMMAND cmake_policy)
     46    CMAKE_POLICY(SET CMP0003 NEW)
     47ENDIF(COMMAND cmake_policy)
     48SET(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${tinygettext_SOURCE_DIR})
     49
     50# move some config clutter to the advanced section
     51MARK_AS_ADVANCED(
     52    CMAKE_BACKWARDS_COMPATIBILITY
     53    CMAKE_BUILD_TYPE
     54    CMAKE_INSTALL_PREFIX
     55    EXECUTABLE_OUTPUT_PATH
     56    CMAKE_OSX_ARCHITECTURES
     57    CMAKE_OSX_SYSROOT
     58)
     59
     60## Reveal library type choice to users
     61OPTION(BUILD_SHARED_LIBS "Produce dynamic library instead of static archive" ON)
     62
     63## Add iconv to include directories
     64
     65FIND_PACKAGE(ICONV REQUIRED)
     66INCLUDE_DIRECTORIES(${ICONV_INCLUDE_DIR})
     67
     68## Check iconv_const
     69
     70INCLUDE(CheckCXXSourceCompiles)
     71
     72SET(CMAKE_REQUIRED_INCLUDES ${CMAKE_REQUIRED_INCLUDES} ${ICONV_INCLUDE_DIR})
     73CHECK_CXX_SOURCE_COMPILES(
     74    "
     75    #include <iconv.h>
     76    // this declaration will fail when there already exists a non const char** version which returns size_t
     77    double iconv(iconv_t cd,  char **inbuf, size_t *inbytesleft, char **outbuf, size_t *outbytesleft);
     78    int main() { return 0; }
     79    "
     80    HAVE_ICONV_CONST
     81)
     82
     83# TODO: better way of config
     84
     85IF(HAVE_ICONV_CONST)
     86  ADD_DEFINITIONS(-DHAVE_ICONV_CONST)
     87ELSE(HAVE_ICONV_CONST)
     88  REMOVE_DEFINITIONS(-DHAVE_ICONV_CONST)
     89ENDIF(HAVE_ICONV_CONST)
     90
     91## TinyGetText library compilation
     92
     93## build list of source files
     94
     95FILE(GLOB TINYGETTEXT_SOURCES RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} tinygettext/*.cpp)
     96FILE(GLOB TINYGETTEXT_HEADERS RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} tinygettext/*.hpp)
     97
     98## define a target for building the library
     99
     100ADD_LIBRARY(tinygettext ${TINYGETTEXT_SOURCES})
     101
     102## Add tinygettext dir to search path
     103
     104INCLUDE_DIRECTORIES(${tinygettext_SOURCE_DIR})
     105
     106## Debug options
     107
     108OPTION(WERROR "Stops on first compiler warning in debug mode" OFF)
     109IF(CMAKE_COMPILER_IS_GNUCC)
     110  ADD_DEFINITIONS(-O3 -Wall -Wextra -Weffc++ -pedantic)
     111  # -ansi fails in MinGW
     112  OPTION(WARNINGS "Enable long list of warnings for compiler to check" ON)
     113  IF(WARNINGS)
     114    ADD_DEFINITIONS(
     115          -Wabi  -Wctor-dtor-privacy
     116          -Wstrict-null-sentinel
     117          -Wold-style-cast
     118          -Woverloaded-virtual
     119          -Wsign-promo -Wswitch-enum
     120          -Wcast-align  -Wcast-qual
     121          -Wdisabled-optimization
     122          -Wfloat-equal 
     123          -Wformat=2
     124          -Winit-self
     125          -Winvalid-pch  -Wunsafe-loop-optimizations
     126          -Wlogical-op
     127          -Wmissing-format-attribute  -Wmissing-include-dirs -Wmissing-noreturn
     128          -Wpacked
     129          -Wredundant-decls
     130          -Wshadow
     131          -Wsign-conversion  -Wstack-protector
     132          -Wstrict-overflow=5
     133          -Wswitch-default  -Wswitch-enum
     134          -Wundef)
     135        # Still left:
     136        # -Wconversion  (find alternative to using toupper(int) on char)
     137        # -Wpadded      (DictionaryManager has a bool that sticks out)
     138  ENDIF(WARNINGS)
     139  IF(WERROR)
     140    ADD_DEFINITIONS(-Werror)
     141  ENDIF(WERROR)
     142ENDIF(CMAKE_COMPILER_IS_GNUCC)
     143
     144## Extra definitions
     145
     146ADD_DEFINITIONS(-DVERSION=\\\"${VERSION}\\\")
     147
     148## Generate test executables in the right place
     149
     150SET(EXECUTABLE_OUTPUT_PATH ${tinygettext_BINARY_DIR}/test)
     151
     152## Build tinygettext tests
     153
     154FOREACH(TEST tinygettext_test po_parser_test)
     155  ## Add target for tinygettext test
     156  ADD_EXECUTABLE(${TEST} test/${TEST}.cpp)
     157  ## Link with tinygettext library
     158  TARGET_LINK_LIBRARIES(${TEST} tinygettext)
     159  TARGET_LINK_LIBRARIES(${TEST} ${ICONV_LIBRARY})
     160ENDFOREACH(TEST)
     161
     162## Install tinygettext
     163
     164# use standardized variable name
     165SET(LIB_SUBDIR "lib${LIB_SUFFIX}"
     166    CACHE STRING "Subdirectory of prefix into which libraries are installed (e.g., lib32, lib64)")
     167
     168## prepare tinygettext.pc
     169CONFIGURE_FILE(tinygettext.pc.in tinygettext.pc @ONLY)
     170
     171INSTALL(TARGETS tinygettext
     172    ARCHIVE DESTINATION ${LIB_SUBDIR}
     173    LIBRARY DESTINATION ${LIB_SUBDIR})
     174INSTALL(FILES ${TINYGETTEXT_HEADERS}
     175    DESTINATION include/tinygettext)
     176INSTALL(FILES ${tinygettext_BINARY_DIR}/tinygettext.pc
     177    DESTINATION ${LIB_SUBDIR}/pkgconfig)
  • new file libraries/source/tinygettext/COPYING

    diff --git a/libraries/source/tinygettext/COPYING b/libraries/source/tinygettext/COPYING
    new file mode 100644
    index 0000000..c45fcd8
    - +  
     1                    GNU GENERAL PUBLIC LICENSE
     2                       Version 2, June 1991
     3
     4 Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
     5 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
     6 Everyone is permitted to copy and distribute verbatim copies
     7 of this license document, but changing it is not allowed.
     8
     9                            Preamble
     10
     11  The licenses for most software are designed to take away your
     12freedom to share and change it.  By contrast, the GNU General Public
     13License is intended to guarantee your freedom to share and change free
     14software--to make sure the software is free for all its users.  This
     15General Public License applies to most of the Free Software
     16Foundation's software and to any other program whose authors commit to
     17using it.  (Some other Free Software Foundation software is covered by
     18the GNU Lesser General Public License instead.)  You can apply it to
     19your programs, too.
     20
     21  When we speak of free software, we are referring to freedom, not
     22price.  Our General Public Licenses are designed to make sure that you
     23have the freedom to distribute copies of free software (and charge for
     24this service if you wish), that you receive source code or can get it
     25if you want it, that you can change the software or use pieces of it
     26in new free programs; and that you know you can do these things.
     27
     28  To protect your rights, we need to make restrictions that forbid
     29anyone to deny you these rights or to ask you to surrender the rights.
     30These restrictions translate to certain responsibilities for you if you
     31distribute copies of the software, or if you modify it.
     32
     33  For example, if you distribute copies of such a program, whether
     34gratis or for a fee, you must give the recipients all the rights that
     35you have.  You must make sure that they, too, receive or can get the
     36source code.  And you must show them these terms so they know their
     37rights.
     38
     39  We protect your rights with two steps: (1) copyright the software, and
     40(2) offer you this license which gives you legal permission to copy,
     41distribute and/or modify the software.
     42
     43  Also, for each author's protection and ours, we want to make certain
     44that everyone understands that there is no warranty for this free
     45software.  If the software is modified by someone else and passed on, we
     46want its recipients to know that what they have is not the original, so
     47that any problems introduced by others will not reflect on the original
     48authors' reputations.
     49
     50  Finally, any free program is threatened constantly by software
     51patents.  We wish to avoid the danger that redistributors of a free
     52program will individually obtain patent licenses, in effect making the
     53program proprietary.  To prevent this, we have made it clear that any
     54patent must be licensed for everyone's free use or not licensed at all.
     55
     56  The precise terms and conditions for copying, distribution and
     57modification follow.
     58
     59                    GNU GENERAL PUBLIC LICENSE
     60   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
     61
     62  0. This License applies to any program or other work which contains
     63a notice placed by the copyright holder saying it may be distributed
     64under the terms of this General Public License.  The "Program", below,
     65refers to any such program or work, and a "work based on the Program"
     66means either the Program or any derivative work under copyright law:
     67that is to say, a work containing the Program or a portion of it,
     68either verbatim or with modifications and/or translated into another
     69language.  (Hereinafter, translation is included without limitation in
     70the term "modification".)  Each licensee is addressed as "you".
     71
     72Activities other than copying, distribution and modification are not
     73covered by this License; they are outside its scope.  The act of
     74running the Program is not restricted, and the output from the Program
     75is covered only if its contents constitute a work based on the
     76Program (independent of having been made by running the Program).
     77Whether that is true depends on what the Program does.
     78
     79  1. You may copy and distribute verbatim copies of the Program's
     80source code as you receive it, in any medium, provided that you
     81conspicuously and appropriately publish on each copy an appropriate
     82copyright notice and disclaimer of warranty; keep intact all the
     83notices that refer to this License and to the absence of any warranty;
     84and give any other recipients of the Program a copy of this License
     85along with the Program.
     86
     87You may charge a fee for the physical act of transferring a copy, and
     88you may at your option offer warranty protection in exchange for a fee.
     89
     90  2. You may modify your copy or copies of the Program or any portion
     91of it, thus forming a work based on the Program, and copy and
     92distribute such modifications or work under the terms of Section 1
     93above, provided that you also meet all of these conditions:
     94
     95    a) You must cause the modified files to carry prominent notices
     96    stating that you changed the files and the date of any change.
     97
     98    b) You must cause any work that you distribute or publish, that in
     99    whole or in part contains or is derived from the Program or any
     100    part thereof, to be licensed as a whole at no charge to all third
     101    parties under the terms of this License.
     102
     103    c) If the modified program normally reads commands interactively
     104    when run, you must cause it, when started running for such
     105    interactive use in the most ordinary way, to print or display an
     106    announcement including an appropriate copyright notice and a
     107    notice that there is no warranty (or else, saying that you provide
     108    a warranty) and that users may redistribute the program under
     109    these conditions, and telling the user how to view a copy of this
     110    License.  (Exception: if the Program itself is interactive but
     111    does not normally print such an announcement, your work based on
     112    the Program is not required to print an announcement.)
     113
     114These requirements apply to the modified work as a whole.  If
     115identifiable sections of that work are not derived from the Program,
     116and can be reasonably considered independent and separate works in
     117themselves, then this License, and its terms, do not apply to those
     118sections when you distribute them as separate works.  But when you
     119distribute the same sections as part of a whole which is a work based
     120on the Program, the distribution of the whole must be on the terms of
     121this License, whose permissions for other licensees extend to the
     122entire whole, and thus to each and every part regardless of who wrote it.
     123
     124Thus, it is not the intent of this section to claim rights or contest
     125your rights to work written entirely by you; rather, the intent is to
     126exercise the right to control the distribution of derivative or
     127collective works based on the Program.
     128
     129In addition, mere aggregation of another work not based on the Program
     130with the Program (or with a work based on the Program) on a volume of
     131a storage or distribution medium does not bring the other work under
     132the scope of this License.
     133
     134  3. You may copy and distribute the Program (or a work based on it,
     135under Section 2) in object code or executable form under the terms of
     136Sections 1 and 2 above provided that you also do one of the following:
     137
     138    a) Accompany it with the complete corresponding machine-readable
     139    source code, which must be distributed under the terms of Sections
     140    1 and 2 above on a medium customarily used for software interchange; or,
     141
     142    b) Accompany it with a written offer, valid for at least three
     143    years, to give any third party, for a charge no more than your
     144    cost of physically performing source distribution, a complete
     145    machine-readable copy of the corresponding source code, to be
     146    distributed under the terms of Sections 1 and 2 above on a medium
     147    customarily used for software interchange; or,
     148
     149    c) Accompany it with the information you received as to the offer
     150    to distribute corresponding source code.  (This alternative is
     151    allowed only for noncommercial distribution and only if you
     152    received the program in object code or executable form with such
     153    an offer, in accord with Subsection b above.)
     154
     155The source code for a work means the preferred form of the work for
     156making modifications to it.  For an executable work, complete source
     157code means all the source code for all modules it contains, plus any
     158associated interface definition files, plus the scripts used to
     159control compilation and installation of the executable.  However, as a
     160special exception, the source code distributed need not include
     161anything that is normally distributed (in either source or binary
     162form) with the major components (compiler, kernel, and so on) of the
     163operating system on which the executable runs, unless that component
     164itself accompanies the executable.
     165
     166If distribution of executable or object code is made by offering
     167access to copy from a designated place, then offering equivalent
     168access to copy the source code from the same place counts as
     169distribution of the source code, even though third parties are not
     170compelled to copy the source along with the object code.
     171
     172  4. You may not copy, modify, sublicense, or distribute the Program
     173except as expressly provided under this License.  Any attempt
     174otherwise to copy, modify, sublicense or distribute the Program is
     175void, and will automatically terminate your rights under this License.
     176However, parties who have received copies, or rights, from you under
     177this License will not have their licenses terminated so long as such
     178parties remain in full compliance.
     179
     180  5. You are not required to accept this License, since you have not
     181signed it.  However, nothing else grants you permission to modify or
     182distribute the Program or its derivative works.  These actions are
     183prohibited by law if you do not accept this License.  Therefore, by
     184modifying or distributing the Program (or any work based on the
     185Program), you indicate your acceptance of this License to do so, and
     186all its terms and conditions for copying, distributing or modifying
     187the Program or works based on it.
     188
     189  6. Each time you redistribute the Program (or any work based on the
     190Program), the recipient automatically receives a license from the
     191original licensor to copy, distribute or modify the Program subject to
     192these terms and conditions.  You may not impose any further
     193restrictions on the recipients' exercise of the rights granted herein.
     194You are not responsible for enforcing compliance by third parties to
     195this License.
     196
     197  7. If, as a consequence of a court judgment or allegation of patent
     198infringement or for any other reason (not limited to patent issues),
     199conditions are imposed on you (whether by court order, agreement or
     200otherwise) that contradict the conditions of this License, they do not
     201excuse you from the conditions of this License.  If you cannot
     202distribute so as to satisfy simultaneously your obligations under this
     203License and any other pertinent obligations, then as a consequence you
     204may not distribute the Program at all.  For example, if a patent
     205license would not permit royalty-free redistribution of the Program by
     206all those who receive copies directly or indirectly through you, then
     207the only way you could satisfy both it and this License would be to
     208refrain entirely from distribution of the Program.
     209
     210If any portion of this section is held invalid or unenforceable under
     211any particular circumstance, the balance of the section is intended to
     212apply and the section as a whole is intended to apply in other
     213circumstances.
     214
     215It is not the purpose of this section to induce you to infringe any
     216patents or other property right claims or to contest validity of any
     217such claims; this section has the sole purpose of protecting the
     218integrity of the free software distribution system, which is
     219implemented by public license practices.  Many people have made
     220generous contributions to the wide range of software distributed
     221through that system in reliance on consistent application of that
     222system; it is up to the author/donor to decide if he or she is willing
     223to distribute software through any other system and a licensee cannot
     224impose that choice.
     225
     226This section is intended to make thoroughly clear what is believed to
     227be a consequence of the rest of this License.
     228
     229  8. If the distribution and/or use of the Program is restricted in
     230certain countries either by patents or by copyrighted interfaces, the
     231original copyright holder who places the Program under this License
     232may add an explicit geographical distribution limitation excluding
     233those countries, so that distribution is permitted only in or among
     234countries not thus excluded.  In such case, this License incorporates
     235the limitation as if written in the body of this License.
     236
     237  9. The Free Software Foundation may publish revised and/or new versions
     238of the General Public License from time to time.  Such new versions will
     239be similar in spirit to the present version, but may differ in detail to
     240address new problems or concerns.
     241
     242Each version is given a distinguishing version number.  If the Program
     243specifies a version number of this License which applies to it and "any
     244later version", you have the option of following the terms and conditions
     245either of that version or of any later version published by the Free
     246Software Foundation.  If the Program does not specify a version number of
     247this License, you may choose any version ever published by the Free Software
     248Foundation.
     249
     250  10. If you wish to incorporate parts of the Program into other free
     251programs whose distribution conditions are different, write to the author
     252to ask for permission.  For software which is copyrighted by the Free
     253Software Foundation, write to the Free Software Foundation; we sometimes
     254make exceptions for this.  Our decision will be guided by the two goals
     255of preserving the free status of all derivatives of our free software and
     256of promoting the sharing and reuse of software generally.
     257
     258                            NO WARRANTY
     259
     260  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
     261FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
     262OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
     263PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
     264OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
     265MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
     266TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
     267PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
     268REPAIR OR CORRECTION.
     269
     270  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
     271WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
     272REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
     273INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
     274OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
     275TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
     276YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
     277PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
     278POSSIBILITY OF SUCH DAMAGES.
     279
     280                     END OF TERMS AND CONDITIONS
     281
     282            How to Apply These Terms to Your New Programs
     283
     284  If you develop a new program, and you want it to be of the greatest
     285possible use to the public, the best way to achieve this is to make it
     286free software which everyone can redistribute and change under these terms.
     287
     288  To do so, attach the following notices to the program.  It is safest
     289to attach them to the start of each source file to most effectively
     290convey the exclusion of warranty; and each file should have at least
     291the "copyright" line and a pointer to where the full notice is found.
     292
     293    tinygettext - A gettext replacement that works directly on .po files
     294    Copyright (C) 2006 Ingo Ruhnke <grumbel@gmx.de>
     295
     296    This program is free software; you can redistribute it and/or modify
     297    it under the terms of the GNU General Public License as published by
     298    the Free Software Foundation; either version 2 of the License, or
     299    (at your option) any later version.
     300
     301    This program is distributed in the hope that it will be useful,
     302    but WITHOUT ANY WARRANTY; without even the implied warranty of
     303    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     304    GNU General Public License for more details.
     305
     306    You should have received a copy of the GNU General Public License along
     307    with this program; if not, write to the Free Software Foundation, Inc.,
     308    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
     309
     310Also add information on how to contact you by electronic and paper mail.
     311
     312If the program is interactive, make it output a short notice like this
     313when it starts in an interactive mode:
     314
     315    Gnomovision version 69, Copyright (C) year name of author
     316    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
     317    This is free software, and you are welcome to redistribute it
     318    under certain conditions; type `show c' for details.
     319
     320The hypothetical commands `show w' and `show c' should show the appropriate
     321parts of the General Public License.  Of course, the commands you use may
     322be called something other than `show w' and `show c'; they could even be
     323mouse-clicks or menu items--whatever suits your program.
     324
     325You should also get your employer (if you work as a programmer) or your
     326school, if any, to sign a "copyright disclaimer" for the program, if
     327necessary.  Here is a sample; alter the names:
     328
     329  Yoyodyne, Inc., hereby disclaims all copyright interest in the program
     330  `Gnomovision' (which makes passes at compilers) written by James Hacker.
     331
     332  <signature of Ty Coon>, 1 April 1989
     333  Ty Coon, President of Vice
     334
     335This General Public License does not permit incorporating your program into
     336proprietary programs.  If your program is a subroutine library, you may
     337consider it more useful to permit linking proprietary applications with the
     338library.  If this is what you want to do, use the GNU Lesser General
     339Public License instead of this License.
  • new file libraries/source/tinygettext/FindICONV.cmake

    diff --git a/libraries/source/tinygettext/FindICONV.cmake b/libraries/source/tinygettext/FindICONV.cmake
    new file mode 100644
    index 0000000..0ac82b7
    - +  
     1#
     2#  Copyright (c) 2006, Peter Kümmel, <syntheticpp@gmx.net>
     3#
     4#  Redistribution and use in source and binary forms, with or without
     5#  modification, are permitted provided that the following conditions
     6#  are met:
     7
     8#  1. Redistributions of source code must retain the copyright
     9#     notice, this list of conditions and the following disclaimer.
     10#  2. Redistributions in binary form must reproduce the copyright
     11#     notice, this list of conditions and the following disclaimer in the
     12#     documentation and/or other materials provided with the distribution.
     13#  3. The name of the author may not be used to endorse or promote products
     14#     derived from this software without specific prior written permission.
     15
     16#  THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
     17#  IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
     18#  OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
     19#  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
     20#  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
     21#  NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     22#  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     23#  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     24#  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
     25#  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     26
     27
     28set(CMAKE_ALLOW_LOOSE_LOOP_CONSTRUCTS true)
     29
     30if (ICONV_INCLUDE_DIR)
     31  # Already in cache, be silent
     32  set(ICONV_FIND_QUIETLY TRUE)
     33endif()
     34
     35find_path(ICONV_INCLUDE_DIR iconv.h
     36 /usr/include
     37 /usr/local/include)
     38
     39set(POTENTIAL_ICONV_LIBS iconv libiconv libiconv2)
     40
     41find_library(ICONV_LIBRARY NAMES ${POTENTIAL_ICONV_LIBS}
     42    PATHS /usr/lib /usr/local/lib)
     43
     44if(WIN32)
     45    set(ICONV_DLL_NAMES iconv.dll  libiconv.dll libiconv2.dll)
     46    find_file(ICONV_DLL   
     47                    NAMES ${ICONV_DLL_NAMES}
     48                    PATHS ENV PATH
     49                    NO_DEFAULT_PATH)
     50    find_file(ICONV_DLL_HELP   
     51                    NAMES ${ICONV_DLL_NAMES}
     52                    PATHS ENV PATH
     53                    ${ICONV_INCLUDE_DIR}/../bin)
     54    if(ICONV_FIND_REQUIRED)
     55        if(NOT ICONV_DLL AND NOT ICONV_DLL_HELP)
     56            message(FATAL_ERROR "Could not find iconv.dll, please add correct your PATH environment variable")
     57        endif()
     58        if(NOT ICONV_DLL AND ICONV_DLL_HELP)
     59            get_filename_component(ICONV_DLL_HELP ${ICONV_DLL_HELP} PATH)
     60            message(STATUS)
     61            message(STATUS "Could not find iconv.dll in standard search path, please add ")
     62            message(STATUS "${ICONV_DLL_HELP}")
     63            message(STATUS "to your PATH environment variable.")
     64            message(STATUS)
     65            message(FATAL_ERROR "exit cmake")
     66        endif()
     67    endif()
     68    if(ICONV_INCLUDE_DIR AND ICONV_LIBRARY AND ICONV_DLL)
     69        set(ICONV_FOUND TRUE)
     70    endif()
     71else()
     72    include(CheckFunctionExists)
     73    check_function_exists(iconv HAVE_ICONV_IN_LIBC)
     74    if(ICONV_INCLUDE_DIR AND HAVE_ICONV_IN_LIBC)
     75        set(ICONV_FOUND TRUE)
     76        set(ICONV_LIBRARY  CACHE TYPE STRING FORCE)
     77    endif()
     78    if(ICONV_INCLUDE_DIR AND ICONV_LIBRARY)
     79        set(ICONV_FOUND TRUE)
     80    endif()
     81endif()
     82
     83
     84
     85if(ICONV_FOUND)
     86   if(NOT ICONV_FIND_QUIETLY)
     87      message(STATUS "Found iconv library: ${ICONV_LIBRARY}")
     88      #message(STATUS "Found iconv   dll  : ${ICONV_DLL}")
     89   endif()
     90else()
     91   if(ICONV_FIND_REQUIRED)
     92      message(STATUS "Looked for iconv library named ${POTENTIAL_ICONV_LIBS}.")
     93      message(STATUS "Found no acceptable iconv library. This is fatal.")
     94      message(STATUS "iconv header: ${ICONV_INCLUDE_DIR}")
     95      message(STATUS "iconv lib   : ${ICONV_LIBRARY}")
     96      message(FATAL_ERROR "Could NOT find iconv library")
     97   endif()
     98endif()
     99
     100mark_as_advanced(ICONV_LIBRARY ICONV_INCLUDE_DIR)
  • new file libraries/source/tinygettext/NEWS

    diff --git a/libraries/source/tinygettext/NEWS b/libraries/source/tinygettext/NEWS
    new file mode 100644
    index 0000000..fcf6ef6
    - +  
     1tinygettext 0.0.1 - (??. Feb 2009)
     2==================================
     3
     4* initial release
     5
     6# EOF #
  • new file libraries/source/tinygettext/README

    diff --git a/libraries/source/tinygettext/README b/libraries/source/tinygettext/README
    new file mode 100644
    index 0000000..0eeabe9
    - +  
     1tinygettext
     2===========
     3
     4tinygettext is a minimal gettext() replacement written in C++. It can
     5read .po files directly and doesn't need .mo files generated from .po.
     6It also can read the .po files from arbitary locations, so its much
     7better suited for non-Unix systems and situations in which one wants
     8to store or distrubite .po files seperatly from the software itself.
     9
     10
     11
     12Detecting the locale setting
     13============================
     14
     15Different operating systems store the default locale in different
     16places; a portable way to find it is provided by FindLocale:
     17
     18 * http://icculus.org/~aspirin/findlocale/
     19
     20
     21# EOF #
  • new file libraries/source/tinygettext/SConstruct

    diff --git a/libraries/source/tinygettext/SConstruct b/libraries/source/tinygettext/SConstruct
    new file mode 100644
    index 0000000..cc5f9ec
    - +  
     1# -*- python -*-
     2
     3env = Environment(CXXFLAGS=['-O0',
     4                            '-g3',
     5                            '-Wall',
     6                            '-Wcast-qual',
     7                            '-Wconversion',
     8                            '-Weffc++',
     9                            '-Werror',
     10                            '-Wextra',
     11                            '-Winit-self',
     12                            '-Wno-unused-parameter',
     13                            '-Wnon-virtual-dtor',
     14                            '-Wshadow',
     15                            '-ansi',
     16                            '-pedantic',
     17                            ],
     18                  CPPPATH=['tinygettext', '.'])
     19
     20# env.ParseConfig("sdl-config --cflags --libs")
     21# env['CPPDEFINES'] += HAVE_SDL
     22
     23libtinygettext = env.SharedLibrary('tinygettext/tinygettext',
     24                                   ['tinygettext/tinygettext.cpp',
     25                                    'tinygettext/language.cpp',
     26                                    'tinygettext/plural_forms.cpp',
     27                                    'tinygettext/dictionary.cpp',
     28                                    'tinygettext/dictionary_manager.cpp',
     29                                    'tinygettext/unix_file_system.cpp',
     30                                    'tinygettext/po_parser.cpp',
     31                                    'tinygettext/iconv.cpp',
     32                                    'tinygettext/log.cpp'])
     33
     34env.Program('test/tinygettext_test', ['test/tinygettext_test.cpp', libtinygettext])
     35env.Program('test/po_parser_test', ['test/po_parser_test.cpp', libtinygettext])
     36
     37# EOF #
  • new file libraries/source/tinygettext/TODO

    diff --git a/libraries/source/tinygettext/TODO b/libraries/source/tinygettext/TODO
    new file mode 100644
    index 0000000..29daf3f
    - +  
     1tinygettext API related stuff:
     2==============================
     3
     4* translate, translate_ctxt, translate_ctxt_plural, ... could be
     5  unified via overloading, not sure if that is a good idea. For the
     6  same reason add_translation() could be de-overloaded, to
     7  add_translation_ctxt, ...
     8
     9* iconv handling needs cleanup and more flexibility, since some
     10  systems don't provide iconv or only through SDL
     11
     12* Customizability could use grouping and documentation or other means
     13  to make it more obvious:
     14
     15  - POParser::pedantic
     16  - iconv (???)
     17  - logging (log_callback(std::string))
     18
     19* handle errors better, not with log_* stream, cases of errors:
     20
     21  - couldn't translate
     22  - collision while adding translation
     23  - failure to open file or directory
     24  - unknown language
     25  - iconv failure to convert charset
     26
     27* ABI management/freezing. If tinygettext is to benefit other projects,
     28  it should be able to provide a stable API (and, better, ABI).
     29
     30
     31tinygettext implementation details:
     32===================================
     33
     34* with PluralForms moved into Dictionary a lot of the Langugae stuff
     35  is pointless
     36
     37* get rid of goto
     38
     39* POParser can handle Big5, but needs testing.
     40  Big5 is one byte for ASCII letters and two bytes for chinese ones,
     41  this means some two byte characters collide with '\', some .po files
     42  seem to escape the \ properly so that the string can be read as
     43  usual, while others don't.
     44
     45* _()  -> getext() (gettext default)
     46  N_(id) -> gettext_noop(id) (gettext default)
     47  C_(ctxt, id) -> pgettext(ctxt, id) (Gnome does this: http://library.gnome.org/devel/glib/2.16/glib-I18N.html#Q-:CAPS)
     48  NC_(ctxt, id) -> pgettext(ctxt, id) (Gnome does this: http://library.gnome.org/devel/glib/2.16/glib-I18N.html#Q-:CAPS)
     49
     50* figure out how up-to-date other tinygettext implementations in the
     51  wild are (LinCity):
     52
     53  Pingus:
     54  -------
     55  dictionary.hpp (synced with Pingus)
     56  dictionary_manager.hpp (PhysFS vs opendir())
     57  language_def.hpp (synced with Pingus)
     58  po_file_reader.hpp (UTF-8 0xef-'header', lots of stuff from mathner)
     59  tinygettext.hpp (iconv vs convert)
     60
     61
    062
     63Random Unimportant Stuff
     64========================
     65
     66* a hashmap instead of std::map might be a good idea
     67
     68* support for .gmo files would be cool
     69
    170
     71tinygettext Documentation:
     72==========================
     73
     74* recommend a way to handle translation of speech and other data files
     75
     76* document how to use tinygettext and make it work like gettext
  • new file libraries/source/tinygettext/build.sh

    +
    
    +# EOF #
    diff --git a/libraries/source/tinygettext/build.sh b/libraries/source/tinygettext/build.sh
    new file mode 100755
    index 0000000..1f9f99b
    - +  
     1#!/bin/sh
     2
     3set -e
     4
     5JOBS=${JOBS:="-j2"}
     6
     7echo "Building TinyGettext…"
     8echo
     9
     10scons ${JOBS}
     11
     12mkdir -p lib/
     13
     14if [ "`uname -s`" = "Darwin" ]
     15then
     16  extension=dylib
     17else
     18  extension=so
     19fi
     20
     21filepath=tinygettext/libtinygettext.${extension}
     22cp $filepath lib/
     23cp $filepath ../../../binaries/system/
  • new file libraries/source/tinygettext/test/broken.po

    diff --git a/libraries/source/tinygettext/test/broken.po b/libraries/source/tinygettext/test/broken.po
    new file mode 100644
    index 0000000..c841a73
    - +  
     1# SOME DESCRIPTIVE TITLE.
     2# Copyright (C) YEAR Free Software Foundation, Inc.
     3# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
     4#
     5#, fuzzy
     6msgid ""
     7msgstr ""
     8"Project-Id-Version: PACKAGE VERSION\n"
     9"Report-Msgid-Bugs-To: \n"
     10"POT-Creation-Date: 2009-01-30 08:01+0100\n"
     11"PO-Revision-Date: 2009-01-30 08:39+0100\n"
     12"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
     13"Language-Team: LANGUAGE <LL@li.org>\n"
     14"MIME-Version: 1.0\n"
     15"Content-Type: text/plain; charset=UTF-8\n"
     16"Content-Transfer-Encoding: 8bit\n"
     17
     18#: helloworld.cpp:7
     19msgid "Short Hello World"
     20msgstr "kurzes Hallo Welt
     21
     22#: helloworld.cpp:8 helloworld.cpp:14
     23#, fuzzy
     24msgid "Hello World"
     25msgid_plural "Hello Worlds"
     26msgstr[0] "Hallo Welt (singular)"
     27msgstr[1] "Hallo Welt (plural)"
     28msgstr[10] "Hallo Welt (plural)"
     29
     30#: helloworld.cpp:10 helloworld.cpp:16
     31#, fuzzy
     32msgctxt ""
     33msgid "Hello World"
     34msgid_plural "Hello Worlds"
     35msgstr[0] Hallo Welt (singular) mit leerem Kontext"
     36msgstr[1] "Hallo Welt (plural) mit leerem Kontext"
     37
     38#: helloworld.cpp:11 helloworld.cpp:17
     39msgctxt "console"
     40msgid "Hello World"
     41msgid_plural "Hello Worlds"
     42msgstr[0]"Hallo Welt (singular) in der Console"
     43msgstr[1] "Hallo Welt (plural) in der Console"
     44
     45#: helloworld.cpp:13
     46msgid "gui"
     47msgid_plural "Hello World"
     48msgstr[0]   "Hallo Welt (singular)"
     49msgstr[1] "Hallo Welt (plural)"
     50
     51#: helloworld.cpp:18
     52#, fuzzy
     53msgctxt "gui"
     54msgid "Hello World"
     55msgid_plural "Hello Worlds"
     56msgstr[0] "Hallo Welt im GUI"
     57msgstr[1] "Hallo Welt (plural) im GUI"
  • new file libraries/source/tinygettext/test/game/de.po

    diff --git a/libraries/source/tinygettext/test/game/de.po b/libraries/source/tinygettext/test/game/de.po
    new file mode 100644
    index 0000000..a92db3b
    - +  
     1# SOME DESCRIPTIVE TITLE.
     2# Copyright (C) YEAR Free Software Foundation, Inc.
     3# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
     4#
     5msgid ""
     6msgstr ""
     7"Project-Id-Version: Pingus 0.6.0\n"
     8"Report-Msgid-Bugs-To: \n"
     9"POT-Creation-Date: 2004-04-09 18:37+0000\n"
     10"PO-Revision-Date: 2003-04-15 17:31+0200\n"
     11"Last-Translator: David Philippi <david@torangan.de>\n"
     12"Language-Team: David Philippi <david@torangan.de>, Ingo Ruhnke <grumbel@gmx."
     13"de>, Giray Devlet <giray@devlet.cc>\n"
     14"MIME-Version: 1.0\n"
     15"Content-Type: text/plain; charset=ISO-8859-1\n"
     16"Content-Transfer-Encoding: 8bit\n"
     17
     18#: src/actions/bridger.cxx:48 src/actions/bridger.cxx:232
     19#: src/pingu_enums.cxx:40
     20msgid "Bridger"
     21msgstr "Bridger"
     22
     23#: src/config.cxx:73
     24msgid "Couldn't open: "
     25msgstr "Datei oder Verzeichnis konnte nicht geöffnet werden: "
     26
     27#: src/config.cxx:172
     28msgid "Unexpected char: '"
     29msgstr "Unerwartetes Zeichen: '"
     30
     31#: src/config.cxx:206
     32msgid "Unexpected char '"
     33msgstr "Unerwartetes Zeichen: '"
     34
     35#: src/credits.cxx:48
     36msgid "-Idea"
     37msgstr "-Idee"
     38
     39#: src/credits.cxx:52
     40msgid "-Maintaining"
     41msgstr "-Verwaltung"
     42
     43#: src/credits.cxx:56
     44msgid "-Programming"
     45msgstr "-Programmierung"
     46
     47#: src/credits.cxx:62
     48msgid "-Porting (Win32)"
     49msgstr "-Portierung (Win32)"
     50
     51#: src/credits.cxx:70
     52msgid "-Gfx"
     53msgstr "-Grafiken"
     54
     55#: src/credits.cxx:82
     56msgid "-Music"
     57msgstr "-Musik"
     58
     59#: src/credits.cxx:88
     60msgid "-Level Design"
     61msgstr "-Level Design"
     62
     63#: src/credits.cxx:93
     64msgid "-Story"
     65msgstr "-Geschichte"
     66
     67#: src/credits.cxx:97
     68msgid "-Translation"
     69msgstr "-Übersetzung"
     70
     71#: src/credits.cxx:112
     72msgid "-Special"
     73msgstr "-Besonderen"
     74
     75#: src/credits.cxx:113
     76msgid "-Thanks to"
     77msgstr "-Dank an"
     78
     79#: src/credits.cxx:154
     80msgid "_And a very Special Thanks"
     81msgstr "_Und einen besonderen Dank"
     82
     83#: src/credits.cxx:155
     84msgid "_to all the people who"
     85msgstr "_an alle Leute die"
     86
     87#: src/credits.cxx:156
     88msgid "_contribute to"
     89msgstr "_an Freier Software"
     90
     91#: src/credits.cxx:157
     92msgid "_Free Software!"
     93msgstr "_mitarbeiten!"
     94
     95#: src/credits.cxx:163
     96msgid "_Thank you for"
     97msgstr "_Dankeschön fürs"
     98
     99#: src/credits.cxx:164
     100msgid "_playing!"
     101msgstr "_spielen!"
     102
     103#: src/editor/editor_event.cxx:588
     104msgid "Enter filename to save as:"
     105msgstr "Datei speichern als:  "
     106
     107#: src/editor/editor_help_screen.cxx:43
     108msgid "Editor Helpscreen (hide with F1)"
     109msgstr "Editor Hilfe (ausblenden mit F1)"
     110
     111#: src/editor/editor_help_screen.cxx:51
     112msgid "F1 - show/hide this help screen"
     113msgstr "F1 - Hilfe anzeigen/verstecken"
     114
     115#: src/editor/editor_help_screen.cxx:52
     116msgid "F2 - launch level building tutorial"
     117msgstr "F2 - Starte Levelbau Tutorial"
     118
     119#: src/editor/editor_help_screen.cxx:53
     120msgid "F3 - toggle background color"
     121msgstr "F3 - Hintergrundfarbe aendern"
     122
     123#: src/editor/editor_help_screen.cxx:54
     124msgid "F4 - play/test the level"
     125msgstr "F4 - Level starten/testen"
     126
     127#: src/editor/editor_help_screen.cxx:55
     128msgid "F5 - load a level"
     129msgstr "Level Laden (F5)"
     130
     131#: src/editor/editor_help_screen.cxx:56
     132msgid "F6 - save this level"
     133msgstr "Level Speichern (F6)"
     134
     135#: src/editor/editor_help_screen.cxx:57
     136msgid "F7 - [unset]"
     137msgstr "F7 - [nicht belegt]"
     138
     139#: src/editor/editor_help_screen.cxx:58
     140msgid "F8 - quick save/backup save?!"
     141msgstr "F8 - Schnellspeichern/Backup"
     142
     143#: src/editor/editor_help_screen.cxx:59
     144msgid "F9 - change level width and height"
     145msgstr "F9 - Level Höhe und Breite ändern"
     146
     147#: src/editor/editor_help_screen.cxx:60
     148msgid "F10 - [unset]"
     149msgstr "F10 - [nicht belegt]"
     150
     151#: src/editor/editor_help_screen.cxx:61
     152msgid "F11 - toggle fps counter"
     153msgstr "F11 - fps Zähler an/aus"
     154
     155#: src/editor/editor_help_screen.cxx:62
     156msgid "F12 - make screenshot"
     157msgstr "F12 - Screenshot erstellen"
     158
     159#: src/editor/editor_help_screen.cxx:66
     160msgid "Home - increase object size"
     161msgstr "Einfg - Objekt vergrößern"
     162
     163#: src/editor/editor_help_screen.cxx:67
     164msgid "End  - decrease object size"
     165msgstr "Ende - Objekt verkleinern"
     166
     167#: src/editor/editor_help_screen.cxx:68
     168msgid "Cursor Keys - Move object"
     169msgstr "Cursor Tasten - Objekt bewegen"
     170
     171#: src/editor/editor_help_screen.cxx:69
     172msgid "Shift 'Cursor Keys' - Move objects fast "
     173msgstr "Shift Cursor Tasten - Objekt schneller bewegen"
     174
     175#: src/editor/editor_help_screen.cxx:70
     176msgid "PageUp   - level object up"
     177msgstr "Bild rauf - Objekt nach oben"
     178
     179#: src/editor/editor_help_screen.cxx:71
     180msgid "PageDown - level object down"
     181msgstr "Bild runter - Objekt nach unten"
     182
     183#: src/editor/editor_help_screen.cxx:72
     184msgid "Shift PageUp   - increase objects z-pos by 50"
     185msgstr "Shift Bild rauf - Objekt nach oben"
     186
     187#: src/editor/editor_help_screen.cxx:73
     188msgid "Shift PageDown - decrease objects z-pos by 50"
     189msgstr "Shift Bild runter - Objekt nach unten"
     190
     191#: src/editor/editor_help_screen.cxx:74
     192msgid "Enter - Set default zoom (1:1)"
     193msgstr "Eingabe - Setze Standard Zoom (1:1)"
     194
     195#: src/editor/editor_help_screen.cxx:75
     196msgid "d - duplicate object"
     197msgstr "d - Objekt kopieren"
     198
     199#: src/editor/editor_help_screen.cxx:76
     200msgid "a - mark all objects"
     201msgstr "a - Alle Objekte markieren"
     202
     203#: src/editor/editor_help_screen.cxx:77
     204msgid "shift leftmouseclick - add object to selection"
     205msgstr "Shift + linke Maustaste - Objekt zur Auswahl tun"
     206
     207#: src/editor/editor_help_screen.cxx:78
     208msgid "leftmouseclick - select object"
     209msgstr "linke Maustaste - Objekt auswählen"
     210
     211#: src/editor/editor_help_screen.cxx:79
     212msgid "Insert - insert new object"
     213msgstr "Einfügen - neues Objekt einfügen"
     214
     215#: src/editor/editor_help_screen.cxx:80
     216msgid "Remove - remove selected object"
     217msgstr "Entfernen - entferne ausgewähltes Objekt"
     218
     219#: src/editor/editor_help_screen.cxx:81
     220msgid "g - ungroup/group current selection"
     221msgstr "g - Auswahl gruppieren / Gruppierung aufheben"
     222
     223#: src/editor/editor_help_screen.cxx:82
     224msgid "Ctrl PageUp   - increase objects z-pos by 1"
     225msgstr "Strg Bild rauf - z-pos des Objekts um 1 erhöhen"
     226
     227#: src/editor/editor_help_screen.cxx:83
     228msgid "Ctrl PageDown - decrease objects z-pos by 1"
     229msgstr "Strg Bild runter - z-pos des Objekts um 1 senken"
     230
     231#: src/editor/editor_help_screen.cxx:89
     232msgid "Naming Convention: <LEVELNAME><NUMBER>-<CREATOR>.plf"
     233msgstr "Dateinamensvorgabe: <LEVELNAME><NUMMER>-<AUTOR>.pfl"
     234
     235#: src/editor/editor_help_screen.cxx:91
     236msgid ""
     237"When you have created a level and want to have it in the next Pingus "
     238"release,\n"
     239"please mail it to pingus-devel@nongnu.org."
     240msgstr ""
     241"Falls Du einen Level erstellt hast und ihn gerne im nächsten Pingus\n"
     242"Release hättest, schicke ihn an pingus-devel@nongnu.org."
     243
     244#: src/editor/object_selector.cxx:106
     245msgid "1 - guillotine"
     246msgstr "1 - Guillotine"
     247
     248#: src/editor/object_selector.cxx:107
     249msgid "2 - hammer"
     250msgstr "2 - Hammer"
     251
     252#: src/editor/object_selector.cxx:108
     253msgid "3 - spike"
     254msgstr "3 - Stacheln"
     255
     256#: src/editor/object_selector.cxx:109
     257msgid "4 - laser_exit"
     258msgstr "4 - Laser Ausgang"
     259
     260#: src/editor/object_selector.cxx:110
     261msgid "5 - fake_exit"
     262msgstr "5 - Täusch Ausgang"
     263
     264#: src/editor/object_selector.cxx:111
     265msgid "6 - smasher"
     266msgstr "6 - Stampfer"
     267
     268#: src/editor/object_selector.cxx:112
     269msgid "7 - bumper"
     270msgstr "7 - Stosser"
     271
     272#: src/editor/object_selector.cxx:186
     273msgid "Select a WorldObj"
     274msgstr "Wähle ein WeltObjekt"
     275
     276#: src/editor/object_selector.cxx:187
     277msgid "1 - teleporter"
     278msgstr "1 - Teleporter"
     279
     280#: src/editor/object_selector.cxx:188
     281msgid "2 - switch and door"
     282msgstr "2 - Schalter und Tür"
     283
     284#: src/editor/object_selector.cxx:189
     285msgid "3 - ConveyorBelt"
     286msgstr "3 - Förderband"
     287
     288#: src/editor/object_selector.cxx:190
     289msgid "4 - IceBlock"
     290msgstr "4 - Eisblock"
     291
     292#: src/editor/object_selector.cxx:191
     293msgid "5 - InfoBox"
     294msgstr "5 - InfoBox"
     295
     296#: src/editor/object_selector.cxx:232
     297msgid "Select a weather"
     298msgstr "Wähle ein Wetter"
     299
     300#: src/editor/object_selector.cxx:233
     301msgid "1 - snow"
     302msgstr "1 - Schnee"
     303
     304#: src/editor/object_selector.cxx:234
     305msgid "2 - rain"
     306msgstr "2 - Regen"
     307
     308#: src/editor/object_selector.cxx:265
     309msgid "Select an entrance"
     310msgstr "Wähle einen Eingang"
     311
     312#: src/editor/object_selector.cxx:266
     313msgid "1 - generic"
     314msgstr "1 - allgemein"
     315
     316#: src/editor/object_selector.cxx:267
     317msgid "2 - woodthing"
     318msgstr "2 - hölzern"
     319
     320#: src/editor/object_selector.cxx:268
     321msgid "3 - cloud"
     322msgstr "3 - Wolke"
     323
     324#: src/editor/object_selector.cxx:269
     325msgid "h - entrance surface (hotspot)"
     326msgstr "h - Eingangs Grafik (hotspot)"
     327
     328#: src/editor/object_selector.cxx:343
     329msgid "What object type do you want?"
     330msgstr "Was für ein Objekt willst du?"
     331
     332#: src/editor/object_selector.cxx:344 src/editor/object_selector.cxx:400
     333msgid "h - Hotspot"
     334msgstr "h - Grafikelement (hotspot)"
     335
     336#: src/editor/object_selector.cxx:345
     337msgid "g - Groundpiece (ground) [not implemented]"
     338msgstr "g - Bodenstück (ground) [nicht implementiert]"
     339
     340#: src/editor/object_selector.cxx:394 src/editor/object_selector.cxx:562
     341msgid "Which object do you want?"
     342msgstr "Welches Objekt willst du?"
     343
     344#: src/editor/object_selector.cxx:395
     345msgid "g - Groundpiece (ground)"
     346msgstr "g - Bodenstück (ground)"
     347
     348#: src/editor/object_selector.cxx:396
     349msgid "s - Groundpiece (solid)"
     350msgstr "s - Bodenelement (Stahl)"
     351
     352#: src/editor/object_selector.cxx:397
     353msgid "b - Groundpiece (bridge)"
     354msgstr "b - Bodenelement (Bruecke)"
     355
     356#: src/editor/object_selector.cxx:398
     357msgid "n - Groundpiece (transparent)"
     358msgstr "n - Bodenelement (transparent)"
     359
     360#: src/editor/object_selector.cxx:399
     361msgid "r - Groundpiece (remove)"
     362msgstr "r - Bodenelement (entfernen)"
     363
     364#: src/editor/object_selector.cxx:401
     365msgid "e - Entrance"
     366msgstr "e - Eingang"
     367
     368#: src/editor/object_selector.cxx:402
     369msgid "x - Exit"
     370msgstr "x - Ausgang"
     371
     372#: src/editor/object_selector.cxx:403
     373msgid "l - Liquid"
     374msgstr "l - Flüssigkeit"
     375
     376#: src/editor/object_selector.cxx:404
     377msgid "w - Weather"
     378msgstr "w - Wetter"
     379
     380#: src/editor/object_selector.cxx:405
     381msgid "t - Traps"
     382msgstr "t - Falle"
     383
     384#: src/editor/object_selector.cxx:406
     385msgid "o - WorldObject"
     386msgstr "o - WeltObjekt"
     387
     388#: src/editor/object_selector.cxx:407
     389msgid "z - Background"
     390msgstr "z - Hintergrund"
     391
     392#: src/editor/object_selector.cxx:408
     393msgid "p - Prefab (ObjectGroup)"
     394msgstr "p - Prefab (Objekt Gruppe)"
     395
     396#: src/editor/object_selector.cxx:409
     397msgid "f - something from file (~/.pingus/images/)"
     398msgstr "f - etwas aus einer Datei (~/.pingus/images/)"
     399
     400#: src/editor/object_selector.cxx:498
     401msgid "Which prefab do you want?"
     402msgstr "Welche Prefab willst du?"
     403
     404#: src/editor/object_selector.cxx:563
     405msgid "1 - Surface Background"
     406msgstr "1 - Bild Hintergrund"
     407
     408#: src/editor/object_selector.cxx:564
     409msgid "2 - Solid Color Background"
     410msgstr "2 - Farb Hintergrund"
     411
     412#: src/editor/object_selector.cxx:565
     413msgid "3 - Starfield Background"
     414msgstr "3 - Sternen Hintergrund"
     415
     416#: src/editor/object_selector.cxx:566
     417msgid "4 - Thunderstorm Background"
     418msgstr "4 - Gewitter Hintergrund"
     419
     420#: src/editor/panel_icons.cxx:33
     421msgid "Load a level (F5)"
     422msgstr "Level laden (F5)"
     423
     424#: src/editor/panel_icons.cxx:46
     425msgid "Exit the editor (Escape)"
     426msgstr "Editor Beenden (Esc)"
     427
     428#: src/editor/panel_icons.cxx:58
     429msgid "Save this level (F6)"
     430msgstr "Level Speichern (F6)"
     431
     432#: src/editor/panel_icons.cxx:70
     433msgid "Delete marked objects (delete)"
     434msgstr "Markierte Objekte Löschen (Entfernen)"
     435
     436#: src/editor/panel_icons.cxx:82
     437msgid "Duplicate current object (d)"
     438msgstr "Aktuelles Object kopieren (d)"
     439
     440#: src/editor/panel_icons.cxx:94
     441msgid "Edit Level Properties"
     442msgstr "Leveleigenschaften ändern"
     443
     444#: src/editor/panel_icons.cxx:106
     445msgid "Edit Object Properties"
     446msgstr "Objekteigenschaften ändern"
     447
     448#: src/editor/panel_icons.cxx:118
     449msgid "Start the level and test it (F4)"
     450msgstr "Level starten und testen (F4)"
     451
     452#: src/editor/panel_icons.cxx:130
     453msgid "Create a new level from scratch"
     454msgstr "Neuen Level erstellen"
     455
     456#: src/editor/panel_icons.cxx:142
     457msgid "Insert an object (Insert)"
     458msgstr "Objekt einfuegen (Einfg)"
     459
     460#: src/editor/panel_icons.cxx:154
     461msgid "Zoom into a region"
     462msgstr "Einen Bereich vergrössern"
     463
     464#: src/editor/panel_icons.cxx:166
     465msgid "Zoom in"
     466msgstr "Vergroessern"
     467
     468#: src/editor/panel_icons.cxx:179
     469msgid "Zoom out"
     470msgstr "Verkleinern"
     471
     472#: src/editor/panel_icons.cxx:192
     473msgid "Setup Number of Actions"
     474msgstr "Stelle die Anzahl der Fähigkeiten ein"
     475
     476#: src/editor/panel_icons.cxx:204
     477msgid "Display Help Screen (F1)"
     478msgstr "Hilfe Anzeigen (F1)"
     479
     480#: src/exit_menu.cxx:48
     481msgid "Yes"
     482msgstr "Ja"
     483
     484#: src/exit_menu.cxx:81
     485msgid "No"
     486msgstr "Nein"
     487
     488#: src/exit_menu.cxx:114
     489msgid "Exit Pingus?"
     490msgstr "Pingus beenden?"
     491
     492#: src/fps_counter.cxx:48
     493msgid "unknown"
     494msgstr "unbekannt"
     495
     496#: src/game_time.cxx:70
     497msgid "unlimited"
     498msgstr "unbegrenzt"
     499
     500#: src/level_desc.cxx:74
     501msgid "Designed by "
     502msgstr "Erstellt von "
     503
     504#: src/level_desc.cxx:79
     505#, c-format
     506msgid "Pingus to Save: %d"
     507msgstr "Zu rettende Pingus: %d"
     508
     509#: src/level_desc.cxx:81
     510#, c-format
     511msgid "Number of Pingus: %d"
     512msgstr "Anzahl an Pingus: %d"
     513
     514#: src/level_desc.cxx:86
     515msgid "Loading..."
     516msgstr "Ladevorgang läuft..."
     517
     518#: src/level_desc.cxx:89
     519msgid "Loading finished. Press a mouse button to start the level"
     520msgstr ""
     521"Ladevorgang abgeschlossen. Drücke eine Maus Taste um den Level zu starten"
     522
     523#: src/level_result.cxx:61
     524msgid "Results:"
     525msgstr "Ergebnisse:"
     526
     527#: src/level_result.cxx:67
     528#, c-format
     529msgid "Pingus saved:   %3d/%3d"
     530msgstr "Gerettete Pingus: %3d/%3d"
     531
     532#: src/level_result.cxx:72
     533#, c-format
     534msgid "Pingus died:  %3d/%3d"
     535msgstr "Tote Pingus: %3d/%3d"
     536
     537#: src/level_result.cxx:88
     538msgid "Press button to continue..."
     539msgstr "Knopf drücken um fortzufahren"
     540
     541#: src/level_result.cxx:102
     542msgid ""
     543"As many Pingus escaped as entered the level. That's going to be hard to "
     544"beat.... unless this game becomes pornographic."
     545msgstr ""
     546"Es wurden alle Pingu dieses Levels gerettet. Das wird hart zu schlagen "
     547"sein... es sei denn dieses Spiel wird pornographisch."
     548
     549#: src/level_result.cxx:104
     550msgid "Very impressive indeed."
     551msgstr "In der Tat sehr eindrucksvoll."
     552
     553#: src/level_result.cxx:106
     554msgid "Good work. Still room for improvement though."
     555msgstr "Gute Arbeit. Aber Übung macht den Meiser!"
     556
     557#: src/level_result.cxx:108
     558msgid "Not too shabby, not too shabby at all."
     559msgstr "Nicht schlecht, nicht schlecht!"
     560
     561#: src/level_result.cxx:110
     562msgid ""
     563"That was OK, but Pingu life insurance premiums have just gotten more "
     564"expensive."
     565msgstr ""
     566"Das war ok, aber die Lebensversicherungsprämien für Pingus sind gerade "
     567"gestiegen."
     568
     569#: src/level_result.cxx:112
     570msgid "Maybe this level calls for a different strategy."
     571msgstr "Möglicherweise verlangt dieser Level eine andere Strategie."
     572
     573#: src/level_result.cxx:114
     574msgid "Exactly half. Are you saving only the female ones?"
     575msgstr "Genau die Hälfte! Rettest du nur die Weibchen?"
     576
     577#: src/level_result.cxx:116
     578msgid "If I were a Pingu, I never would have left that entrance."
     579msgstr "Wenn ich ein Pingu wäre, hätte ich den Eingang nie verlassen."
     580
     581#: src/level_result.cxx:118
     582msgid "Maybe you would feel more at home playing Quake."
     583msgstr "Möglicherweise wäre es besser Quake zu spielen?"
     584
     585#: src/level_result.cxx:120
     586msgid ""
     587"Maybe this level calls for a different strategy. Like attempting to save "
     588"them, for example."
     589msgstr ""
     590"Es kann sein, dass wir etwas anderes versuchen sollten.  Vielleicht könnten "
     591"wir ja die Pingus retten?"
     592
     593#: src/level_result.cxx:122
     594msgid "Ever considered a career as a Pingu exterminator?"
     595msgstr "Hast du mal über eine Karriere als Pingu Zerstörer nachgedacht?"
     596
     597#: src/level_result.cxx:124
     598msgid "You missed one! What's your excuse!?"
     599msgstr "Du hast einen vergessen! Was ist deine Entschuldigung?"
     600
     601#: src/level_result.cxx:126
     602msgid "Please reassure me that you hit the Armageddon button."
     603msgstr "Bestätige mir bitte, dass das die Armageddon Taste war."
     604
     605#: src/level_result.cxx:128
     606msgid "You've got a negative save/total value, something is buggy."
     607msgstr "Ein negativer Wert? Hier liegt ein Fehler vor."
     608
     609#: src/menu_button.cxx:181
     610msgid "..:: The people who brought this game to you ::.."
     611msgstr "..:: Die Leute, die fuer dieses Spiel verantwortlich sind... ::.."
     612
     613#: src/menu_button.cxx:184
     614msgid "Credits"
     615msgstr "Mitwirkende"
     616
     617#: src/menu_button.cxx:216
     618msgid "..:: Takes you to the options menu ::.."
     619msgstr "..:: Einstellungen, Cheats und Debugging stuff ::.."
     620
     621#: src/menu_button.cxx:219
     622msgid "Options"
     623msgstr "Einstellungen"
     624
     625#: src/menu_button.cxx:252
     626msgid "..:: Bye, bye ::.."
     627msgstr "..:: Auf Wiedersehen ::.."
     628
     629#: src/menu_button.cxx:255
     630msgid "Exit"
     631msgstr "Beenden"
     632
     633#: src/menu_button.cxx:306
     634msgid "..:: Launch the level editor ::.."
     635msgstr "..:: Erstelle deinen eigenen Level ::.."
     636
     637#: src/menu_button.cxx:309
     638msgid "Create a"
     639msgstr "Bau einen"
     640
     641#: src/menu_button.cxx:310
     642msgid "Level"
     643msgstr "Level"
     644
     645#: src/menu_button.cxx:344
     646msgid "..:: Start the game ::.."
     647msgstr "..:: das Spiel starten ::.."
     648
     649#: src/menu_button.cxx:345
     650msgid "Start"
     651msgstr "Start"
     652
     653#: src/menu_button.cxx:375
     654msgid "..:: Start a contrib level ::.."
     655msgstr "..:: Contrib level Spielen ::.."
     656
     657#: src/menu_button.cxx:377
     658msgid "Contrib"
     659msgstr "Levels"
     660
     661#: src/menu_button.cxx:399
     662msgid "..:: Multiplayer Modes... experimental stuff ::.."
     663msgstr "..:: Mehrspieler Modus ::.. Experimentelles Zeug ::.."
     664
     665#: src/menu_button.cxx:401
     666msgid "Multi"
     667msgstr "Multi"
     668
     669#: src/pingu_enums.cxx:35
     670msgid "Angel"
     671msgstr "Angel"
     672
     673#: src/pingu_enums.cxx:36
     674msgid "Basher"
     675msgstr "Basher"
     676
     677#: src/pingu_enums.cxx:37
     678msgid "Blocker"
     679msgstr "Blocker"
     680
     681#: src/pingu_enums.cxx:38
     682msgid "Boarder"
     683msgstr "Boarder"
     684
     685#: src/pingu_enums.cxx:39
     686msgid "Bomber"
     687msgstr "Bomber"
     688
     689#: src/pingu_enums.cxx:41
     690msgid "Climber"
     691msgstr "Climber"
     692
     693#: src/pingu_enums.cxx:42
     694msgid "Digger"
     695msgstr "Digger"
     696
     697#: src/pingu_enums.cxx:43
     698msgid "Drown"
     699msgstr "Drown"
     700
     701#: src/pingu_enums.cxx:44
     702msgid "Exiter"
     703msgstr "Exiter"
     704
     705#: src/pingu_enums.cxx:45
     706msgid "Faller"
     707msgstr "Faller"
     708
     709#: src/pingu_enums.cxx:46
     710msgid "Floater"
     711msgstr "Floater"
     712
     713#: src/pingu_enums.cxx:47
     714msgid "Jumper"
     715msgstr "Jumper"
     716
     717#: src/pingu_enums.cxx:48
     718msgid "Laserkill"
     719msgstr "Laserkill"
     720
     721#: src/pingu_enums.cxx:49
     722msgid "Miner"
     723msgstr "Miner"
     724
     725#: src/pingu_enums.cxx:50
     726msgid "Rocketlauncher"
     727msgstr "Rocketlauncher"
     728
     729#: src/pingu_enums.cxx:51
     730msgid "Slider"
     731msgstr "Slider"
     732
     733#: src/pingu_enums.cxx:52
     734msgid "Smashed"
     735msgstr "Smashed"
     736
     737#: src/pingu_enums.cxx:53
     738msgid "Splashed"
     739msgstr "Splashed"
     740
     741#: src/pingu_enums.cxx:54
     742msgid "Superman"
     743msgstr "Superman"
     744
     745#: src/pingu_enums.cxx:55
     746msgid "Teleported"
     747msgstr "Teleported"
     748
     749#: src/pingu_enums.cxx:56
     750msgid "Waiter"
     751msgstr "Waiter"
     752
     753#: src/pingu_enums.cxx:57
     754msgid "Walker"
     755msgstr "Walker"
     756
     757#: src/pingus_counter.cxx:52
     758#, c-format
     759msgid "Released:%3d/%-3d   Out:%3d   Saved:%3d/%-3d"
     760msgstr "Rein: %3d/%-3d  Raus: %3d Gerettet: %3d/%-3d"
     761
     762#: src/pingus_main.cxx:90
     763msgid "| segfault_handler: catched a SIGSEGV."
     764msgstr "| segfault_handler: SIGSEGV abgefangen."
     765
     766#: src/pingus_main.cxx:92
     767msgid "| Woops, Pingus just crashed, congratulations you've found a bug."
     768msgstr ""
     769"| Woops, Pingus ist abgestürzt. Gratuliere, du hast einen Bug gefunden."
     770
     771#: src/pingus_main.cxx:93
     772msgid ""
     773"| Please write a little bug report to <grumbel@gmx.de>, include informations"
     774msgstr ""
     775"| Bitte schreibe einen kleinen Report an <pingus-devel@nongnu.org, mit "
     776"Informationen,"
     777
     778#: src/pingus_main.cxx:94
     779msgid "| where exacly the SIGSEGV occured and how to reproduce it."
     780msgstr "| wo genau der SIGSEGV auftrat und wie man ihn reproduziert."
     781
     782#: src/pingus_main.cxx:95
     783msgid "| Also try include a backtrace, you can get it like this:"
     784msgstr "| Versuche auch einen backtrace zu erstellen, du bekommst ihn so:"
     785
     786#: src/pingus_main.cxx:101
     787msgid "| If that doesn't work, try this:"
     788msgstr "| Wenn das nicht geht, versuche dies:"
     789
     790#: src/pingus_main.cxx:105
     791msgid "| [play until it crashes again]"
     792msgstr "| [spiele bis es wieder crasht]"
     793
     794#: src/pingus_main.cxx:113
     795msgid "| Warning: Pingus recieved a SIGINT, exiting now."
     796msgstr "| Warnung: Pingus erhielt einen SIGINT, beende jetzt."
     797
     798#: src/pingus_main.cxx:301
     799msgid "Warning: Larger resolution than 800x600 will result in visual problems"
     800msgstr ""
     801"Warnung: Auflösungen grösser als 800x600 können zu visuellen Problemen führen"
     802
     803#: src/pingus_main.cxx:488
     804msgid "Unknow char: "
     805msgstr "Unbekannter Buchstabe: "
     806
     807#: src/pingus_main.cxx:489
     808msgid "Usage: "
     809msgstr "Benutzung: "
     810
     811#: src/pingus_main.cxx:489
     812msgid " [OPTIONS]... [LEVELFILE]"
     813msgstr "[OPTIONEN]... [LEVELDATEI]"
     814
     815#: src/pingus_main.cxx:492
     816msgid "Options:"
     817msgstr "Einstellungen"
     818
     819#: src/pingus_main.cxx:494
     820msgid "Set the resolution for pingus (default: 800x600)"
     821msgstr "Setze die Auflösung für Pingus (Standard: 800x600)"
     822
     823#: src/pingus_main.cxx:495
     824msgid "Displays this help"
     825msgstr "Hilfe Anzeigen"
     826
     827#: src/pingus_main.cxx:496
     828msgid "Disable intro"
     829msgstr "Intro abschalten"
     830
     831#: src/pingus_main.cxx:497
     832msgid "Use OpenGL"
     833msgstr "OpenGL benutzen"
     834
     835#: src/pingus_main.cxx:499
     836msgid "Start in Window Mode"
     837msgstr "Pingus im Fenster starten"
     838
     839#: src/pingus_main.cxx:500
     840msgid "Start in Fullscreen"
     841msgstr "Pingus im Vollbild starten"
     842
     843#: src/pingus_main.cxx:504
     844msgid "FILE      "
     845msgstr "Datei     "
     846
     847#: src/pingus_main.cxx:504
     848msgid "Load a custom level from FILE"
     849msgstr "Einen Level aus DATEI laden"
     850
     851#: src/pingus_main.cxx:505
     852msgid "FILE        "
     853msgstr "Datei      "
     854
     855#: src/pingus_main.cxx:505
     856msgid "Load a custom worldmap from FILE"
     857msgstr "Eine Weltkarte aus DATEI laden"
     858
     859#: src/pingus_main.cxx:506
     860msgid "Print some more messages to stdout, can be set"
     861msgstr "Gibt mehr Nachrichten auf stdout aus, kann"
     862
     863#: src/pingus_main.cxx:507
     864msgid "multiple times to increase verbosity"
     865msgstr "mehrmals gesetzt werden, um die Genauigkeit zu erhöhen"
     866
     867#: src/pingus_main.cxx:508
     868msgid "Prints version number and exit"
     869msgstr "Version ausgeben und beenden"
     870
     871#: src/pingus_main.cxx:509
     872msgid "Launch the Level editor (experimental)"
     873msgstr "Level Editor starten (Experimentell)"
     874
     875#: src/pingus_main.cxx:510
     876msgid "Disable automatic scrolling"
     877msgstr "Automatisches Scrollen abschalten"
     878
     879#: src/pingus_main.cxx:512
     880msgid "Enable software cursor"
     881msgstr "Aktiviere Software Cursor"
     882
     883#: src/pingus_main.cxx:515
     884msgid "Don't read ~/.pingus/config"
     885msgstr "~/.pingus/config nicht einlesen"
     886
     887#: src/pingus_main.cxx:516
     888msgid "FILE       "
     889msgstr "Datei      "
     890
     891#: src/pingus_main.cxx:516
     892msgid "Read config from FILE (default: ~/.pingus/config)"
     893msgstr "Konfiguration aus DATEI lesen"
     894
     895#: src/pingus_main.cxx:517
     896msgid "reduce CPU usage, might speed up the game on slower machines"
     897msgstr ""
     898"reduziere CPU Belastung, könnte das Spiel auf langsamen Rechnern "
     899"beschleunigen"
     900
     901#: src/pingus_main.cxx:518
     902msgid "Uses the controller given in FILE"
     903msgstr "Controller aus FILE benutzen"
     904
     905#: src/pingus_main.cxx:520
     906msgid "Debugging and experimental stuff:"
     907msgstr "Debug und Experimentelles Zeug"
     908
     909#: src/pingus_main.cxx:521
     910msgid "Enables some features, only interesting programmers"
     911msgstr "Aktiviere einige Funktionen, nur für Programmierer"
     912
     913#: src/pingus_main.cxx:522
     914msgid "Enable the output of debugging infos, possible"
     915msgstr "Aktiviere die Ausgabe von Debug Informationen, mögliche"
     916
     917#: src/pingus_main.cxx:523
     918msgid "OPTION's are tiles, gametime, actions, sound, resources, gui,"
     919msgstr "Optionen sind tiles, gametime, actions, sound, resources, gui,"
     920
     921#: src/pingus_main.cxx:525
     922msgid "Skip at least N frames, larger values speed the game up"
     923msgstr ""
     924"Überspringe mindestens N Bilder, größere Werte erhöhen die Geschwindigkeit"
     925
     926#: src/pingus_main.cxx:526
     927msgid "Skip at most N frames"
     928msgstr "Überspringe maximal N Bilder"
     929
     930#: src/pingus_main.cxx:527
     931msgid "Set both min and max frameskip to N"
     932msgstr "Setze sowohl minimalen als auch maximalen Bildsprung auf N"
     933
     934#: src/pingus_main.cxx:528
     935msgid "Set the game speed (0=fastest, >0=slower)"
     936msgstr "Setze die Geschwindigkeit (0=schnellste, >0=langsamer)"
     937
     938#: src/pingus_main.cxx:529
     939msgid "Prints the fps to stdout"
     940msgstr "Schreibe die fps auf stdout"
     941
     942#: src/pingus_main.cxx:530
     943msgid "Set the size of the map tiles (default: 32)"
     944msgstr "Setze die Größe der Kartenteile (Standard: 32)"
     945
     946#: src/pingus_main.cxx:531
     947msgid "Disable some cpu intensive features"
     948msgstr "Deaktivere einige CPU intensive Funktionen"
     949
     950#: src/pingus_main.cxx:532
     951msgid "Reduces the CPU usage by issuing sleep()"
     952msgstr "Reduziert die CPU Belastung durch Verwendung von sleep()"
     953
     954#: src/pingus_main.cxx:534
     955msgid "Demo playing and recording:"
     956msgstr "Demo aufzeichnung und wiedergabe:"
     957
     958#: src/pingus_main.cxx:535
     959msgid "FILE     "
     960msgstr "Datei    "
     961
     962#: src/pingus_main.cxx:535
     963msgid "Plays a demo session from FILE"
     964msgstr "Spielt eine Demo Sitzung aus FILE"
     965
     966#: src/pingus_main.cxx:537
     967msgid "Record demos for each played level"
     968msgstr "Nehme Demos für jeden gespielten Level auf"
     969
     970#: src/pingus_main.cxx:539
     971msgid "Sound:"
     972msgstr "Sound"
     973
     974#: src/pingus_main.cxx:540
     975msgid "Disable sound"
     976msgstr "Sound deaktivieren"
     977
     978#: src/pingus_main.cxx:541
     979msgid "Disable music"
     980msgstr "Musik deaktivieren"
     981
     982#: src/pingus_main.cxx:720
     983msgid "clanVorbis support:           ok"
     984msgstr "clanVorbis Unterstützung:    ok"
     985
     986#: src/pingus_main.cxx:722
     987msgid "clanVoribs support:  missing (.ogg music files will not be playable)"
     988msgstr ""
     989"clanVorbis Unterstützung: fehlt (.ogg Musik Datein können nicht abgespielt "
     990"werden)"
     991
     992#: src/pingus_main.cxx:726
     993msgid "clanMikMod support:           ok"
     994msgstr "clanMikMod Unterstützung:    ok"
     995
     996#: src/pingus_main.cxx:728
     997msgid "clanMikMod support:  missing (music files will not be playable)"
     998msgstr ""
     999"clanMikMod Untersützung: fehlt (Musikdateien können nicht abgespielt werden)"
     1000
     1001#: src/pingus_main.cxx:732
     1002msgid "getext support:               ok"
     1003msgstr "gettext Unterstützung:       ok"
     1004
     1005#: src/pingus_main.cxx:733
     1006msgid "gettext language:        english"
     1007msgstr "gettext Sprache:        deutsch"
     1008
     1009#: src/pingus_main.cxx:739
     1010msgid "sound support:           enabled"
     1011msgstr "Sound Unterstützung:         an"
     1012
     1013#: src/pingus_main.cxx:741
     1014msgid "sound support:          disabled"
     1015msgstr "Sound Unterstützung:        aus"
     1016
     1017#: src/pingus_main.cxx:744
     1018msgid "music support:           enabled"
     1019msgstr "Musik Unterstützung:         an"
     1020
     1021#: src/pingus_main.cxx:746
     1022msgid "music support:          disabled"
     1023msgstr "Musik Unterstützung:        aus"
     1024
     1025#: src/pingus_main.cxx:748
     1026msgid "resolution set to:       "
     1027msgstr "Auflösung:              "
     1028
     1029#: src/pingus_main.cxx:749
     1030msgid "fullscreen:              "
     1031msgstr "Vollbild:           "
     1032
     1033#: src/pingus_main.cxx:750
     1034msgid " enabled"
     1035msgstr "aktiviert"
     1036
     1037#: src/pingus_main.cxx:750
     1038msgid "disabled"
     1039msgstr "deaktiviert"
     1040
  • new file libraries/source/tinygettext/test/helloworld.cpp

    diff --git a/libraries/source/tinygettext/test/helloworld.cpp b/libraries/source/tinygettext/test/helloworld.cpp
    new file mode 100644
    index 0000000..071ab96
    - +  
     1#include <iostream>
     2
     3#define _(x) gettext(x)
     4
     5int main()
     6{
     7  std::cout << _("Short Hello World") << std::endl;
     8  std::cout << gettext("Hello World") << std::endl;
     9  std::cout << gettext("Hello Worlds") << std::endl;
     10
     11  std::cout << pgettext("", "Hello World") << std::endl;
     12  std::cout << pgettext("console", "Hello World") << std::endl;
     13
     14  std::cout << ngettext("gui", "Hello World") << std::endl;
     15  std::cout << ngettext("Hello World", "Hello Worlds", 5) << std::endl;
     16
     17  std::cout << npgettext("", "Hello World", "Hello Worlds", 5) << std::endl;
     18  std::cout << npgettext("console", "Hello World", "Hello Worlds", 5) << std::endl;
     19  std::cout << npgettext("gui", "Hello World", "Hello Worlds", 5) << std::endl;
     20
     21  return 0;
     22}
     23
     24/* EOF */
  • new file libraries/source/tinygettext/test/helloworld/de.po

    diff --git a/libraries/source/tinygettext/test/helloworld/de.po b/libraries/source/tinygettext/test/helloworld/de.po
    new file mode 100644
    index 0000000..048acc6
    - +  
     1# SOME DESCRIPTIVE TITLE.
     2# Copyright (C) YEAR Free Software Foundation, Inc.
     3# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
     4#
     5#, fuzzy
     6msgid ""
     7msgstr ""
     8"Project-Id-Version: PACKAGE VERSION\n"
     9"Report-Msgid-Bugs-To: \n"
     10"POT-Creation-Date: 2009-01-30 08:01+0100\n"
     11"PO-Revision-Date: 2009-01-30 08:39+0100\n"
     12"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
     13"Language-Team: LANGUAGE <LL@li.org>\n"
     14"MIME-Version: 1.0\n"
     15"Content-Type: text/plain; charset=UTF-8\n"
     16"Content-Transfer-Encoding: 8bit\n"
     17
     18#: helloworld.cpp:7
     19msgid "Short Hello World"
     20msgstr "kurzes Hallo Welt"
     21
     22#: helloworld.cpp:8 helloworld.cpp:14
     23#, fuzzy
     24msgid "Hello World"
     25msgid_plural "Hello Worlds"
     26msgstr[0] "Hallo Welt (singular)"
     27msgstr[1] "Hallo Welt (plural)"
     28
     29#: helloworld.cpp:10 helloworld.cpp:16
     30#, fuzzy
     31msgctxt ""
     32msgid "Hello World"
     33msgid_plural "Hello Worlds"
     34msgstr[0] "Hallo Welt (singular) mit leerem Kontext"
     35msgstr[1] "Hallo Welt (plural) mit leerem Kontext"
     36
     37#: helloworld.cpp:11 helloworld.cpp:17
     38msgctxt "console"
     39msgid "Hello World"
     40msgid_plural "Hello Worlds"
     41msgstr[0] "Hallo Welt (singular) in der Console"
     42msgstr[1] "Hallo Welt (plural) in der Console"
     43
     44#: helloworld.cpp:13
     45msgid "gui"
     46msgid_plural "Hello World"
     47msgstr[0] "Hallo Welt (singular)"
     48msgstr[1] "Hallo Welt (plural)"
     49
     50#: helloworld.cpp:18
     51#, fuzzy
     52msgctxt "gui"
     53msgid "Hello World"
     54msgid_plural "Hello Worlds"
     55msgstr[0] "Hallo Welt im GUI"
     56msgstr[1] "Hallo Welt (plural) im GUI"
  • new file libraries/source/tinygettext/test/helloworld/helloworld.pot

    diff --git a/libraries/source/tinygettext/test/helloworld/helloworld.pot b/libraries/source/tinygettext/test/helloworld/helloworld.pot
    new file mode 100644
    index 0000000..a9174f8
    - +  
     1# SOME DESCRIPTIVE TITLE.
     2# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
     3# This file is distributed under the same license as the PACKAGE package.
     4# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
     5#
     6#, fuzzy
     7msgid ""
     8msgstr ""
     9"Project-Id-Version: PACKAGE VERSION\n"
     10"Report-Msgid-Bugs-To: \n"
     11"POT-Creation-Date: 2009-01-30 08:10+0100\n"
     12"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
     13"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
     14"Language-Team: LANGUAGE <LL@li.org>\n"
     15"MIME-Version: 1.0\n"
     16"Content-Type: text/plain; charset=CHARSET\n"
     17"Content-Transfer-Encoding: 8bit\n"
     18"Plural-Forms: nplurals=INTEGER; plural=EXPRESSION;\n"
     19
     20#: helloworld.cpp:7
     21msgid "Short Hello World"
     22msgstr ""
     23
     24#: helloworld.cpp:8 helloworld.cpp:14
     25msgid "Hello World"
     26msgid_plural "Hello Worlds"
     27msgstr[0] ""
     28msgstr[1] ""
     29
     30#: helloworld.cpp:10 helloworld.cpp:16
     31msgctxt ""
     32msgid "Hello World"
     33msgid_plural "Hello Worlds"
     34msgstr[0] ""
     35msgstr[1] ""
     36
     37#: helloworld.cpp:11 helloworld.cpp:17
     38msgctxt "console"
     39msgid "Hello World"
     40msgid_plural "Hello Worlds"
     41msgstr[0] ""
     42msgstr[1] ""
     43
     44#: helloworld.cpp:13
     45msgid "gui"
     46msgid_plural "Hello World"
     47msgstr[0] ""
     48msgstr[1] ""
     49
     50#: helloworld.cpp:18
     51msgctxt "gui"
     52msgid "Hello World"
     53msgid_plural "Hello Worlds"
     54msgstr[0] ""
     55msgstr[1] ""
  • new file libraries/source/tinygettext/test/level/de.po

    diff --git a/libraries/source/tinygettext/test/level/de.po b/libraries/source/tinygettext/test/level/de.po
    new file mode 100644
    index 0000000..69e0206
    - +  
     1# SOME DESCRIPTIVE TITLE.
     2# Copyright (C) YEAR Free Software Foundation, Inc.
     3# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
     4#
     5#, fuzzy
     6msgid ""
     7msgstr ""
     8"Project-Id-Version: PACKAGE VERSION\n"
     9"PO-Revision-Date: YEAR-MO-DA HO:MI +ZONE\n"
     10"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
     11"Language-Team: LANGUAGE <LL@li.org>\n"
     12"MIME-Version: 1.0\n"
     13"Content-Type: text/plain; charset=CHARSET\n"
     14"Content-Transfer-Encoding: 8bit\n"
     15
     16#: src/pingus_main.cxx:760
     17msgid "PingusMain: Starting Main: "
     18msgstr "PingusMain: Hauptteil wird gestartet: "
     19
     20#: src/pingus_main.cxx:805
     21msgid "PingusMain: Levelfile not found, ignoring: "
     22msgstr "PingusMain: Leveldatei nicht gefunden, Fehler wird ignoriert: "
     23
     24#: src/pingus_main.cxx:909
     25msgid "Error caught from ClanLib: "
     26msgstr "ClanLib Fehler abgefangen: "
     27
     28#: src/pingus_main.cxx:913
     29msgid "Error caught from Pingus: "
     30msgstr "Pingus Fehler wurde abgefangen: "
     31
     32#: src/pingus_main.cxx:917
     33msgid "Pingus: Out of memory!"
     34msgstr "Pingus: Speicher ist ausgegangen"
     35
     36#: src/pingus_main.cxx:921
     37msgid "Pingus: Standard exception caught!:\n"
     38msgstr "Pingus: Standard Ausnahme abgefangen!:\n"
     39
     40#: src/pingus_main.cxx:925
     41msgid "Pingus: Unknown throw caught!"
     42msgstr "Pingus: Unbekannte Ausnahme abgefangen!"
     43
     44#: src/result_screen.cxx:99 src/start_screen.cxx:111
     45msgid "Abort"
     46msgstr "Abbruch"
     47
     48#: src/result_screen.cxx:167
     49msgid "Retry"
     50msgstr "Versuche erneut"
     51
     52#: src/result_screen.cxx:175
     53msgid "Success!"
     54msgstr "Erfolg!"
     55
     56#: src/result_screen.cxx:182
     57msgid "Failure!"
     58msgstr "Fehler!"
     59
     60#: src/result_screen.cxx:191
     61msgid "Perfect! You saved everyone possible - great!"
     62msgstr "Perfekt! Du hast alle gerettet!"
     63
     64#: src/result_screen.cxx:193
     65msgid "No-one got killed, pretty good work."
     66msgstr "Keiner wurde getötet, sehr gute Arbeit."
     67
     68#: src/result_screen.cxx:195
     69msgid ""
     70"You saved exactly what you needed - you made it, but\n"
     71"maybe you can do better?"
     72msgstr ""
     73"Du hast so viele gerettet wie nötig. Du hast es\n"
     74"geschafft, aber vielleicht kannst Du es noch besser?"
     75
     76#: src/result_screen.cxx:198
     77msgid "Not everybody was saved, but still good work!"
     78msgstr "Nicht alle wurden gerettet, aber trotzdem noch gute Arbeit!"
     79
     80#: src/result_screen.cxx:200
     81msgid "What can I say, you made it - congratulations!"
     82msgstr "Was soll ich sagen, Du hast es geschafft. Gratuliere!"
     83
     84#: src/result_screen.cxx:205
     85msgid "You killed everybody, not good."
     86msgstr "Du hast alle getötet, nicht gut."
     87
     88#: src/result_screen.cxx:207
     89msgid "No-one got saved - I know you can do better."
     90msgstr "Keiner wurde gerettet, ich weiß, dass du es besser kannst."
     91
     92#: src/result_screen.cxx:209
     93msgid ""
     94"You didn't save enough, but you saved a few.  Next\n"
     95"time you might do better."
     96msgstr ""
     97"Du hast nicht genug gerettet, aber immerhin ein paar.\n"
     98"Nächstes Mal machst du es bestimmt besser."
     99
     100#: src/result_screen.cxx:212
     101msgid "Only one more and you would have made it - try again!"
     102msgstr "Einer mehr und du hast es, versuch es nochmal!"
     103
     104#: src/result_screen.cxx:214
     105msgid "Only a handful more and you would have made it - try again!"
     106msgstr "Nur ein paar mehr und du hättest es, versuch es nochmal!"
     107
     108#: src/result_screen.cxx:216
     109msgid "Better luck next time!"
     110msgstr "Mehr Glück fürs nächste Mal!"
     111
     112#: src/result_screen.cxx:232
     113msgid "Saved: "
     114msgstr "Gerettet: "
     115
     116#: src/result_screen.cxx:236
     117msgid "Died: "
     118msgstr "Getötet: "
     119
     120#: src/result_screen.cxx:240
     121msgid "Time left: "
     122msgstr "Verbliebene Zeit: "
     123
     124#: src/screenshot.cxx:45
     125msgid "Screenshot: Saving screenshot to: "
     126msgstr "Screenshot: Speichere Screenshot als: "
     127
     128#: src/screenshot.cxx:47
     129msgid "Screenshot: Screenshot is done."
     130msgstr "Screenshot: Screenshot wurde erstellt."
     131
     132#: src/screenshot.cxx:53
     133msgid "Screenshot: Couldn't save screenshot"
     134msgstr "Screenshot: Screenshot konnte nicht gespeichert werden"
     135
     136#: src/screenshot.cxx:138
     137msgid "Screenshot: Couldn't write file: "
     138msgstr "Screenshot: Datei konnte nicht geschrieben werden: "
     139
     140#: src/spot_map.cxx:286
     141#, c-format
     142msgid "Image has wrong color depth: %d"
     143msgstr "Bild hat falsche Farbtiefe: %d"
     144
     145#: src/start_screen.cxx:75
     146msgid "Ok"
     147msgstr "Ok"
     148
     149#: src/start_screen.cxx:158
     150msgid "Number of Pingus: "
     151msgstr "Anzahl an Pingus: "
     152
     153#: src/start_screen.cxx:161
     154msgid "Number to Save: "
     155msgstr "Zu rettende Pingus: "
     156
     157#: src/start_screen.cxx:164
     158msgid "Time: "
     159msgstr "Zeit: "
     160
     161#: src/start_screen.cxx:167
     162msgid "Difficulty:"
     163msgstr "Schwierigkeitsgrad:"
     164
     165#: src/start_screen.cxx:175
     166msgid "Author: "
     167msgstr "Autor: "
     168
     169#: src/start_screen.cxx:178
     170msgid "Filename: "
     171msgstr "Dateiname: "
     172
     173#: src/story.cxx:41
     174msgid "The Journey Continues"
     175msgstr "Die Reise geht weiter"
     176
     177#: src/story.cxx:46
     178msgid ""
     179"Now after you and the Pingus have learned the basics and\n"
     180"practiced a bit it is time to move on and begin the journey into\n"
     181"the world. Since the ice floe with which the Pingus traveled to the\n"
     182"Tutorial Island isn't going to hold on the whole way into the warmer\n"
     183"climates the Pingus have to find something else to guide\n"
     184"them on their journey.\n"
     185msgstr ""
     186"Nachdem Du und die Pingus nun die Grundlagen gelernt und\n"
     187"ein wenig Übung haben, ist es an der Zeit, weiter zu gehen und die\n"
     188"Reise in die Welt zu beginnen. Da die Scholle, mit der die Pingus zum\n"
     189"Tutorial Island reisten, nicht den ganzen Weg in die wärmeren Regionen\n"
     190"halten wird, müssen die Pingus etwas anderes finden, um sie auf der\n"
     191"Reise zu begleiten.\n"
     192
     193#: src/story.cxx:58
     194msgid ""
     195"But as the eldest have said, the Tutorial Island provides not\n"
     196"only a good way to practice, but it is also the starting point into\n"
     197"the world. After some searching the Pingus discovered the meaning\n"
     198"of this, and they found the large tree at the end of the island\n"
     199"which gave them wood to construct a float.\n"
     200msgstr ""
     201"Aber wie die Weisen sagten, ist Tutorial Island nicht nur\n"
     202"eine Möglichkeit zum üben, es ist auch der erste Schritt in\n"
     203"die Welt, denn das Holz der Bäume am Ende der Insel liefert\n"
     204"gutes Material, um ein Floß zu bauen.\n"
     205
     206#: src/story.cxx:69
     207msgid ""
     208"So the Pingus set out and constructed some large rafts, enough\n"
     209"to carry them all. After also packing a bunch of provisions\n"
     210"they were prepared to start their journey and leave\n"
     211"their familiar ground and enter the unknown parts of the world.\n"
     212msgstr ""
     213"So gingen die Pingus hin und bauten ein paar große\n"
     214"Flöße, genug, um alle zu tragen. Nachdem sie auch noch einigen\n"
     215"Proviant eingepackt hatten, waren sie endlich bereit, ihre Reise zu\n"
     216"beginnen, den bekannten Bereich zu verlassen und die unbekannten\n"
     217"Bereiche der Welt zu betreten.\n"
     218
     219#: src/story.cxx:79
     220msgid ""
     221"So the Pingus sit on their raft, worrying about what's to come and\n"
     222"where to go, while floating into the sunset.\n"
     223"\n"
     224"To be continued..."
     225msgstr ""
     226"So saßen die Pingus nur auf ihrem Floß und sorgten sich, was denn nun\n"
     227"kommen möge, während sie in den Sonnenuntergang trieben.\n"
     228"\n"
     229"Fortsetzung folgt..."
     230
     231#: src/story.cxx:91
     232msgid "The Journey Begins"
     233msgstr "Die Reise beginnt"
     234
     235#: src/story.cxx:96
     236msgid ""
     237"For a long time, the Pingus have lived happily in peace on the\n"
     238"South Pole along with all the other animals. Everything was in\n"
     239"balance and it seemed like nothing could disrupt their peace.  The\n"
     240"Pingus were happy and it seemed like this could never end.\n"
     241msgstr ""
     242"Die Pingus lebten schon lange glücklich und in Frieden am Südpol,\n"
     243"zusammen mit all den anderen Tieren. Alles war im Gleichgewicht und\n"
     244"es schien, als könnte nichts ihren Frieden stören. Die Pingus waren\n"
     245"glücklich und es schien, als würde dies niemals enden.\n"
     246
     247#: src/story.cxx:106
     248msgid ""
     249"But then one day, things began to change slowly: the sky got darker\n"
     250"and the earth got warmer. Firstly, they thought this was just a\n"
     251"normal fluctuation in the world's climate, but things seemed to get\n"
     252"worse and worse with every year."
     253msgstr ""
     254"Aber dann, eines Tages, veränderten sich die Dinge langsam. Der\n"
     255"Himmel wurde dunkler und die Erde wärmer. Zuerst dachten sie, dies\n"
     256"wäre nur eine normale Schwankung im Klima, aber es wurde von Jahr \n"
     257"zu Jahr immer schlimmer."
     258
     259#: src/story.cxx:117
     260msgid ""
     261"The snow began to melt away in a few areas and food became an\n"
     262"issue. Other animals tried to leave the region to search\n"
     263"for colder areas, but the Pingus knew that this wouldn't help:\n"
     264"they knew that they had to do something about it."
     265msgstr ""
     266"Der Schnee begann in einigen Bereichen zu schmelzen und Nahrung\n"
     267"wurde ein Problem. Andere Tiere begannen bereits, die Region zu\n"
     268"verlassen, um kältere Gebiete zu suchen. Aber die Pingus wussten,\n"
     269"dass dies nicht helfen würde, sie wussten, es musste etwas gegen\n"
     270"dieses Problem getan werden."
     271
     272#: src/story.cxx:127
     273msgid ""
     274"So the circle of the eldest came together to decide what to do\n"
     275"about it. They decided to send out an expedition around the world\n"
     276"to find the cause of this warming. The expedition consisted of\n"
     277"hundreds of the bravest Pingus on the South Pole."
     278msgstr ""
     279"Darum traf sich der Rat der Ältesten, um zu entscheiden, was dagegen\n"
     280"getan werden sollte. Sie entschieden, eine Expedition um die Welt\n"
     281"zu senden, um den Grund für die Erwärmung zu finden. Die Expedition\n"
     282"bestand aus hunderten der mutigsten Pingus des ganzen Südpols."
     283
     284#: src/story.cxx:137
     285msgid ""
     286"And they picked you to lead them on their journey around the\n"
     287"world. Since the journey will be dangerous and difficult, your\n"
     288"first goal is the Island of Mogorok, also known as the Tutorial\n"
     289"Island. According to the eldest, this island has always been the\n"
     290"first stop of Pingus that were sent out into the world."
     291msgstr ""
     292"Und sie wählten dich, um sie auf der Reise um die Welt zu führen.\n"
     293"Denn die Reise wird gefährlich und schwierig werden. Dein erstes Ziel ist\n"
     294"die Insel Mogorok, auch bekannt als Tutorial Island. Den Weisen\n"
     295"zufolge war diese Insel immer der erste Anlaufpunkt für Pingus,\n"
     296"die in die Welt gesandt wurden."
     297
     298#: src/story.cxx:148
     299msgid ""
     300"The island consists of many areas that are ideal to teach the\n"
     301"Pingus their abilities. The Pingus can learn to build\n"
     302"bridges, climb, bash and use many other talents which they\n"
     303"will need on their long and dangerous journey."
     304msgstr ""
     305"Die Insel besteht aus verschiedenen Regionen, die ideal sind, um die\n"
     306"Fähigkeiten der Pingus zu trainieren. Sie können dort ihre Fähig-\n"
     307"keiten im Brückenbau, klettern, graben und all die anderen Talente\n"
     308"trainieren, die sie sicher auf der langen und gefährlichen Reise\n"
     309"benötigen werden."
     310
     311#: src/story.cxx:158
     312msgid ""
     313"While there, you can practice your abilities in commanding\n"
     314"and guiding the Pingus. You can also get familiar with\n"
     315"all the abilities the Pingus provide and learn to master them,\n"
     316"since you will need all of them on your journey around the\n"
     317"world."
     318msgstr ""
     319"Währenddessen kannst Du auf der anderen Seite deine Fähigkeit, die\n"
     320"Pingus zu leiten und zu führen, trainieren. Du kannst dich dort auch mit\n"
     321"allen Fähigkeiten vertraut machen, die die Pingus besitzen und\n"
     322"erlernen, sie zu meistern, denn du wirst sie sicher alle auf der\n"
     323"Reise um die Welt benötigen."
     324
     325#: src/story.cxx:169
     326msgid ""
     327"Now that you and the Pingus have arrived at Tutorial Island it\n"
     328"is time to take command and begin your mission.\n"
     329"\n"
     330"Good Luck!"
     331msgstr ""
     332"Nun da du und die Pingus im Tutorial Island angekommen sind,\n"
     333"musst du das Kommando übernehmen und deine Mission beginnen.\n"
     334"\n"
     335"Viel Glück!"
     336
     337#: src/system.cxx:273
     338msgid "Environment variable $HOME not set, fix that and start again."
     339msgstr ""
     340"Umgebungs Variable $HOME ist nicht gesetzt. Setze sie und starte erneut."
     341
     342#: src/worldmap/level_dot.cxx:174 src/worldmap/level_dot.cxx:184
     343msgid "locked"
     344msgstr "gesperrt"
     345
     346#: src/worldmap/manager.cxx:103
     347msgid "Show Ending?"
     348msgstr "Ende anzeigen?"
     349
     350#: src/worldmap/manager.cxx:133
     351msgid "Show Story?"
     352msgstr "Story zeigen?"
     353
     354#: src/worldmap/manager.cxx:161
     355msgid "Leave?"
     356msgstr "Verlassen?"
     357
     358#: src/worldmap/manager.cxx:201
     359msgid "Enter?"
     360msgstr "Betreten?"
     361
     362#: src/worldmap/worldmap.cxx:77
     363msgid "WorldMap: File not found: "
     364msgstr "Worldmap: Datei nicht gefunden: "
     365
     366#: src/worldmap/worldmap.cxx:261
     367msgid "...walking..."
     368msgstr "...laufe..."
     369
     370msgid "You got %d error.\n"
     371msgid_plural "You got %d error.\n"
     372msgstr[0] "Du hast %d fehler\n"
     373msgstr[1] "Du hast %d fehlers\n"
     374
     375msgid "found %d fatal error"
     376msgid_plural "found %d fatal errors"
     377msgstr[0] "s'ha trobat %d error fatal"
     378msgstr[1] "s'han trobat %d errors fatals"
     379
  • new file libraries/source/tinygettext/test/po/de.po

    diff --git a/libraries/source/tinygettext/test/po/de.po b/libraries/source/tinygettext/test/po/de.po
    new file mode 100644
    index 0000000..e863f81
    - +  
     1# SOME DESCRIPTIVE TITLE.
     2# Copyright (C) YEAR Free Software Foundation, Inc.
     3# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
     4#
     5msgid ""
     6msgstr ""
     7"Project-Id-Version: Pingus 0.6.0\n"
     8"Report-Msgid-Bugs-To: \n"
     9"POT-Creation-Date: 2004-04-09 18:37+0000\n"
     10"PO-Revision-Date: 2009-02-01 17:44+0100\n"
     11"Last-Translator: David Philippi <david@torangan.de>\n"
     12"Language-Team: David Philippi <david@torangan.de>, Ingo Ruhnke <grumbel@gmx.de>, Giray Devlet <giray@devlet.cc>\n"
     13"MIME-Version: 1.0\n"
     14"Plural-Forms: nplurals=2; plural=(n != 1);\n"
     15"Content-Type: text/plain; charset=UTF-8\n"
     16"Content-Transfer-Encoding: 8bit\n"
     17
     18msgid "umlaut"
     19msgstr "ÄÖÜäöüß"
     20
     21#: src/actions/bridger.cxx:48 src/actions/bridger.cxx:232
     22#: src/pingu_enums.cxx:40
     23msgid "Bridger"
     24msgstr "Bridger"
     25
     26#: src/config.cxx:73
     27msgid "Couldn't open: "
     28msgstr "Datei oder Verzeichnis konnte nicht geöffnet werden: "
     29
     30#: src/config.cxx:172
     31msgid "Unexpected char: '"
     32msgstr "Unerwartetes Zeichen: '"
     33
     34#: src/config.cxx:206
     35msgid "Unexpected char '"
     36msgstr "Unerwartetes Zeichen: '"
     37
     38#: src/credits.cxx:48
     39msgid "-Idea"
     40msgstr "-Idee"
     41
     42#: src/credits.cxx:52
     43msgid "-Maintaining"
     44msgstr "-Verwaltung"
     45
     46#: src/credits.cxx:56
     47msgid "-Programming"
     48msgstr "-Programmierung"
     49
     50#: src/credits.cxx:62
     51msgid "-Porting (Win32)"
     52msgstr "-Portierung (Win32)"
     53
     54#: src/credits.cxx:70
     55msgid "-Gfx"
     56msgstr "-Grafiken"
     57
     58#: src/credits.cxx:82
     59msgid "-Music"
     60msgstr "-Musik"
     61
     62#: src/credits.cxx:88
     63msgid "-Level Design"
     64msgstr "-Level Design"
     65
     66#: src/credits.cxx:93
     67msgid "-Story"
     68msgstr "-Geschichte"
     69
     70#: src/credits.cxx:97
     71msgid "-Translation"
     72msgstr "-Übersetzung"
     73
     74#: src/credits.cxx:112
     75msgid "-Special"
     76msgstr "-Besonderen"
     77
     78#: src/credits.cxx:113
     79msgid "-Thanks to"
     80msgstr "-Dank an"
     81
     82#: src/credits.cxx:154
     83msgid "_And a very Special Thanks"
     84msgstr "_Und einen besonderen Dank"
     85
     86#: src/credits.cxx:155
     87msgid "_to all the people who"
     88msgstr "_an alle Leute die"
     89
     90#: src/credits.cxx:156
     91msgid "_contribute to"
     92msgstr "_an Freier Software"
     93
     94#: src/credits.cxx:157
     95msgid "_Free Software!"
     96msgstr "_mitarbeiten!"
     97
     98#: src/credits.cxx:163
     99msgid "_Thank you for"
     100msgstr "_Dankeschön fürs"
     101
     102#: src/credits.cxx:164
     103msgid "_playing!"
     104msgstr "_spielen!"
     105
     106#: src/editor/editor_event.cxx:588
     107msgid "Enter filename to save as:"
     108msgstr "Datei speichern als:  "
     109
     110#: src/editor/editor_help_screen.cxx:43
     111msgid "Editor Helpscreen (hide with F1)"
     112msgstr "Editor Hilfe (ausblenden mit F1)"
     113
     114#: src/editor/editor_help_screen.cxx:51
     115msgid "F1 - show/hide this help screen"
     116msgstr "F1 - Hilfe anzeigen/verstecken"
     117
     118#: src/editor/editor_help_screen.cxx:52
     119msgid "F2 - launch level building tutorial"
     120msgstr "F2 - Starte Levelbau Tutorial"
     121
     122#: src/editor/editor_help_screen.cxx:53
     123msgid "F3 - toggle background color"
     124msgstr "F3 - Hintergrundfarbe aendern"
     125
     126#: src/editor/editor_help_screen.cxx:54
     127msgid "F4 - play/test the level"
     128msgstr "F4 - Level starten/testen"
     129
     130#: src/editor/editor_help_screen.cxx:55
     131msgid "F5 - load a level"
     132msgstr "Level Laden (F5)"
     133
     134#: src/editor/editor_help_screen.cxx:56
     135msgid "F6 - save this level"
     136msgstr "Level Speichern (F6)"
     137
     138#: src/editor/editor_help_screen.cxx:57
     139msgid "F7 - [unset]"
     140msgstr "F7 - [nicht belegt]"
     141
     142#: src/editor/editor_help_screen.cxx:58
     143msgid "F8 - quick save/backup save?!"
     144msgstr "F8 - Schnellspeichern/Backup"
     145
     146#: src/editor/editor_help_screen.cxx:59
     147msgid "F9 - change level width and height"
     148msgstr "F9 - Level Höhe und Breite ändern"
     149
     150#: src/editor/editor_help_screen.cxx:60
     151msgid "F10 - [unset]"
     152msgstr "F10 - [nicht belegt]"
     153
     154#: src/editor/editor_help_screen.cxx:61
     155msgid "F11 - toggle fps counter"
     156msgstr "F11 - fps Zähler an/aus"
     157
     158#: src/editor/editor_help_screen.cxx:62
     159msgid "F12 - make screenshot"
     160msgstr "F12 - Screenshot erstellen"
     161
     162#: src/editor/editor_help_screen.cxx:66
     163msgid "Home - increase object size"
     164msgstr "Einfg - Objekt vergrößern"
     165
     166#: src/editor/editor_help_screen.cxx:67
     167msgid "End  - decrease object size"
     168msgstr "Ende - Objekt verkleinern"
     169
     170#: src/editor/editor_help_screen.cxx:68
     171msgid "Cursor Keys - Move object"
     172msgstr "Cursor Tasten - Objekt bewegen"
     173
     174#: src/editor/editor_help_screen.cxx:69
     175msgid "Shift 'Cursor Keys' - Move objects fast "
     176msgstr "Shift Cursor Tasten - Objekt schneller bewegen"
     177
     178#: src/editor/editor_help_screen.cxx:70
     179msgid "PageUp   - level object up"
     180msgstr "Bild rauf - Objekt nach oben"
     181
     182#: src/editor/editor_help_screen.cxx:71
     183msgid "PageDown - level object down"
     184msgstr "Bild runter - Objekt nach unten"
     185
     186#: src/editor/editor_help_screen.cxx:72
     187msgid "Shift PageUp   - increase objects z-pos by 50"
     188msgstr "Shift Bild rauf - Objekt nach oben"
     189
     190#: src/editor/editor_help_screen.cxx:73
     191msgid "Shift PageDown - decrease objects z-pos by 50"
     192msgstr "Shift Bild runter - Objekt nach unten"
     193
     194#: src/editor/editor_help_screen.cxx:74
     195msgid "Enter - Set default zoom (1:1)"
     196msgstr "Eingabe - Setze Standard Zoom (1:1)"
     197
     198#: src/editor/editor_help_screen.cxx:75
     199msgid "d - duplicate object"
     200msgstr "d - Objekt kopieren"
     201
     202#: src/editor/editor_help_screen.cxx:76
     203msgid "a - mark all objects"
     204msgstr "a - Alle Objekte markieren"
     205
     206#: src/editor/editor_help_screen.cxx:77
     207msgid "shift leftmouseclick - add object to selection"
     208msgstr "Shift + linke Maustaste - Objekt zur Auswahl tun"
     209
     210#: src/editor/editor_help_screen.cxx:78
     211msgid "leftmouseclick - select object"
     212msgstr "linke Maustaste - Objekt auswählen"
     213
     214#: src/editor/editor_help_screen.cxx:79
     215msgid "Insert - insert new object"
     216msgstr "Einfügen - neues Objekt einfügen"
     217
     218#: src/editor/editor_help_screen.cxx:80
     219msgid "Remove - remove selected object"
     220msgstr "Entfernen - entferne ausgewähltes Objekt"
     221
     222#: src/editor/editor_help_screen.cxx:81
     223msgid "g - ungroup/group current selection"
     224msgstr "g - Auswahl gruppieren / Gruppierung aufheben"
     225
     226#: src/editor/editor_help_screen.cxx:82
     227msgid "Ctrl PageUp   - increase objects z-pos by 1"
     228msgstr "Strg Bild rauf - z-pos des Objekts um 1 erhöhen"
     229
     230#: src/editor/editor_help_screen.cxx:83
     231msgid "Ctrl PageDown - decrease objects z-pos by 1"
     232msgstr "Strg Bild runter - z-pos des Objekts um 1 senken"
     233
     234#: src/editor/editor_help_screen.cxx:89
     235msgid "Naming Convention: <LEVELNAME><NUMBER>-<CREATOR>.plf"
     236msgstr "Dateinamensvorgabe: <LEVELNAME><NUMMER>-<AUTOR>.pfl"
     237
     238#: src/editor/editor_help_screen.cxx:91
     239msgid ""
     240"When you have created a level and want to have it in the next Pingus "
     241"release,\n"
     242"please mail it to pingus-devel@nongnu.org."
     243msgstr ""
     244"Falls Du einen Level erstellt hast und ihn gerne im nächsten Pingus\n"
     245"Release hättest, schicke ihn an pingus-devel@nongnu.org."
     246
     247#: src/editor/object_selector.cxx:106
     248msgid "1 - guillotine"
     249msgstr "1 - Guillotine"
     250
     251#: src/editor/object_selector.cxx:107
     252msgid "2 - hammer"
     253msgstr "2 - Hammer"
     254
     255#: src/editor/object_selector.cxx:108
     256msgid "3 - spike"
     257msgstr "3 - Stacheln"
     258
     259#: src/editor/object_selector.cxx:109
     260msgid "4 - laser_exit"
     261msgstr "4 - Laser Ausgang"
     262
     263#: src/editor/object_selector.cxx:110
     264msgid "5 - fake_exit"
     265msgstr "5 - Täusch Ausgang"
     266
     267#: src/editor/object_selector.cxx:111
     268msgid "6 - smasher"
     269msgstr "6 - Stampfer"
     270
     271#: src/editor/object_selector.cxx:112
     272msgid "7 - bumper"
     273msgstr "7 - Stosser"
     274
     275#: src/editor/object_selector.cxx:186
     276msgid "Select a WorldObj"
     277msgstr "Wähle ein WeltObjekt"
     278
     279#: src/editor/object_selector.cxx:187
     280msgid "1 - teleporter"
     281msgstr "1 - Teleporter"
     282
     283#: src/editor/object_selector.cxx:188
     284msgid "2 - switch and door"
     285msgstr "2 - Schalter und Tür"
     286
     287#: src/editor/object_selector.cxx:189
     288msgid "3 - ConveyorBelt"
     289msgstr "3 - Förderband"
     290
     291#: src/editor/object_selector.cxx:190
     292msgid "4 - IceBlock"
     293msgstr "4 - Eisblock"
     294
     295#: src/editor/object_selector.cxx:191
     296msgid "5 - InfoBox"
     297msgstr "5 - InfoBox"
     298
     299#: src/editor/object_selector.cxx:232
     300msgid "Select a weather"
     301msgstr "Wähle ein Wetter"
     302
     303#: src/editor/object_selector.cxx:233
     304msgid "1 - snow"
     305msgstr "1 - Schnee"
     306
     307#: src/editor/object_selector.cxx:234
     308msgid "2 - rain"
     309msgstr "2 - Regen"
     310
     311#: src/editor/object_selector.cxx:265
     312msgid "Select an entrance"
     313msgstr "Wähle einen Eingang"
     314
     315#: src/editor/object_selector.cxx:266
     316msgid "1 - generic"
     317msgstr "1 - allgemein"
     318
     319#: src/editor/object_selector.cxx:267
     320msgid "2 - woodthing"
     321msgstr "2 - hölzern"
     322
     323#: src/editor/object_selector.cxx:268
     324msgid "3 - cloud"
     325msgstr "3 - Wolke"
     326
     327#: src/editor/object_selector.cxx:269
     328msgid "h - entrance surface (hotspot)"
     329msgstr "h - Eingangs Grafik (hotspot)"
     330
     331#: src/editor/object_selector.cxx:343
     332msgid "What object type do you want?"
     333msgstr "Was für ein Objekt willst du?"
     334
     335#: src/editor/object_selector.cxx:344 src/editor/object_selector.cxx:400
     336msgid "h - Hotspot"
     337msgstr "h - Grafikelement (hotspot)"
     338
     339#: src/editor/object_selector.cxx:345
     340msgid "g - Groundpiece (ground) [not implemented]"
     341msgstr "g - Bodenstück (ground) [nicht implementiert]"
     342
     343#: src/editor/object_selector.cxx:394 src/editor/object_selector.cxx:562
     344msgid "Which object do you want?"
     345msgstr "Welches Objekt willst du?"
     346
     347#: src/editor/object_selector.cxx:395
     348msgid "g - Groundpiece (ground)"
     349msgstr "g - Bodenstück (ground)"
     350
     351#: src/editor/object_selector.cxx:396
     352msgid "s - Groundpiece (solid)"
     353msgstr "s - Bodenelement (Stahl)"
     354
     355#: src/editor/object_selector.cxx:397
     356msgid "b - Groundpiece (bridge)"
     357msgstr "b - Bodenelement (Bruecke)"
     358
     359#: src/editor/object_selector.cxx:398
     360msgid "n - Groundpiece (transparent)"
     361msgstr "n - Bodenelement (transparent)"
     362
     363#: src/editor/object_selector.cxx:399
     364msgid "r - Groundpiece (remove)"
     365msgstr "r - Bodenelement (entfernen)"
     366
     367#: src/editor/object_selector.cxx:401
     368msgid "e - Entrance"
     369msgstr "e - Eingang"
     370
     371#: src/editor/object_selector.cxx:402
     372msgid "x - Exit"
     373msgstr "x - Ausgang"
     374
     375#: src/editor/object_selector.cxx:403
     376msgid "l - Liquid"
     377msgstr "l - Flüssigkeit"
     378
     379#: src/editor/object_selector.cxx:404
     380msgid "w - Weather"
     381msgstr "w - Wetter"
     382
     383#: src/editor/object_selector.cxx:405
     384msgid "t - Traps"
     385msgstr "t - Falle"
     386
     387#: src/editor/object_selector.cxx:406
     388msgid "o - WorldObject"
     389msgstr "o - WeltObjekt"
     390
     391#: src/editor/object_selector.cxx:407
     392msgid "z - Background"
     393msgstr "z - Hintergrund"
     394
     395#: src/editor/object_selector.cxx:408
     396msgid "p - Prefab (ObjectGroup)"
     397msgstr "p - Prefab (Objekt Gruppe)"
     398
     399#: src/editor/object_selector.cxx:409
     400msgid "f - something from file (~/.pingus/images/)"
     401msgstr "f - etwas aus einer Datei (~/.pingus/images/)"
     402
     403#: src/editor/object_selector.cxx:498
     404msgid "Which prefab do you want?"
     405msgstr "Welche Prefab willst du?"
     406
     407#: src/editor/object_selector.cxx:563
     408msgid "1 - Surface Background"
     409msgstr "1 - Bild Hintergrund"
     410
     411#: src/editor/object_selector.cxx:564
     412msgid "2 - Solid Color Background"
     413msgstr "2 - Farb Hintergrund"
     414
     415#: src/editor/object_selector.cxx:565
     416msgid "3 - Starfield Background"
     417msgstr "3 - Sternen Hintergrund"
     418
     419#: src/editor/object_selector.cxx:566
     420msgid "4 - Thunderstorm Background"
     421msgstr "4 - Gewitter Hintergrund"
     422
     423#: src/editor/panel_icons.cxx:33
     424msgid "Load a level (F5)"
     425msgstr "Level laden (F5)"
     426
     427#: src/editor/panel_icons.cxx:46
     428msgid "Exit the editor (Escape)"
     429msgstr "Editor Beenden (Esc)"
     430
     431#: src/editor/panel_icons.cxx:58
     432msgid "Save this level (F6)"
     433msgstr "Level Speichern (F6)"
     434
     435#: src/editor/panel_icons.cxx:70
     436msgid "Delete marked objects (delete)"
     437msgstr "Markierte Objekte Löschen (Entfernen)"
     438
     439#: src/editor/panel_icons.cxx:82
     440msgid "Duplicate current object (d)"
     441msgstr "Aktuelles Object kopieren (d)"
     442
     443#: src/editor/panel_icons.cxx:94
     444msgid "Edit Level Properties"
     445msgstr "Leveleigenschaften ändern"
     446
     447#: src/editor/panel_icons.cxx:106
     448msgid "Edit Object Properties"
     449msgstr "Objekteigenschaften ändern"
     450
     451#: src/editor/panel_icons.cxx:118
     452msgid "Start the level and test it (F4)"
     453msgstr "Level starten und testen (F4)"
     454
     455#: src/editor/panel_icons.cxx:130
     456msgid "Create a new level from scratch"
     457msgstr "Neuen Level erstellen"
     458
     459#: src/editor/panel_icons.cxx:142
     460msgid "Insert an object (Insert)"
     461msgstr "Objekt einfuegen (Einfg)"
     462
     463#: src/editor/panel_icons.cxx:154
     464msgid "Zoom into a region"
     465msgstr "Einen Bereich vergrössern"
     466
     467#: src/editor/panel_icons.cxx:166
     468msgid "Zoom in"
     469msgstr "Vergroessern"
     470
     471#: src/editor/panel_icons.cxx:179
     472msgid "Zoom out"
     473msgstr "Verkleinern"
     474
     475#: src/editor/panel_icons.cxx:192
     476msgid "Setup Number of Actions"
     477msgstr "Stelle die Anzahl der Fähigkeiten ein"
     478
     479#: src/editor/panel_icons.cxx:204
     480msgid "Display Help Screen (F1)"
     481msgstr "Hilfe Anzeigen (F1)"
     482
     483#: src/exit_menu.cxx:48
     484msgid "Yes"
     485msgstr "Ja"
     486
     487#: src/exit_menu.cxx:81
     488msgid "No"
     489msgstr "Nein"
     490
     491#: src/exit_menu.cxx:114
     492msgid "Exit Pingus?"
     493msgstr "Pingus beenden?"
     494
     495#: src/fps_counter.cxx:48
     496msgid "unknown"
     497msgstr "unbekannt"
     498
     499#: src/game_time.cxx:70
     500msgid "unlimited"
     501msgstr "unbegrenzt"
     502
     503#: src/level_desc.cxx:74
     504msgid "Designed by "
     505msgstr "Erstellt von "
     506
     507#: src/level_desc.cxx:79
     508#, c-format
     509msgid "Pingus to Save: %d"
     510msgstr "Zu rettende Pingus: %d"
     511
     512#: src/level_desc.cxx:81
     513#, c-format
     514msgid "Number of Pingus: %d"
     515msgstr "Anzahl an Pingus: %d"
     516
     517#: src/level_desc.cxx:86
     518msgid "Loading..."
     519msgstr "Ladevorgang läuft..."
     520
     521#: src/level_desc.cxx:89
     522msgid "Loading finished. Press a mouse button to start the level"
     523msgstr ""
     524"Ladevorgang abgeschlossen. Drücke eine Maus Taste um den Level zu starten"
     525
     526#: src/level_result.cxx:61
     527msgid "Results:"
     528msgstr "Ergebnisse:"
     529
     530#: src/level_result.cxx:67
     531#, c-format
     532msgid "Pingus saved:   %3d/%3d"
     533msgstr "Gerettete Pingus: %3d/%3d"
     534
     535#: src/level_result.cxx:72
     536#, c-format
     537msgid "Pingus died:  %3d/%3d"
     538msgstr "Tote Pingus: %3d/%3d"
     539
     540#: src/level_result.cxx:88
     541msgid "Press button to continue..."
     542msgstr "Knopf drücken um fortzufahren"
     543
     544#: src/level_result.cxx:102
     545msgid ""
     546"As many Pingus escaped as entered the level. That's going to be hard to "
     547"beat.... unless this game becomes pornographic."
     548msgstr ""
     549"Es wurden alle Pingu dieses Levels gerettet. Das wird hart zu schlagen "
     550"sein... es sei denn dieses Spiel wird pornographisch."
     551
     552#: src/level_result.cxx:104
     553msgid "Very impressive indeed."
     554msgstr "In der Tat sehr eindrucksvoll."
     555
     556#: src/level_result.cxx:106
     557msgid "Good work. Still room for improvement though."
     558msgstr "Gute Arbeit. Aber Übung macht den Meiser!"
     559
     560#: src/level_result.cxx:108
     561msgid "Not too shabby, not too shabby at all."
     562msgstr "Nicht schlecht, nicht schlecht!"
     563
     564#: src/level_result.cxx:110
     565msgid ""
     566"That was OK, but Pingu life insurance premiums have just gotten more "
     567"expensive."
     568msgstr ""
     569"Das war ok, aber die Lebensversicherungsprämien für Pingus sind gerade "
     570"gestiegen."
     571
     572#: src/level_result.cxx:112
     573msgid "Maybe this level calls for a different strategy."
     574msgstr "Möglicherweise verlangt dieser Level eine andere Strategie."
     575
     576#: src/level_result.cxx:114
     577msgid "Exactly half. Are you saving only the female ones?"
     578msgstr "Genau die Hälfte! Rettest du nur die Weibchen?"
     579
     580#: src/level_result.cxx:116
     581msgid "If I were a Pingu, I never would have left that entrance."
     582msgstr "Wenn ich ein Pingu wäre, hätte ich den Eingang nie verlassen."
     583
     584#: src/level_result.cxx:118
     585msgid "Maybe you would feel more at home playing Quake."
     586msgstr "Möglicherweise wäre es besser Quake zu spielen?"
     587
     588#: src/level_result.cxx:120
     589msgid ""
     590"Maybe this level calls for a different strategy. Like attempting to save "
     591"them, for example."
     592msgstr ""
     593"Es kann sein, dass wir etwas anderes versuchen sollten.  Vielleicht könnten "
     594"wir ja die Pingus retten?"
     595
     596#: src/level_result.cxx:122
     597msgid "Ever considered a career as a Pingu exterminator?"
     598msgstr "Hast du mal über eine Karriere als Pingu Zerstörer nachgedacht?"
     599
     600#: src/level_result.cxx:124
     601msgid "You missed one! What's your excuse!?"
     602msgstr "Du hast einen vergessen! Was ist deine Entschuldigung?"
     603
     604#: src/level_result.cxx:126
     605msgid "Please reassure me that you hit the Armageddon button."
     606msgstr "Bestätige mir bitte, dass das die Armageddon Taste war."
     607
     608#: src/level_result.cxx:128
     609msgid "You've got a negative save/total value, something is buggy."
     610msgstr "Ein negativer Wert? Hier liegt ein Fehler vor."
     611
     612#: src/menu_button.cxx:181
     613msgid "..:: The people who brought this game to you ::.."
     614msgstr "..:: Die Leute, die fuer dieses Spiel verantwortlich sind... ::.."
     615
     616#: src/menu_button.cxx:184
     617msgid "Credits"
     618msgstr "Mitwirkende"
     619
     620#: src/menu_button.cxx:216
     621msgid "..:: Takes you to the options menu ::.."
     622msgstr "..:: Einstellungen, Cheats und Debugging stuff ::.."
     623
     624#: src/menu_button.cxx:219
     625msgid "Options"
     626msgstr "Einstellungen"
     627
     628#: src/menu_button.cxx:252
     629msgid "..:: Bye, bye ::.."
     630msgstr "..:: Auf Wiedersehen ::.."
     631
     632#: src/menu_button.cxx:255
     633msgid "Exit"
     634msgstr "Beenden"
     635
     636#: src/menu_button.cxx:306
     637msgid "..:: Launch the level editor ::.."
     638msgstr "..:: Erstelle deinen eigenen Level ::.."
     639
     640#: src/menu_button.cxx:309
     641msgid "Create a"
     642msgstr "Bau einen"
     643
     644#: src/menu_button.cxx:310
     645msgid "Level"
     646msgstr "Level"
     647
     648#: src/menu_button.cxx:344
     649msgid "..:: Start the game ::.."
     650msgstr "..:: das Spiel starten ::.."
     651
     652#: src/menu_button.cxx:345
     653msgid "Start"
     654msgstr "Start"
     655
     656#: src/menu_button.cxx:375
     657msgid "..:: Start a contrib level ::.."
     658msgstr "..:: Contrib level Spielen ::.."
     659
     660#: src/menu_button.cxx:377
     661msgid "Contrib"
     662msgstr "Levels"
     663
     664#: src/menu_button.cxx:399
     665msgid "..:: Multiplayer Modes... experimental stuff ::.."
     666msgstr "..:: Mehrspieler Modus ::.. Experimentelles Zeug ::.."
     667
     668#: src/menu_button.cxx:401
     669msgid "Multi"
     670msgstr "Multi"
     671
     672#: src/pingu_enums.cxx:35
     673msgid "Angel"
     674msgstr "Angel"
     675
     676#: src/pingu_enums.cxx:36
     677msgid "Basher"
     678msgstr "Basher"
     679
     680#: src/pingu_enums.cxx:37
     681msgid "Blocker"
     682msgstr "Blocker"
     683
     684#: src/pingu_enums.cxx:38
     685msgid "Boarder"
     686msgstr "Boarder"
     687
     688#: src/pingu_enums.cxx:39
     689msgid "Bomber"
     690msgstr "Bomber"
     691
     692#: src/pingu_enums.cxx:41
     693msgid "Climber"
     694msgstr "Climber"
     695
     696#: src/pingu_enums.cxx:42
     697msgid "Digger"
     698msgstr "Digger"
     699
     700#: src/pingu_enums.cxx:43
     701msgid "Drown"
     702msgstr "Drown"
     703
     704#: src/pingu_enums.cxx:44
     705msgid "Exiter"
     706msgstr "Exiter"
     707
     708#: src/pingu_enums.cxx:45
     709msgid "Faller"
     710msgstr "Faller"
     711
     712#: src/pingu_enums.cxx:46
     713msgid "Floater"
     714msgstr "Floater"
     715
     716#: src/pingu_enums.cxx:47
     717msgid "Jumper"
     718msgstr "Jumper"
     719
     720#: src/pingu_enums.cxx:48
     721msgid "Laserkill"
     722msgstr "Laserkill"
     723
     724#: src/pingu_enums.cxx:49
     725msgid "Miner"
     726msgstr "Miner"
     727
     728#: src/pingu_enums.cxx:50
     729msgid "Rocketlauncher"
     730msgstr "Rocketlauncher"
     731
     732#: src/pingu_enums.cxx:51
     733msgid "Slider"
     734msgstr "Slider"
     735
     736#: src/pingu_enums.cxx:52
     737msgid "Smashed"
     738msgstr "Smashed"
     739
     740#: src/pingu_enums.cxx:53
     741msgid "Splashed"
     742msgstr "Splashed"
     743
     744#: src/pingu_enums.cxx:54
     745msgid "Superman"
     746msgstr "Superman"
     747
     748#: src/pingu_enums.cxx:55
     749msgid "Teleported"
     750msgstr "Teleported"
     751
     752#: src/pingu_enums.cxx:56
     753msgid "Waiter"
     754msgstr "Waiter"
     755
     756#: src/pingu_enums.cxx:57
     757msgid "Walker"
     758msgstr "Walker"
     759
     760#: src/pingus_counter.cxx:52
     761#, c-format
     762msgid "Released:%3d/%-3d   Out:%3d   Saved:%3d/%-3d"
     763msgstr "Rein: %3d/%-3d  Raus: %3d Gerettet: %3d/%-3d"
     764
     765#: src/pingus_main.cxx:90
     766msgid "| segfault_handler: catched a SIGSEGV."
     767msgstr "| segfault_handler: SIGSEGV abgefangen."
     768
     769#: src/pingus_main.cxx:92
     770msgid "| Woops, Pingus just crashed, congratulations you've found a bug."
     771msgstr ""
     772"| Woops, Pingus ist abgestürzt. Gratuliere, du hast einen Bug gefunden."
     773
     774#: src/pingus_main.cxx:93
     775msgid ""
     776"| Please write a little bug report to <grumbel@gmx.de>, include informations"
     777msgstr ""
     778"| Bitte schreibe einen kleinen Report an <pingus-devel@nongnu.org, mit "
     779"Informationen,"
     780
     781#: src/pingus_main.cxx:94
     782msgid "| where exacly the SIGSEGV occured and how to reproduce it."
     783msgstr "| wo genau der SIGSEGV auftrat und wie man ihn reproduziert."
     784
     785#: src/pingus_main.cxx:95
     786msgid "| Also try include a backtrace, you can get it like this:"
     787msgstr "| Versuche auch einen backtrace zu erstellen, du bekommst ihn so:"
     788
     789#: src/pingus_main.cxx:101
     790msgid "| If that doesn't work, try this:"
     791msgstr "| Wenn das nicht geht, versuche dies:"
     792
     793#: src/pingus_main.cxx:105
     794msgid "| [play until it crashes again]"
     795msgstr "| [spiele bis es wieder crasht]"
     796
     797#: src/pingus_main.cxx:113
     798msgid "| Warning: Pingus recieved a SIGINT, exiting now."
     799msgstr "| Warnung: Pingus erhielt einen SIGINT, beende jetzt."
     800
     801#: src/pingus_main.cxx:301
     802msgid "Warning: Larger resolution than 800x600 will result in visual problems"
     803msgstr ""
     804"Warnung: Auflösungen grösser als 800x600 können zu visuellen Problemen führen"
     805
     806#: src/pingus_main.cxx:488
     807msgid "Unknow char: "
     808msgstr "Unbekannter Buchstabe: "
     809
     810#: src/pingus_main.cxx:489
     811msgid "Usage: "
     812msgstr "Benutzung: "
     813
     814#: src/pingus_main.cxx:489
     815msgid " [OPTIONS]... [LEVELFILE]"
     816msgstr "[OPTIONEN]... [LEVELDATEI]"
     817
     818#: src/pingus_main.cxx:492
     819msgid "Options:"
     820msgstr "Einstellungen"
     821
     822#: src/pingus_main.cxx:494
     823msgid "Set the resolution for pingus (default: 800x600)"
     824msgstr "Setze die Auflösung für Pingus (Standard: 800x600)"
     825
     826#: src/pingus_main.cxx:495
     827msgid "Displays this help"
     828msgstr "Hilfe Anzeigen"
     829
     830#: src/pingus_main.cxx:496
     831msgid "Disable intro"
     832msgstr "Intro abschalten"
     833
     834#: src/pingus_main.cxx:497
     835msgid "Use OpenGL"
     836msgstr "OpenGL benutzen"
     837
     838#: src/pingus_main.cxx:499
     839msgid "Start in Window Mode"
     840msgstr "Pingus im Fenster starten"
     841
     842#: src/pingus_main.cxx:500
     843msgid "Start in Fullscreen"
     844msgstr "Pingus im Vollbild starten"
     845
     846#: src/pingus_main.cxx:504
     847msgid "FILE      "
     848msgstr "Datei     "
     849
     850#: src/pingus_main.cxx:504
     851msgid "Load a custom level from FILE"
     852msgstr "Einen Level aus DATEI laden"
     853
     854#: src/pingus_main.cxx:505
     855msgid "FILE        "
     856msgstr "Datei      "
     857
     858#: src/pingus_main.cxx:505
     859msgid "Load a custom worldmap from FILE"
     860msgstr "Eine Weltkarte aus DATEI laden"
     861
     862#: src/pingus_main.cxx:506
     863msgid "Print some more messages to stdout, can be set"
     864msgstr "Gibt mehr Nachrichten auf stdout aus, kann"
     865
     866#: src/pingus_main.cxx:507
     867msgid "multiple times to increase verbosity"
     868msgstr "mehrmals gesetzt werden, um die Genauigkeit zu erhöhen"
     869
     870#: src/pingus_main.cxx:508
     871msgid "Prints version number and exit"
     872msgstr "Version ausgeben und beenden"
     873
     874#: src/pingus_main.cxx:509
     875msgid "Launch the Level editor (experimental)"
     876msgstr "Level Editor starten (Experimentell)"
     877
     878#: src/pingus_main.cxx:510
     879msgid "Disable automatic scrolling"
     880msgstr "Automatisches Scrollen abschalten"
     881
     882#: src/pingus_main.cxx:512
     883msgid "Enable software cursor"
     884msgstr "Aktiviere Software Cursor"
     885
     886#: src/pingus_main.cxx:515
     887msgid "Don't read ~/.pingus/config"
     888msgstr "~/.pingus/config nicht einlesen"
     889
     890#: src/pingus_main.cxx:516
     891msgid "FILE       "
     892msgstr "Datei      "
     893
     894#: src/pingus_main.cxx:516
     895msgid "Read config from FILE (default: ~/.pingus/config)"
     896msgstr "Konfiguration aus DATEI lesen"
     897
     898#: src/pingus_main.cxx:517
     899msgid "reduce CPU usage, might speed up the game on slower machines"
     900msgstr ""
     901"reduziere CPU Belastung, könnte das Spiel auf langsamen Rechnern "
     902"beschleunigen"
     903
     904#: src/pingus_main.cxx:518
     905msgid "Uses the controller given in FILE"
     906msgstr "Controller aus FILE benutzen"
     907
     908#: src/pingus_main.cxx:520
     909msgid "Debugging and experimental stuff:"
     910msgstr "Debug und Experimentelles Zeug"
     911
     912#: src/pingus_main.cxx:521
     913msgid "Enables some features, only interesting programmers"
     914msgstr "Aktiviere einige Funktionen, nur für Programmierer"
     915
     916#: src/pingus_main.cxx:522
     917msgid "Enable the output of debugging infos, possible"
     918msgstr "Aktiviere die Ausgabe von Debug Informationen, mögliche"
     919
     920#: src/pingus_main.cxx:523
     921msgid "OPTION's are tiles, gametime, actions, sound, resources, gui,"
     922msgstr "Optionen sind tiles, gametime, actions, sound, resources, gui,"
     923
     924#: src/pingus_main.cxx:525
     925msgid "Skip at least N frames, larger values speed the game up"
     926msgstr ""
     927"Überspringe mindestens N Bilder, größere Werte erhöhen die Geschwindigkeit"
     928
     929#: src/pingus_main.cxx:526
     930msgid "Skip at most N frames"
     931msgstr "Überspringe maximal N Bilder"
     932
     933#: src/pingus_main.cxx:527
     934msgid "Set both min and max frameskip to N"
     935msgstr "Setze sowohl minimalen als auch maximalen Bildsprung auf N"
     936
     937#: src/pingus_main.cxx:528
     938msgid "Set the game speed (0=fastest, >0=slower)"
     939msgstr "Setze die Geschwindigkeit (0=schnellste, >0=langsamer)"
     940
     941#: src/pingus_main.cxx:529
     942msgid "Prints the fps to stdout"
     943msgstr "Schreibe die fps auf stdout"
     944
     945#: src/pingus_main.cxx:530
     946msgid "Set the size of the map tiles (default: 32)"
     947msgstr "Setze die Größe der Kartenteile (Standard: 32)"
     948
     949#: src/pingus_main.cxx:531
     950msgid "Disable some cpu intensive features"
     951msgstr "Deaktivere einige CPU intensive Funktionen"
     952
     953#: src/pingus_main.cxx:532
     954msgid "Reduces the CPU usage by issuing sleep()"
     955msgstr "Reduziert die CPU Belastung durch Verwendung von sleep()"
     956
     957#: src/pingus_main.cxx:534
     958msgid "Demo playing and recording:"
     959msgstr "Demo aufzeichnung und wiedergabe:"
     960
     961#: src/pingus_main.cxx:535
     962msgid "FILE     "
     963msgstr "Datei    "
     964
     965#: src/pingus_main.cxx:535
     966msgid "Plays a demo session from FILE"
     967msgstr "Spielt eine Demo Sitzung aus FILE"
     968
     969#: src/pingus_main.cxx:537
     970msgid "Record demos for each played level"
     971msgstr "Nehme Demos für jeden gespielten Level auf"
     972
     973#: src/pingus_main.cxx:539
     974msgid "Sound:"
     975msgstr "Sound"
     976
     977#: src/pingus_main.cxx:540
     978msgid "Disable sound"
     979msgstr "Sound deaktivieren"
     980
     981#: src/pingus_main.cxx:541
     982msgid "Disable music"
     983msgstr "Musik deaktivieren"
     984
     985#: src/pingus_main.cxx:720
     986msgid "clanVorbis support:           ok"
     987msgstr "clanVorbis Unterstützung:    ok"
     988
     989#: src/pingus_main.cxx:722
     990msgid "clanVoribs support:  missing (.ogg music files will not be playable)"
     991msgstr ""
     992"clanVorbis Unterstützung: fehlt (.ogg Musik Datein können nicht abgespielt "
     993"werden)"
     994
     995#: src/pingus_main.cxx:726
     996msgid "clanMikMod support:           ok"
     997msgstr "clanMikMod Unterstützung:    ok"
     998
     999#: src/pingus_main.cxx:728
     1000msgid "clanMikMod support:  missing (music files will not be playable)"
     1001msgstr ""
     1002"clanMikMod Untersützung: fehlt (Musikdateien können nicht abgespielt werden)"
     1003
     1004#: src/pingus_main.cxx:732
     1005msgid "getext support:               ok"
     1006msgstr "gettext Unterstützung:       ok"
     1007
     1008#: src/pingus_main.cxx:733
     1009msgid "gettext language:        english"
     1010msgstr "gettext Sprache:        deutsch"
     1011
     1012#: src/pingus_main.cxx:739
     1013msgid "sound support:           enabled"
     1014msgstr "Sound Unterstützung:         an"
     1015
     1016#: src/pingus_main.cxx:741
     1017msgid "sound support:          disabled"
     1018msgstr "Sound Unterstützung:        aus"
     1019
     1020#: src/pingus_main.cxx:744
     1021msgid "music support:           enabled"
     1022msgstr "Musik Unterstützung:         an"
     1023
     1024#: src/pingus_main.cxx:746
     1025msgid "music support:          disabled"
     1026msgstr "Musik Unterstützung:        aus"
     1027
     1028#: src/pingus_main.cxx:748
     1029msgid "resolution set to:       "
     1030msgstr "Auflösung:              "
     1031
     1032#: src/pingus_main.cxx:749
     1033msgid "fullscreen:              "
     1034msgstr "Vollbild:           "
     1035
     1036#: src/pingus_main.cxx:750
     1037msgid " enabled"
     1038msgstr "aktiviert"
     1039
     1040#: src/pingus_main.cxx:750
     1041msgid "disabled"
     1042msgstr "däktiviert"
     1043
     1044
     1045#: src/pingus_main.cxx:751
     1046msgid "reenabled"
     1047msgstr ""
  • new file libraries/source/tinygettext/test/po/de_AT.po

    diff --git a/libraries/source/tinygettext/test/po/de_AT.po b/libraries/source/tinygettext/test/po/de_AT.po
    new file mode 100644
    index 0000000..f4c3d81
    - +  
     1# SOME DESCRIPTIVE TITLE.
     2# Copyright (C) YEAR Free Software Foundation, Inc.
     3# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
     4#
     5#, fuzzy
     6msgid ""
     7msgstr ""
     8"Project-Id-Version: PACKAGE VERSION\n"
     9"PO-Revision-Date: 2009-02-02 12:07+0100\n"
     10"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
     11"Language-Team: LANGUAGE <LL@li.org>\n"
     12"MIME-Version: 1.0\n"
     13"Content-Type: text/plain; charset=UTF-8\n"
     14"Content-Transfer-Encoding: 8bit\n"
     15"Plural-Forms: nplurals=2; plural=( n != 1);\n"
     16
     17msgid "umlaut"
     18msgstr "ÄÖÜäöü߀¢"
     19
     20msgid "You got %d error."
     21msgid_plural "You got %d error."
     22msgstr[0] "Du hast %d fehler"
     23msgstr[1] "Du hast %d fehlers"
     24
     25msgid "found %d fatal error"
     26msgid_plural "found %d fatal errors"
     27msgstr[0] "s'ha trobat %d error fätal"
     28msgstr[1] "s'han trobat %d errors fätals"
     29
     30
     31msgid "I ate %d pizza."
     32msgid_plural "I ate %d pizzas."
     33msgstr[0] ""
  • new file libraries/source/tinygettext/test/po/fr.po

    diff --git a/libraries/source/tinygettext/test/po/fr.po b/libraries/source/tinygettext/test/po/fr.po
    new file mode 100644
    index 0000000..0670f48
    - +  
     1# SOME DESCRIPTIVE TITLE.
     2# Copyright (C) YEAR Free Software Foundation, Inc.
     3# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
     4#
     5#, fuzzy
     6msgid ""
     7msgstr ""
     8"Project-Id-Version: PACKAGE VERSION\n"
     9"PO-Revision-Date: 2009-01-28 08:45+0100\n"
     10"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
     11"Language-Team: LANGUAGE <LL@li.org>\n"
     12"MIME-Version: 1.0\n"
     13"Content-Type: text/plain; charset=utf-8\n"
     14"Content-Transfer-Encoding: 8bit\n"
     15
     16#: src/actions/bridger.cxx:48 src/actions/bridger.cxx:232
     17#: src/pingu_enums.cxx:40
     18msgid "invalid"
     19msgstr "ungütig"
     20
  • new file libraries/source/tinygettext/test/po_parser_test.cpp

    diff --git a/libraries/source/tinygettext/test/po_parser_test.cpp b/libraries/source/tinygettext/test/po_parser_test.cpp
    new file mode 100644
    index 0000000..e8f0ffb
    - +  
     1//  tinygettext - A gettext replacement that works directly on .po files
     2//  Copyright (C) 2009 Ingo Ruhnke <grumbel@gmx.de>
     3//
     4//  This program is free software; you can redistribute it and/or
     5//  modify it under the terms of the GNU General Public License
     6//  as published by the Free Software Foundation; either version 2
     7//  of the License, or (at your option) any later version.
     8//
     9//  This program is distributed in the hope that it will be useful,
     10//  but WITHOUT ANY WARRANTY; without even the implied warranty of
     11//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     12//  GNU General Public License for more details.
     13//
     14//  You should have received a copy of the GNU General Public License
     15//  along with this program; if not, write to the Free Software
     16//  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
     17
     18#include <errno.h>
     19#include <string.h>
     20#include <iostream>
     21#include <fstream>
     22#include <stdexcept>
     23
     24#include "tinygettext/po_parser.hpp"
     25#include "tinygettext/tinygettext.hpp"
     26#include "tinygettext/log.hpp"
     27
     28void my_log_callback(const std::string& err)
     29{
     30  std::cerr << err;
     31}
     32
     33int main(int argc, char** argv)
     34{
     35  if (argc < 2)
     36  {
     37    std::cout << argv[0] << " FILENAME..." << std::endl;
     38  }
     39  else
     40  {
     41    tinygettext::Log::set_log_info_callback(my_log_callback);
     42    tinygettext::Log::set_log_warning_callback(my_log_callback);
     43    tinygettext::Log::set_log_error_callback(my_log_callback);
     44
     45    for(int i = 1; i < argc; ++i)
     46    {
     47      std::ifstream in(argv[i]);
     48      if (!in)
     49      {
     50        std::cerr << argv[0] << ": cannot access " << argv[i] << ": " << strerror(errno) << std::endl;
     51      }
     52      else
     53      {
     54        try
     55        {
     56          tinygettext::Dictionary dict1;
     57          tinygettext::POParser::parse(argv[i], in, dict1);
     58
     59          //tinygettext::Dictionary dict2;
     60          //tinygettext::POFileReader::read(in, dict2);
     61        }
     62        catch(std::runtime_error& err)
     63        {
     64          std::cout << argv[i] << ": exception: " << err.what() << std::endl;
     65        }
     66      }
     67    }
     68  } 
     69}
     70
     71/* EOF */
  • new file libraries/source/tinygettext/test/test.sh

    diff --git a/libraries/source/tinygettext/test/test.sh b/libraries/source/tinygettext/test/test.sh
    new file mode 100644
    index 0000000..a7b7789
    - +  
     1#!/bin/sh
     2
     3./tinygettext_test translate po/fr.po  "invalid"
     4./tinygettext_test directory po/ umlaut Deutsch
     5./tinygettext_test directory po/ umlaut deutsch
     6./tinygettext_test directory po/ umlaut de
     7
     8# EOF #
  • new file libraries/source/tinygettext/test/tinygettext_test.cpp

    diff --git a/libraries/source/tinygettext/test/tinygettext_test.cpp b/libraries/source/tinygettext/test/tinygettext_test.cpp
    new file mode 100644
    index 0000000..c0edb52
    - +  
     1//  TinyGetText
     2//  Copyright (C) 2009 Ingo Ruhnke <grumbel@gmx.de>
     3//
     4//  This program is free software; you can redistribute it and/or
     5//  modify it under the terms of the GNU General Public License
     6//  as published by the Free Software Foundation; either version 2
     7//  of the License, or (at your option) any later version.
     8//
     9//  This program is distributed in the hope that it will be useful,
     10//  but WITHOUT ANY WARRANTY; without even the implied warranty of
     11//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     12//  GNU General Public License for more details.
     13//
     14//  You should have received a copy of the GNU General Public License
     15//  along with this program; if not, write to the Free Software
     16//  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
     17
     18#include <iostream>
     19#include <string.h>
     20#include <fstream>
     21#include <stdlib.h>
     22#include <iostream>
     23#include <stdexcept>
     24#include "tinygettext/po_parser.hpp"
     25#include "tinygettext/tinygettext.hpp"
     26
     27using namespace tinygettext;
     28
     29void print_msg(const std::string& msgid, const std::vector<std::string>& msgstrs)
     30{
     31  std::cout << "Msgid: " << msgid << std::endl;
     32  for(std::vector<std::string>::const_iterator i = msgstrs.begin(); i != msgstrs.end(); ++i)
     33    {
     34      std::cout << *i << std::endl;
     35    }
     36}
     37
     38void print_msg_ctxt(const std::string& ctxt, const std::string& msgid, const std::vector<std::string>& msgstrs)
     39{
     40  std::cout << "Msgctxt: " << ctxt << std::endl;
     41  std::cout << "Msgid: " << msgid << std::endl;
     42  for(std::vector<std::string>::const_iterator i = msgstrs.begin(); i != msgstrs.end(); ++i)
     43    {
     44      std::cout << *i << std::endl;
     45    }
     46}
     47
     48void print_usage(int /*argc*/, char** argv)
     49{
     50  std::cout << "Usage: " << argv[0] << " translate FILE MESSAGE" << std::endl;
     51  std::cout << "       " << argv[0] << " translate FILE MESSAGE_S MESSAGE_P NUM" << std::endl;
     52  std::cout << "       " << argv[0] << " directory DIRECTORY MESSAGE [LANG]" << std::endl;
     53  std::cout << "       " << argv[0] << " language LANGUAGE" << std::endl;
     54  std::cout << "       " << argv[0] << " language-dir DIR" << std::endl;
     55  std::cout << "       " << argv[0] << " list-msgstrs FILE" << std::endl;
     56}
     57
     58void read_dictionary(const std::string& filename, Dictionary& dict)
     59{
     60  std::ifstream in(filename.c_str());
     61 
     62  if (!in)
     63    {
     64      throw std::runtime_error("Couldn't open " + filename);
     65    }
     66  else
     67    {
     68      POParser::parse(filename, in, dict);
     69      in.close();
     70    }
     71}
     72
     73int main(int argc, char** argv)
     74{
     75  try
     76  {
     77    if (argc == 3 && strcmp(argv[1], "language-dir") == 0)
     78    {
     79      DictionaryManager dictionary_manager;
     80      dictionary_manager.add_directory(argv[2]);
     81      const std::set<Language>& languages = dictionary_manager.get_languages();
     82      std::cout << "Number of languages: " << languages.size() << std::endl;
     83      for (std::set<Language>::const_iterator i = languages.begin(); i != languages.end(); ++i)
     84      {
     85        const Language& language = *i;
     86        std::cout << "Env:       " << language.str()           << std::endl
     87                  << "Name:      " << language.get_name()      << std::endl
     88                  << "Language:  " << language.get_language()  << std::endl
     89                  << "Country:   " << language.get_country()   << std::endl
     90                  << "Modifier:  " << language.get_modifier()  << std::endl
     91                  << std::endl;
     92      }
     93    }
     94    else if (argc == 3 && strcmp(argv[1], "language") == 0)
     95    {
     96      Language language = Language::from_name(argv[2]);
     97
     98      if (language)
     99        std::cout << "Env:       " << language.str()           << std::endl
     100                  << "Name:      " << language.get_name()      << std::endl
     101                  << "Language:  " << language.get_language()  << std::endl
     102                  << "Country:   " << language.get_country()   << std::endl
     103                  << "Modifier:  " << language.get_modifier()  << std::endl;
     104      else
     105        std::cout << "not found" << std::endl;
     106    }
     107    else if (argc == 4 && strcmp(argv[1], "translate") == 0)
     108    {
     109      const char* filename = argv[2];
     110      const char* message  = argv[3];
     111
     112      Dictionary dict;
     113      read_dictionary(filename, dict);
     114      std::cout << "TRANSLATION: \"\"\"" << dict.translate(message) << "\"\"\""<< std::endl;
     115    }
     116    else if (argc == 5 && strcmp(argv[1], "translate") == 0)
     117    {
     118      const char* filename = argv[2];
     119      const char* context  = argv[3];
     120      const char* message  = argv[4];
     121
     122      Dictionary dict;
     123      read_dictionary(filename, dict);
     124      std::cout << dict.translate_ctxt(context, message) << std::endl;
     125    }
     126    else if (argc == 6 && strcmp(argv[1], "translate") == 0)
     127    {
     128      const char* filename = argv[2];
     129      const char* message_singular = argv[3];
     130      const char* message_plural   = argv[4];
     131      int num = atoi(argv[5]);
     132
     133      Dictionary dict;
     134      read_dictionary(filename, dict);
     135      std::cout << dict.translate_plural(message_singular, message_plural, num) << std::endl;
     136    }
     137    else if (argc == 7 && strcmp(argv[1], "translate") == 0)
     138    {
     139      const char* filename = argv[2];
     140      const char* context  = argv[3];
     141      const char* message_singular = argv[4];
     142      const char* message_plural   = argv[5];
     143      int num = atoi(argv[6]);
     144
     145      Dictionary dict;
     146      read_dictionary(filename, dict);
     147      std::cout << dict.translate_ctxt_plural(context, message_singular, message_plural, num) << std::endl;
     148    }
     149    else if ((argc == 4 || argc == 5) && strcmp(argv[1], "directory") == 0)
     150    {
     151      const char* directory = argv[2];
     152      const char* message   = argv[3];
     153      const char* language  = (argc == 5) ? argv[4] : NULL;
     154         
     155      DictionaryManager manager;
     156      manager.add_directory(directory);
     157         
     158      if (language)
     159      {
     160        Language lang = Language::from_name(language);
     161        if (lang)
     162        {
     163          manager.set_language(lang);
     164        }
     165        else
     166        {
     167          std::cout << "Unknown language: " << language << std::endl;
     168          exit(EXIT_FAILURE);
     169        }
     170      }
     171
     172      std::cout << "Directory:   '" << directory << "'"  << std::endl;
     173      std::cout << "Message:     '" << message << "'" << std::endl;
     174      std::cout << "Language:    '" << manager.get_language().str() << "' (name: '"
     175                << manager.get_language().get_name() << "', language: '"
     176                << manager.get_language().get_language() << "', country: '"
     177                << manager.get_language().get_country() << "', modifier: '"
     178                << manager.get_language().get_modifier() << "')"
     179                << std::endl;
     180      std::cout << "Translation: '" << manager.get_dictionary().translate(message) << "'" << std::endl;
     181    }
     182    else if ((argc == 3) && strcmp(argv[1], "list-msgstrs") == 0)
     183    {
     184      const char* filename = argv[2];
     185
     186      Dictionary dict;
     187      read_dictionary(filename, dict);
     188      dict.foreach(print_msg);
     189      dict.foreach_ctxt(print_msg_ctxt);
     190    }
     191    else
     192    {
     193      print_usage(argc, argv);
     194    }
     195  }
     196  catch(std::exception& err)
     197  {
     198    std::cout << "Exception: " << err.what() << std::endl;
     199  }
     200 
     201  return 0;
     202}
     203
     204/* EOF */
  • new file libraries/source/tinygettext/tinygettext.pc.in

    diff --git a/libraries/source/tinygettext/tinygettext.pc.in b/libraries/source/tinygettext/tinygettext.pc.in
    new file mode 100644
    index 0000000..ef82a93
    - +  
     1# Unfortunately, since this project is built with cmake,
     2# these variables can't properly be set.
     3
     4prefix=@CMAKE_INSTALL_PREFIX@
     5exec_prefix=${prefix}
     6libdir=${exec_prefix}/@LIB_SUBDIR@
     7includedir=${prefix}/include
     8
     9Name: @PROJECT_NAME@
     10Description: tiny, minimal gettext replacement
     11Version: @VERSION@
     12URL: http://tinygettext.googlecode.com/
     13Requires:
     14Libs: -L${libdir} -ltinygettext
     15Libs.private:
     16Cflags: -I${includedir}
  • new file libraries/source/tinygettext/tinygettext/dictionary.cpp

    diff --git a/libraries/source/tinygettext/tinygettext/dictionary.cpp b/libraries/source/tinygettext/tinygettext/dictionary.cpp
    new file mode 100644
    index 0000000..9765d75
    - +  
     1//  tinygettext - A gettext replacement that works directly on .po files
     2//  Copyright (C) 2006 Ingo Ruhnke <grumbel@gmx.de>
     3//
     4//  This program is free software; you can redistribute it and/or
     5//  modify it under the terms of the GNU General Public License
     6//  as published by the Free Software Foundation; either version 2
     7//  of the License, or (at your option) any later version.
     8//
     9//  This program is distributed in the hope that it will be useful,
     10//  but WITHOUT ANY WARRANTY; without even the implied warranty of
     11//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     12//  GNU General Public License for more details.
     13//
     14//  You should have received a copy of the GNU General Public License
     15//  along with this program; if not, write to the Free Software
     16//  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
     17
     18#include <assert.h>
     19#include "log_stream.hpp"
     20#include "dictionary.hpp"
     21
     22namespace tinygettext {
     23
    024
     25Dictionary::Dictionary(const std::string& charset_) :
     26  entries(),
     27  ctxt_entries(),
     28  charset(charset_),
     29  plural_forms()
     30{
     31}
     32
     33Dictionary::~Dictionary()
     34{
     35}
     36
     37std::string
     38Dictionary::get_charset() const
     39{
     40  return charset;
     41}
     42
     43void
     44Dictionary::set_plural_forms(const PluralForms& plural_forms_)
     45{
     46  plural_forms = plural_forms_;
     47}
     48
     49PluralForms
     50Dictionary::get_plural_forms() const
     51{
     52  return plural_forms;
     53}
     54
     55std::string
     56Dictionary::translate_plural(const std::string& msgid, const std::string& msgid_plural, int num)
     57{
     58  return translate_plural(entries, msgid, msgid_plural, num);
     59}
     60
     61std::string
     62Dictionary::translate_plural(const Entries& dict, const std::string& msgid, const std::string& msgid_plural, int count)
     63{
     64  Entries::const_iterator i = dict.find(msgid);
     65  const std::vector<std::string>& msgstrs = i->second;
     66
     67  if (i != dict.end())
     68  {
     69    unsigned int n = 0;
     70    n = plural_forms.get_plural(count);
     71    assert(/*n >= 0 &&*/ n < msgstrs.size());
     72
     73    if (!msgstrs[n].empty())
     74      return msgstrs[n];
     75    else
     76      if (count == 1) // default to english rules
     77        return msgid;
     78      else
     79        return msgid_plural;
     80  }
     81  else
     82  {
     83    log_info << "Couldn't translate: " << msgid << std::endl;
     84    log_info << "Candidates: " << std::endl;
     85    for (i = dict.begin(); i != dict.end(); ++i)
     86      log_info << "'" << i->first << "'" << std::endl;
     87
     88    if (count == 1) // default to english rules
     89      return msgid;
     90    else
     91      return msgid_plural;
     92  }
     93}
     94
     95std::string
     96Dictionary::translate(const std::string& msgid)
     97{
     98  return translate(entries, msgid);
     99}
     100
     101std::string
     102Dictionary::translate(const Entries& dict, const std::string& msgid)
     103{
     104  Entries::const_iterator i = dict.find(msgid);
     105  if (i != dict.end() && !i->second.empty())
     106  {
     107    return i->second[0];
     108  }
     109  else
     110  {
     111    log_info << "Couldn't translate: " << msgid << std::endl;
     112    return msgid;
     113  }
     114}
     115
     116std::string
     117Dictionary::translate_ctxt(const std::string& msgctxt, const std::string& msgid)
     118{
     119  CtxtEntries::iterator i = ctxt_entries.find(msgctxt);
     120  if (i != ctxt_entries.end())
     121  {
     122    return translate(i->second, msgid);
     123  }
     124  else
     125  {
     126    log_info << "Couldn't translate: " << msgid << std::endl;
     127    return msgid;
     128  }
     129}
     130
     131std::string
     132Dictionary::translate_ctxt_plural(const std::string& msgctxt,
     133                                  const std::string& msgid, const std::string& msgidplural, int num)
     134{
     135  CtxtEntries::iterator i = ctxt_entries.find(msgctxt);
     136  if (i != ctxt_entries.end())
     137  {
     138    return translate_plural(i->second, msgid, msgidplural, num);
     139  }
     140  else
     141  {
     142    log_info << "Couldn't translate: " << msgid << std::endl;
     143    if (num != 1) // default to english
     144      return msgidplural;
     145    else
     146      return msgid;
     147  }
     148}
     149
    1150
     151void
     152Dictionary::add_translation(const std::string& msgid, const std::string& ,
     153                            const std::vector<std::string>& msgstrs)
     154{
     155  // Do we need msgid2 for anything? its after all supplied to the
     156  // translate call, so we just throw it away here
     157  entries[msgid] = msgstrs;
     158}
     159
     160void
     161Dictionary::add_translation(const std::string& msgid, const std::string& msgstr)
     162{
     163  std::vector<std::string>& vec = entries[msgid];
     164  if (vec.empty())
     165  {
     166    vec.push_back(msgstr);
     167  }
     168  else
     169  {
     170    log_warning << "collision in add_translation: '"
     171                << msgid << "' -> '" << msgstr << "' vs '" << vec[0] << "'" << std::endl;
     172    vec[0] = msgstr;
     173  }
     174}
     175
     176void
     177Dictionary::add_translation(const std::string& msgctxt,
     178                            const std::string& msgid, const std::string& msgid_plural,
     179                            const std::vector<std::string>& msgstrs)
     180{
     181  std::vector<std::string>& vec = ctxt_entries[msgctxt][msgid];
     182  if (vec.empty())
     183  {
     184    vec = msgstrs;
     185  }
     186  else
     187  {
     188    log_warning << "collision in add_translation(\"" << msgctxt << "\", \"" << msgid << "\", \"" << msgid_plural << "\")" << std::endl;
     189    vec = msgstrs;
     190  }
     191}
     192
     193void
     194Dictionary::add_translation(const std::string& msgctxt, const std::string& msgid, const std::string& msgstr)
     195{
     196  std::vector<std::string>& vec = ctxt_entries[msgctxt][msgid];
     197  if (vec.empty())
     198  {
     199    vec.push_back(msgstr);
     200  }
     201  else
     202  {
     203    log_warning << "collision in add_translation(\"" << msgctxt << "\", \"" << msgid << "\")" << std::endl;
     204    vec[0] = msgstr;
     205  }
     206}
     207
    2208
  • new file libraries/source/tinygettext/tinygettext/dictionary.hpp

    +} // namespace tinygettext
    +
    +/* EOF */
    diff --git a/libraries/source/tinygettext/tinygettext/dictionary.hpp b/libraries/source/tinygettext/tinygettext/dictionary.hpp
    new file mode 100644
    index 0000000..743e075
    - +  
     1//  tinygettext - A gettext replacement that works directly on .po files
     2//  Copyright (C) 2006 Ingo Ruhnke <grumbel@gmx.de>
     3//
     4//  This program is free software; you can redistribute it and/or
     5//  modify it under the terms of the GNU General Public License
     6//  as published by the Free Software Foundation; either version 2
     7//  of the License, or (at your option) any later version.
     8//
     9//  This program is distributed in the hope that it will be useful,
     10//  but WITHOUT ANY WARRANTY; without even the implied warranty of
     11//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     12//  GNU General Public License for more details.
     13//
     14//  You should have received a copy of the GNU General Public License
     15//  along with this program; if not, write to the Free Software
     16//  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
     17
     18#ifndef HEADER_TINYGETTEXT_DICTIONARY_HPP
     19#define HEADER_TINYGETTEXT_DICTIONARY_HPP
     20
     21#include <map>
     22#include <vector>
     23#include <string>
     24#include "plural_forms.hpp"
     25
     26namespace tinygettext {
     27
     28/** A simple dictionary class that mimics gettext() behaviour. Each
     29    Dictionary only works for a single language, for managing multiple
     30    languages and .po files at once use the DictionaryManager. */
     31class Dictionary
     32{
     33private:
     34  typedef std::map<std::string, std::vector<std::string> > Entries;
     35  Entries entries;
     36
     37  typedef std::map<std::string, Entries> CtxtEntries;
     38  CtxtEntries ctxt_entries;
     39
     40  std::string charset;
     41  PluralForms plural_forms;
     42
     43  std::string translate(const Entries& dict, const std::string& msgid);
     44  std::string translate_plural(const Entries& dict, const std::string& msgid, const std::string& msgidplural, int num);
     45
     46public:
     47  /** Constructs a dictionary converting to the specified \a charset (default UTF-8) */
     48  Dictionary(const std::string& charset = "UTF-8");
     49  ~Dictionary();
     50
     51  /** Return the charset used for this dictionary */
     52  std::string get_charset() const;
     53
     54  void set_plural_forms(const PluralForms&);
     55  PluralForms get_plural_forms() const;
     56
     57
     58  /** Translate the string \a msgid. */
     59  std::string translate(const std::string& msgid);
     60
     61  /** Translate the string \a msgid to its correct plural form, based
     62      on the number of items given by \a num. \a msgid_plural is \a msgid in
     63      plural form. */
     64  std::string translate_plural(const std::string& msgid, const std::string& msgidplural, int num);
     65
     66  /** Translate the string \a msgid that is in context \a msgctx. A
     67      context is a way to disambiguate msgids that contain the same
     68      letters, but different meaning. For example "exit" might mean to
     69      quit doing something or it might refer to a door that leads
     70      outside (i.e. 'Ausgang' vs 'Beenden' in german) */
     71  std::string translate_ctxt(const std::string& msgctxt, const std::string& msgid);
     72
     73  std::string translate_ctxt_plural(const std::string& msgctxt, const std::string& msgid, const std::string& msgidplural, int num);
     74
     75  /** Add a translation from \a msgid to \a msgstr to the dictionary,
     76      where \a msgid is the singular form of the message, msgid_plural the
     77      plural form and msgstrs a table of translations. The right
     78      translation will be calculated based on the \a num argument to
     79      translate(). */
     80  void add_translation(const std::string& msgid, const std::string& msgid_plural,
     81                       const std::vector<std::string>& msgstrs);
     82  void add_translation(const std::string& msgctxt,
     83                       const std::string& msgid, const std::string& msgid_plural,
     84                       const std::vector<std::string>& msgstrs);
     85
     86  /** Add a translation from \a msgid to \a msgstr to the
     87      dictionary */
     88  void add_translation(const std::string& msgid, const std::string& msgstr);
     89  void add_translation(const std::string& msgctxt, const std::string& msgid, const std::string& msgstr);
     90
     91  /** Iterate over all messages, Func is of type:
     92      void func(const std::string& msgid, const std::vector<std::string>& msgstrs) */
     93  template<class Func>
     94  Func foreach(Func func)
     95  {
     96    for(Entries::iterator i = entries.begin(); i != entries.end(); ++i)
     97    {
     98      func(i->first, i->second);
     99    }
     100    return func;
     101  }
     102
     103  /** Iterate over all messages with a context, Func is of type:
     104      void func(const std::string& ctxt, const std::string& msgid, const std::vector<std::string>& msgstrs) */
     105  template<class Func>
     106  Func foreach_ctxt(Func func)
     107  {
     108    for(CtxtEntries::iterator i = ctxt_entries.begin(); i != ctxt_entries.end(); ++i)
     109    {
     110      for(Entries::iterator j = i->second.begin(); j != i->second.end(); ++j)
     111      {
     112        func(i->first, j->first, j->second);
     113      }
     114    }
     115    return func;
     116  }
     117};
     118
     119} // namespace tinygettext
     120
     121#endif
     122
     123/* EOF */
  • new file libraries/source/tinygettext/tinygettext/dictionary_manager.cpp

    diff --git a/libraries/source/tinygettext/tinygettext/dictionary_manager.cpp b/libraries/source/tinygettext/tinygettext/dictionary_manager.cpp
    new file mode 100644
    index 0000000..f923470
    - +  
     1//  tinygettext - A gettext replacement that works directly on .po files
     2//  Copyright (C) 2006 Ingo Ruhnke <grumbel@gmx.de>
     3//
     4//  This program is free software; you can redistribute it and/or
     5//  modify it under the terms of the GNU General Public License
     6//  as published by the Free Software Foundation; either version 2
     7//  of the License, or (at your option) any later version.
     8//
     9//  This program is distributed in the hope that it will be useful,
     10//  but WITHOUT ANY WARRANTY; without even the implied warranty of
     11//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     12//  GNU General Public License for more details.
     13//
     14//  You should have received a copy of the GNU General Public License
     15//  along with this program; if not, write to the Free Software
     16//  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
     17
     18#include "dictionary_manager.hpp"
     19
     20#include <memory>
     21#include <assert.h>
     22#include <stdlib.h>
     23#include <string.h>
     24#include <fstream>
     25#include <algorithm>
     26
     27#include "log_stream.hpp"
     28#include "po_parser.hpp"
     29#include "unix_file_system.hpp"
     30
     31namespace tinygettext {
     32
     33static bool has_suffix(const std::string& lhs, const std::string rhs)
     34{
     35  if (lhs.length() < rhs.length())
     36    return false;
     37  else
     38    return lhs.compare(lhs.length() - rhs.length(), rhs.length(), rhs) == 0;
     39}
     40
     41DictionaryManager::DictionaryManager(const std::string& charset_) :
     42  dictionaries(),
     43  search_path(),
     44  charset(charset_),
     45  use_fuzzy(true),
     46  current_language(),
     47  current_dict(0),
     48  empty_dict(),
     49  filesystem(new UnixFileSystem)
     50{
     51}
     52
     53DictionaryManager::~DictionaryManager()
     54{
     55  for(Dictionaries::iterator i = dictionaries.begin(); i != dictionaries.end(); ++i)
     56  {
     57    delete i->second;
     58  }
     59}
     60
     61void
     62DictionaryManager::clear_cache()
     63{
     64  for(Dictionaries::iterator i = dictionaries.begin(); i != dictionaries.end(); ++i)
     65  {
     66    delete i->second;
     67  }
     68  dictionaries.clear();
     69
     70  current_dict = 0;
     71}
     72
     73Dictionary&
     74DictionaryManager::get_dictionary()
     75{
     76  if (current_dict)
     77  {
     78    return *current_dict;
     79  }
     80  else
     81  {
     82    if (current_language)
     83    {
     84      current_dict = &get_dictionary(current_language);
     85      return *current_dict;
     86    }
     87    else
     88    {
     89      return empty_dict;
     90    }
     91  }
     92}
     93
     94Dictionary&
     95DictionaryManager::get_dictionary(const Language& language)
     96{
     97  //log_debug << "Dictionary for language \"" << spec << "\" requested" << std::endl;
     98  //log_debug << "...normalized as \"" << lang << "\"" << std::endl;
     99  assert(language);
     100
     101  Dictionaries::iterator i = dictionaries.find(language);
     102  if (i != dictionaries.end())
     103  {
     104    return *i->second;
     105  }
     106  else // Dictionary for languages lang isn't loaded, so we load it
     107  {
     108    //log_debug << "get_dictionary: " << lang << std::endl;
     109    Dictionary* dict = new Dictionary(charset);
     110
     111    dictionaries[language] = dict;
     112
     113    for (SearchPath::reverse_iterator p = search_path.rbegin(); p != search_path.rend(); ++p)
     114    {
     115      std::vector<std::string> files = filesystem->open_directory(*p);
     116
     117      std::string best_filename;
     118      int best_score = 0;
     119
     120      for(std::vector<std::string>::iterator filename = files.begin(); filename != files.end(); filename++)
     121      {
     122        // check if filename matches requested language
     123        if (has_suffix(*filename, ".po"))
     124        { // ignore anything that isn't a .po file
     125          Language po_language = Language::from_env(filename->substr(0, filename->size()-3));
     126
     127          if (!po_language)
     128          {
     129            log_warning << *filename << ": warning: ignoring, unknown language" << std::endl;
     130          }
     131          else
     132          {
     133            int score = Language::match(language, po_language);
     134                         
     135            if (score > best_score)
     136            {
     137              best_score = score;
     138              best_filename = *filename;
     139            }
     140          }
     141        }
     142      }
     143             
     144      if (!best_filename.empty())
     145      {
     146        std::string pofile = *p + "/" + best_filename;
     147        try
     148        {
     149          std::auto_ptr<std::istream> in = filesystem->open_file(pofile);
     150          if (!in.get())
     151          {
     152            log_error << "error: failure opening: " << pofile << std::endl;
     153          }
     154          else
     155          {
     156            POParser::parse(pofile, *in, *dict);
     157          }
     158        }
     159        catch(std::exception& e)
     160        {
     161          log_error << "error: failure parsing: " << pofile << std::endl;
     162          log_error << e.what() << "" << std::endl;
     163        }
     164      }
     165    }
     166
     167    return *dict;
     168  }
     169}
     170
     171std::set<Language>
     172DictionaryManager::get_languages()
     173{
     174  std::set<Language> languages;
     175
     176  for (SearchPath::iterator p = search_path.begin(); p != search_path.end(); ++p)
     177  {
     178    std::vector<std::string> files = filesystem->open_directory(*p);
     179
     180    for(std::vector<std::string>::iterator file = files.begin(); file != files.end(); ++file)
     181    {
     182      if (has_suffix(*file, ".po"))
     183      {
     184        languages.insert(Language::from_env(file->substr(0, file->size()-3)));
     185      }
     186    }
     187  }
     188  return languages;
     189}
     190
     191void
     192DictionaryManager::set_language(const Language& language)
     193{
     194  if (current_language != language)
     195  {
     196    current_language = language;
     197    current_dict     = 0;
     198  }
     199}
     200
     201Language
     202DictionaryManager::get_language() const
     203{
     204  return current_language;
     205}
     206
     207void
     208DictionaryManager::set_charset(const std::string& charset_)
     209{
     210  clear_cache(); // changing charset invalidates cache
     211  charset = charset_;
     212}
     213
     214void
     215DictionaryManager::set_use_fuzzy(bool t)
     216{
     217  clear_cache();
     218  use_fuzzy = t;
     219}
     220
     221bool
     222DictionaryManager::get_use_fuzzy() const
     223{
     224  return use_fuzzy;
     225}
     226
     227void
     228DictionaryManager::add_directory(const std::string& pathname)
     229{
     230  clear_cache(); // adding directories invalidates cache
     231  search_path.push_back(pathname);
     232}
     233
     234void
     235DictionaryManager::set_filesystem(std::auto_ptr<FileSystem> filesystem_)
     236{
     237  filesystem = filesystem_;
     238}
     239
     240} // namespace tinygettext
     241
     242/* EOF */
  • new file libraries/source/tinygettext/tinygettext/dictionary_manager.hpp

    diff --git a/libraries/source/tinygettext/tinygettext/dictionary_manager.hpp b/libraries/source/tinygettext/tinygettext/dictionary_manager.hpp
    new file mode 100644
    index 0000000..7c3d7f3
    - +  
     1//  tinygettext - A gettext replacement that works directly on .po files
     2//  Copyright (C) 2006 Ingo Ruhnke <grumbel@gmx.de>
     3//
     4//  This program is free software; you can redistribute it and/or
     5//  modify it under the terms of the GNU General Public License
     6//  as published by the Free Software Foundation; either version 2
     7//  of the License, or (at your option) any later version.
     8//
     9//  This program is distributed in the hope that it will be useful,
     10//  but WITHOUT ANY WARRANTY; without even the implied warranty of
     11//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     12//  GNU General Public License for more details.
     13//
     14//  You should have received a copy of the GNU General Public License
     15//  along with this program; if not, write to the Free Software
     16//  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
     17
     18#ifndef HEADER_TINYGETTEXT_DICTIONARY_MANAGER_HPP
     19#define HEADER_TINYGETTEXT_DICTIONARY_MANAGER_HPP
     20
     21#include <map>
     22#include <set>
     23#include <string>
     24#include <vector>
     25#include <memory>
     26
     27#include "dictionary.hpp"
     28#include "language.hpp"
     29
     30namespace tinygettext {
     31
     32class FileSystem;
     33
     34/** Manager class for dictionaries, you give it a bunch of directories
     35    with .po files and it will then automatically load the right file
     36    on demand depending on which language was set. */
     37class DictionaryManager
     38{
     39private:
     40  typedef std::map<Language, Dictionary*> Dictionaries;
     41  Dictionaries dictionaries;
     42
     43  typedef std::vector<std::string> SearchPath;
     44  SearchPath search_path;
     45
     46  std::string charset;
     47  bool        use_fuzzy;
     48 
     49  Language    current_language;
     50  Dictionary* current_dict;
     51
     52  Dictionary  empty_dict;
     53
     54  std::auto_ptr<FileSystem> filesystem;
     55
     56  void clear_cache();
     57
     58public:
     59  DictionaryManager(const std::string& charset_ = "UTF-8");
     60  ~DictionaryManager();
     61
     62  /** Return the currently active dictionary, if none is set, an empty
     63      dictionary is returned. */
     64  Dictionary& get_dictionary();
     65
     66  /** Get dictionary for language */
     67  Dictionary& get_dictionary(const Language& language);
     68
     69  /** Set a language based on a four? letter country code */
     70  void set_language(const Language& language);
     71
     72  /** returns the (normalized) country code of the currently used language */
     73  Language get_language() const;
     74
     75  void set_use_fuzzy(bool t);
     76  bool get_use_fuzzy() const;
     77
     78  /** Set a charset that will be set on the returned dictionaries */
     79  void set_charset(const std::string& charset);
     80
     81  /** Add a directory to the search path for dictionaries, earlier
     82      added directories have higher priority then later added ones */
     83  void add_directory(const std::string& pathname);
     84
     85  /** Return a set of the available languages in their country code */
     86  std::set<Language> get_languages();
     87
     88  void set_filesystem(std::auto_ptr<FileSystem> filesystem);
     89
     90private:
     91  DictionaryManager (const DictionaryManager&);
     92  DictionaryManager& operator= (const DictionaryManager&);
     93};
     94
     95} // namespace tinygettext
     96
     97#endif
     98
     99/* EOF */
  • new file libraries/source/tinygettext/tinygettext/file_system.hpp

    diff --git a/libraries/source/tinygettext/tinygettext/file_system.hpp b/libraries/source/tinygettext/tinygettext/file_system.hpp
    new file mode 100644
    index 0000000..af47aaf
    - +  
     1//  tinygettext - A gettext replacement that works directly on .po files
     2//  Copyright (C) 2009 Ingo Ruhnke <grumbel@gmx.de>
     3//
     4//  This program is free software; you can redistribute it and/or
     5//  modify it under the terms of the GNU General Public License
     6//  as published by the Free Software Foundation; either version 2
     7//  of the License, or (at your option) any later version.
     8//
     9//  This program is distributed in the hope that it will be useful,
     10//  but WITHOUT ANY WARRANTY; without even the implied warranty of
     11//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     12//  GNU General Public License for more details.
     13//
     14//  You should have received a copy of the GNU General Public License
     15//  along with this program; if not, write to the Free Software
     16//  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
     17
     18#ifndef HEADER_TINYGETTEXT_FILE_SYSTEM_HPP
     19#define HEADER_TINYGETTEXT_FILE_SYSTEM_HPP
     20
     21#include <vector>
     22#include <memory>
     23#include <iosfwd>
     24#include <string>
     25
     26namespace tinygettext {
     27
     28class FileSystem
     29{
     30public:
     31  virtual ~FileSystem() {}
     32
     33  virtual std::vector<std::string>    open_directory(const std::string& pathname) =0;
     34  virtual std::auto_ptr<std::istream> open_file(const std::string& filename)      =0;
     35};
     36
     37} // namespace tinygettext
     38
     39#endif
     40
     41/* EOF */
     42
  • new file libraries/source/tinygettext/tinygettext/iconv.cpp

    diff --git a/libraries/source/tinygettext/tinygettext/iconv.cpp b/libraries/source/tinygettext/tinygettext/iconv.cpp
    new file mode 100644
    index 0000000..c0b8b60
    - +  
     1//  tinygettext - A gettext replacement that works directly on .po files
     2//  Copyright (C) 2009 Ingo Ruhnke <grumbel@gmx.de>
     3//
     4//  This program is free software; you can redistribute it and/or
     5//  modify it under the terms of the GNU General Public License
     6//  as published by the Free Software Foundation; either version 2
     7//  of the License, or (at your option) any later version.
     8//
     9//  This program is distributed in the hope that it will be useful,
     10//  but WITHOUT ANY WARRANTY; without even the implied warranty of
     11//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     12//  GNU General Public License for more details.
     13//
     14//  You should have received a copy of the GNU General Public License
     15//  along with this program; if not, write to the Free Software
     16//  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
     17
     18#include <ctype.h>
     19#include <assert.h>
     20#include <sstream>
     21#include <errno.h>
     22#include <stdexcept>
     23#include <string.h>
     24#include <stdlib.h>
     25
     26#include "iconv.hpp"
     27#include "log_stream.hpp"
     28
     29namespace tinygettext {
     30
     31#ifndef tinygettext_ICONV_CONST
     32#  define tinygettext_ICONV_CONST
     33#endif
     34
     35IConv::IConv()
     36  : to_charset(),
     37    from_charset(),
     38    cd(0)
     39{}
     40 
     41IConv::IConv(const std::string& from_charset_, const std::string& to_charset_)
     42  : to_charset(),
     43    from_charset(),
     44    cd(0)
     45{
     46  set_charsets(from_charset_, to_charset_);
     47}
     48 
     49IConv::~IConv()
     50{
     51  if (cd)
     52    tinygettext_iconv_close(cd);
     53}
     54 
     55void
     56IConv::set_charsets(const std::string& from_charset_, const std::string& to_charset_)
     57{
     58  if (cd)
     59    tinygettext_iconv_close(cd);
     60
     61  from_charset = from_charset_;
     62  to_charset   = to_charset_;
     63
     64  for(std::string::iterator i = to_charset.begin(); i != to_charset.end(); ++i)
     65    *i = static_cast<char>(toupper(*i));
     66
     67  for(std::string::iterator i = from_charset.begin(); i != from_charset.end(); ++i)
     68    *i = static_cast<char>(toupper(*i));
     69
     70  if (to_charset == from_charset)
     71  {
     72    cd = 0;
     73  }
     74  else
     75  {
     76    cd = tinygettext_iconv_open(to_charset.c_str(), from_charset.c_str());
     77    if (cd == reinterpret_cast<tinygettext_iconv_t>(-1))
     78    {
     79      if(errno == EINVAL)
     80      {
     81        std::ostringstream str;
     82        str << "IConv construction failed: conversion from '" << from_charset
     83            << "' to '" << to_charset << "' not available";
     84        throw std::runtime_error(str.str());
     85      }
     86      else
     87      {
     88        std::ostringstream str;
     89        str << "IConv: construction failed: " << strerror(errno);
     90        throw std::runtime_error(str.str());
     91      }
     92    }
     93  }
     94}
     95
     96/// Convert a string from encoding to another.
     97std::string
     98IConv::convert(const std::string& text)
     99{
     100  if (!cd)
     101  {
     102    return text;
     103  }
     104  else
     105  {
     106    size_t inbytesleft  = text.size();
     107    size_t outbytesleft = 4*inbytesleft; // Worst case scenario: ASCII -> UTF-32?
     108
     109    // We try to avoid to much copying around, so we write directly into
     110    // a std::string
     111    tinygettext_ICONV_CONST char* inbuf = const_cast<char*>(&text[0]);
     112    std::string result(outbytesleft, 'X');
     113    char* outbuf = &result[0];
     114 
     115    // Try to convert the text.
     116    size_t ret = tinygettext_iconv(cd, &inbuf, &inbytesleft, &outbuf, &outbytesleft);
     117    if (ret == static_cast<size_t>(-1))
     118    {
     119      if (errno == EILSEQ || errno == EINVAL)
     120      { // invalid multibyte sequence
     121        tinygettext_iconv(cd, NULL, NULL, NULL, NULL); // reset state
     122
     123        // FIXME: Could try to skip the invalid byte and continue
     124        log_error << "error: tinygettext:iconv: invalid multibyte sequence in:  \"" << text << "\"" << std::endl;
     125      }
     126      else if (errno == E2BIG)
     127      { // output buffer to small
     128        assert(!"tinygettext/iconv.cpp: E2BIG: This should never be reached");
     129      }
     130      else if (errno == EBADF)
     131      {
     132        assert(!"tinygettext/iconv.cpp: EBADF: This should never be reached");
     133      }
     134      else
     135      {
     136        assert(!"tinygettext/iconv.cpp: <unknown>: This should never be reached");
     137      }
     138    }
     139
     140    result.resize(4*text.size() - outbytesleft);
     141
     142    return result;
     143  }
     144}
     145
     146} // namespace tinygettext
     147
     148/* EOF */
  • new file libraries/source/tinygettext/tinygettext/iconv.hpp

    diff --git a/libraries/source/tinygettext/tinygettext/iconv.hpp b/libraries/source/tinygettext/tinygettext/iconv.hpp
    new file mode 100644
    index 0000000..1ae1750
    - +  
     1//  tinygettext - A gettext replacement that works directly on .po files
     2//  Copyright (C) 2006 Ingo Ruhnke <grumbel@gmx.de>
     3//
     4//  This program is free software: you can redistribute it and/or modify
     5//  it under the terms of the GNU General Public License as published by
     6//  the Free Software Foundation, either version 3 of the License, or
     7//  (at your option) any later version.
     8// 
     9//  This program is distributed in the hope that it will be useful,
     10//  but WITHOUT ANY WARRANTY; without even the implied warranty of
     11//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     12//  GNU General Public License for more details.
     13// 
     14//  You should have received a copy of the GNU General Public License
     15//  along with this program.  If not, see <http://www.gnu.org/licenses/>.
     16
     17#ifndef HEADER_TINYGETTEXT_ICONV_HPP
     18#define HEADER_TINYGETTEXT_ICONV_HPP
     19
     20#include <string>
     21
     22#ifdef HAVE_SDL
     23#  include "SDL.h"
     24
     25#  define tinygettext_ICONV_CONST const
     26#  define tinygettext_iconv_t     SDL_iconv_t
     27#  define tinygettext_iconv       SDL_iconv
     28#  define tinygettext_iconv_open  SDL_iconv_open
     29#  define tinygettext_iconv_close SDL_iconv_close
     30#else
     31#  include <iconv.h>
     32
     33#  ifdef HAVE_ICONV_CONST
     34#    define tinygettext_ICONV_CONST ICONV_CONST
     35#  else
     36#    define tinygettext_ICONV_CONST
     37#  endif
     38
     39#  define tinygettext_iconv_t     iconv_t
     40#  define tinygettext_iconv       iconv
     41#  define tinygettext_iconv_open  iconv_open
     42#  define tinygettext_iconv_close iconv_close
     43#endif
     44
     45namespace tinygettext {
     46
     47class IConv
     48{
     49private:
     50  std::string to_charset;
     51  std::string from_charset;
     52  tinygettext_iconv_t cd;
     53
     54public:
     55  IConv();
     56  IConv(const std::string& fromcode, const std::string& tocode);
     57  ~IConv();
     58
     59  void set_charsets(const std::string& fromcode, const std::string& tocode);
     60  std::string convert(const std::string& text);
     61
     62private:
     63  IConv (const IConv&);
     64  IConv& operator= (const IConv&);
     65};
     66
     67} // namespace tinygettext
     68
     69#endif
     70
     71/* EOF */
  • new file libraries/source/tinygettext/tinygettext/language.cpp

    diff --git a/libraries/source/tinygettext/tinygettext/language.cpp b/libraries/source/tinygettext/tinygettext/language.cpp
    new file mode 100644
    index 0000000..1b6aac0
    - +  
     1//  tinygettext - A gettext replacement that works directly on .po files
     2//  Copyright (C) 2006 Ingo Ruhnke <grumbel@gmx.de>
     3//
     4//  This program is free software; you can redistribute it and/or
     5//  modify it under the terms of the GNU General Public License
     6//  as published by the Free Software Foundation; either version 2
     7//  of the License, or (at your option) any later version.
     8//
     9//  This program is distributed in the hope that it will be useful,
     10//  but WITHOUT ANY WARRANTY; without even the implied warranty of
     11//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     12//  GNU General Public License for more details.
     13//
     14//  You should have received a copy of the GNU General Public License
     15//  along with this program; if not, write to the Free Software
     16//  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
     17
     18#include "language.hpp"
     19
     20#include <map>
     21#include <assert.h>
     22#include <vector>
     23
     24namespace tinygettext {
     25
    026
     27struct LanguageSpec {
     28  /** Language code: "de", "en", ... */
     29  const char* language;
     30
     31  /** Country code: "BR", "DE", ..., can be 0 */
     32  const char* country;
     33
     34  /** Modifier/Varint: "Latn", "ije", "latin"..., can be 0 */
     35  const char* modifier;
     36
     37  /** Language name: "German", "English", "French", ... */
     38  const char* name;
     39};
     40
    141
     42/** Language Definitions */
     43//*{
     44LanguageSpec languages[] = {
     45  { "aa", 0,    0, "Afar"                        },
     46  { "af", 0,    0, "Afrikaans"                   },
     47  { "af", "ZA", 0, "Afrikaans (South Africa)"    },
     48  { "am", 0,    0, "Amharic"                     },
     49  { "ar", 0,    0, "Arabic"                      },
     50  { "ar", "AR", 0, "Arabic (Argentina)"          },
     51  { "ar", "OM", 0, "Arabic (Oman)"               },
     52  { "ar", "SA", 0, "Arabic (Saudi Arabia)"       },
     53  { "ar", "SY", 0, "Arabic (Syrian Arab Republic)" },
     54  { "ar", "TN", 0, "Arabic (Tunisia)"            },
     55  { "as", 0,    0, "Assamese"                    },
     56  { "ast",0,    0, "Asturian"                    },
     57  { "ay", 0,    0, "Aymara"                      },
     58  { "az", 0,    0, "Azerbaijani"                 },
     59  { "az", "IR", 0, "Azerbaijani (Iran)"          },
     60  { "be", 0,    0, "Belarusian"                  },
     61  { "be", 0, "latin", "Belarusian"               },
     62  { "bg", 0,    0, "Bulgarian"                   },
     63  { "bg", "BG", 0, "Bulgarian (Bulgaria)"        },
     64  { "bn", 0,    0, "Bengali"                     },
     65  { "bn", "BD", 0, "Bengali (Bangladesh)"        },
     66  { "bn", "IN", 0, "Bengali (India)"             },
     67  { "bo", 0,    0, "Tibetan"                     },
     68  { "br", 0,    0, "Breton"                      },
     69  { "bs", 0,    0, "Bosnian"                     },
     70  { "bs", "BA", 0, "Bosnian (Bosnia/Herzegovina)"},
     71  { "bs", "BS", 0, "Bosnian (Bahamas)"           },
     72  { "ca", "ES", "valencia", "Catalan (valencia)" },
     73  { "ca", "ES", 0, "Catalan (Spain)"             },
     74  { "ca", 0,    "valencia", "Catalan (valencia)" },
     75  { "ca", 0,    0, "Catalan"                     },
     76  { "co", 0,    0, "Corsican"                    },
     77  { "cs", 0,    0, "Czech"                       },
     78  { "cs", "CZ", 0, "Czech (Czech Republic)"      },
     79  { "cy", 0,    0, "Welsh"                       },
     80  { "cy", "GB", 0, "Welsh (Great Britain)"       },
     81  { "cz", 0,    0, "Unknown language"            },
     82  { "da", 0,    0, "Danish"                      },
     83  { "da", "DK", 0, "Danish (Denmark)"            },
     84  { "de", 0,    0, "German"                      },
     85  { "de", "AT", 0, "German (Austria)"            },
     86  { "de", "CH", 0, "German (Switzerland)"        },
     87  { "de", "DE", 0, "German (Germany)"            },
     88  { "dk", 0,    0, "Unknown language"            },
     89  { "dz", 0,    0, "Dzongkha"                    },
     90  { "el", 0,    0, "Greek"                       },
     91  { "el", "GR", 0, "Greek (Greece)"              },
     92  { "en", 0,    0, "English"                     },
     93  { "en", "AU", 0, "English (Australia)"         },
     94  { "en", "CA", 0, "English (Canada)"            },
     95  { "en", "GB", 0, "English (Great Britain)"     },
     96  { "en", "US", 0, "English (United States)"     },
     97  { "en", "ZA", 0, "English (South Africa)"      },
     98  { "en", 0, "boldquot", "English"               },
     99  { "en", 0, "quot", "English"                   },
     100  { "en", "US", "piglatin", "English"            },
     101  { "eo", 0,    0, "Esperanto"                   },
     102  { "es", 0,    0, "Spanish"                     },
     103  { "es", "AR", 0, "Spanish (Argentina)"         },
     104  { "es", "CL", 0, "Spanish (Chile)"             },
     105  { "es", "CO", 0, "Spanish (Colombia)"          },
     106  { "es", "CR", 0, "Spanish (Costa Rica)"        },
     107  { "es", "DO", 0, "Spanish (Dominican Republic)"},
     108  { "es", "EC", 0, "Spanish (Ecuador)"           },
     109  { "es", "ES", 0, "Spanish (Spain)"             },
     110  { "es", "GT", 0, "Spanish (Guatemala)"         },
     111  { "es", "HN", 0, "Spanish (Honduras)"          },
     112  { "es", "LA", 0, "Spanish (Laos)"              },
     113  { "es", "MX", 0, "Spanish (Mexico)"            },
     114  { "es", "NI", 0, "Spanish (Nicaragua)"         },
     115  { "es", "PA", 0, "Spanish (Panama)"            },
     116  { "es", "PE", 0, "Spanish (Peru)"              },
     117  { "es", "PR", 0, "Spanish (Puerto Rico)"       },
     118  { "es", "SV", 0, "Spanish (El Salvador)"       },
     119  { "es", "UY", 0, "Spanish (Uruguay)"           },
     120  { "es", "VE", 0, "Spanish (Venezuela)"         },
     121  { "et", 0,    0, "Estonian"                    },
     122  { "et", "EE", 0, "Estonian (Estonia)"          },
     123  { "et", "ET", 0, "Estonian (Ethiopia)"         },
     124  { "eu", 0,    0, "Basque"                      },
     125  { "eu", "ES", 0, "Basque (Spain)"              },
     126  { "fa", 0,    0, "Persian"                     },
     127  { "fa", "AF", 0, "Persian (Afghanistan)"       },
     128  { "fa", "IR", 0, "Persian (Iran)"              },
     129  { "fi", 0,    0, "Finnish"                     },
     130  { "fi", "FI", 0, "Finnish (Finland)"           },
     131  { "fo", 0,    0, "Faroese"                     },
     132  { "fo", "FO", 0, "Faeroese (Faroe Islands)"    },
     133  { "fr", 0,    0, "French"                      },
     134  { "fr", "CA", 0, "French (Canada)"             },
     135  { "fr", "CH", 0, "French (Switzerland)"        },
     136  { "fr", "FR", 0, "French (France)"             },
     137  { "fr", "LU", 0, "French (Luxembourg)"         },
     138  { "fy", 0,    0, "Frisian"                     },
     139  { "ga", 0,    0, "Irish"                       },
     140  { "gd", 0,    0, "Gaelic Scots"                },
     141  { "gl", 0,    0, "Galician"                    },
     142  { "gl", "ES", 0, "Galician (Spain)"            },
     143  { "gn", 0,    0, "Guarani"                     },
     144  { "gu", 0,    0, "Gujarati"                    },
     145  { "gv", 0,    0, "Manx"                        },
     146  { "ha", 0,    0, "Hausa"                       },
     147  { "he", 0,    0, "Hebrew"                      },
     148  { "he", "IL", 0, "Hebrew (Israel)"             },
     149  { "hi", 0,    0, "Hindi"                       },
     150  { "hr", 0,    0, "Croatian"                    },
     151  { "hr", "HR", 0, "Croatian (Croatia)"          },
     152  { "hu", 0,    0, "Hungarian"                   },
     153  { "hu", "HU", 0, "Hungarian (Hungary)"         },
     154  { "hy", 0,    0, "Armenian"                    },
     155  { "ia", 0,    0, "Interlingua"                 },
     156  { "id", 0,    0, "Indonesian"                  },
     157  { "id", "ID", 0, "Indonesian (Indonesia)"      },
     158  { "is", 0,    0, "Icelandic"                   },
     159  { "is", "IS", 0, "Icelandic (Iceland)"         },
     160  { "it", 0,    0, "Italian"                     },
     161  { "it", "CH", 0, "Italian (Switzerland)"       },
     162  { "it", "IT", 0, "Italian (Italy)"             },
     163  { "iu", 0,    0, "Inuktitut"                   },
     164  { "ja", 0,    0, "Japanese"                    },
     165  { "ja", "JP", 0, "Japanese (Japan)"            },
     166  { "ka", 0,    0, "Georgian"                    },
     167  { "kk", 0,    0, "Kazakh"                      },
     168  { "kl", 0,    0, "Kalaallisut"                 },
     169  { "km", 0,    0, "Khmer"                       },
     170  { "km", "KH", 0, "Khmer (Cambodia)"            },
     171  { "kn", 0,    0, "Kannada"                     },
     172  { "ko", 0,    0, "Korean"                      },
     173  { "ko", "KR", 0, "Korean (Korea)"              },
     174  { "ku", 0,    0, "Kurdish"                     },
     175  { "kw", 0,    0, "Cornish"                     },
     176  { "ky", 0,    0, "Kirghiz"                     },
     177  { "la", 0,    0, "Latin"                       },
     178  { "lo", 0,    0, "Lao"                         },
     179  { "lt", 0,    0, "Lithuanian"                  },
     180  { "lt", "LT", 0, "Lithuanian (Lithuania)"      },
     181  { "lv", 0,    0, "Latvian"                     },
     182  { "lv", "LV", 0, "Latvian (Latvia)"            },
     183  { "mg", 0,    0, "Malagasy"                    },
     184  { "mi", 0,    0, "Maori"                       },
     185  { "mk", 0,    0, "Macedonian"                  },
     186  { "mk", "MK", 0, "Macedonian (Macedonia)"      },
     187  { "ml", 0,    0, "Malayalam"                   },
     188  { "mn", 0,    0, "Mongolian"                   },
     189  { "mr", 0,    0, "Marathi"                     },
     190  { "ms", 0,    0, "Malay"                       },
     191  { "ms", "MY", 0, "Malay (Malaysia)"            },
     192  { "mt", 0,    0, "Maltese"                     },
     193  { "my", 0,    0, "Burmese"                     },
     194  { "my", "MM", 0, "Burmese (Myanmar)"           },
     195  { "nb", 0,    0, "Norwegian Bokmal"            },
     196  { "nb", "NO", 0, "Norwegian Bokmål (Norway)"   },
     197  { "ne", 0,    0, "Nepali"                      },
     198  { "nl", 0,    0, "Dutch"                       },
     199  { "nl", "BE", 0, "Dutch (Belgium)"             },
     200  { "nl", "NL", 0, "Dutch (Netherlands)"         },
     201  { "nn", 0,    0, "Norwegian Nynorsk"           },
     202  { "nn", "NO", 0, "Norwegian Nynorsk (Norway)"  },
     203  { "no", 0,    0, "Norwegian"                   },
     204  { "no", "NO", 0, "Norwegian (Norway)"          },
     205  { "no", "NY", 0, "Norwegian (NY)"              },
     206  { "nr", 0,    0, "Ndebele, South"              },
     207  { "oc", 0,    0, "Occitan post 1500"           },
     208  { "om", 0,    0, "Oromo"                       },
     209  { "or", 0,    0, "Oriya"                       },
     210  { "pa", 0,    0, "Punjabi"                     },
     211  { "pl", 0,    0, "Polish"                      },
     212  { "pl", "PL", 0, "Polish (Poland)"             },
     213  { "ps", 0,    0, "Pashto"                      },
     214  { "pt", 0,    0, "Portuguese"                  },
     215  { "pt", "BR", 0, "Brazilian"                   },
     216  { "pt", "PT", 0, "Portuguese (Portugal)"       },
     217  { "qu", 0,    0, "Quechua"                     },
     218  { "rm", 0,    0, "Rhaeto-Romance"              },
     219  { "ro", 0,    0, "Romanian"                    },
     220  { "ro", "RO", 0, "Romanian (Romania)"          },
     221  { "ru", 0,    0, "Russian"                     },
     222  { "ru", "RU", 0, "Russian (Russia"             },
     223  { "rw", 0,    0, "Kinyarwanda"                 },
     224  { "sa", 0,    0, "Sanskrit"                    },
     225  { "sd", 0,    0, "Sindhi"                      },
     226  { "se", 0,    0, "Sami"                        },
     227  { "se", "NO", 0, "Sami (Norway)"               },
     228  { "si", 0,    0, "Sinhalese"                   },
     229  { "sk", 0,    0, "Slovak"                      },
     230  { "sk", "SK", 0, "Slovak (Slovakia)"           },
     231  { "sl", 0,    0, "Slovenian"                   },
     232  { "sl", "SI", 0, "Slovenian (Slovenia)"        },
     233  { "sl", "SL", 0, "Slovenian (Sierra Leone)"    },
     234  { "sm", 0,    0, "Samoan"                      },
     235  { "so", 0,    0, "Somali"                      },
     236  { "sp", 0,    0, "Unknown language"            },
     237  { "sq", 0,    0, "Albanian"                    },
     238  { "sq", "AL", 0, "Albanian (Albania)"          },
     239  { "sr", 0,    0, "Serbian"                     },
     240  { "sr", "YU", 0, "Serbian (Yugoslavia)"        },
     241  { "sr", 0,"ije", "Serbian"                     },
     242  { "sr", 0, "latin", "Serbian"                  },
     243  { "sr", 0, "Latn",  "Serbian"                  },
     244  { "ss", 0,    0, "Swati"                       },
     245  { "st", 0,    0, "Sotho"                       },
     246  { "sv", 0,    0, "Swedish"                     },
     247  { "sv", "SE", 0, "Swedish (Sweden)"            },
     248  { "sv", "SV", 0, "Swedish (El Salvador)"       },
     249  { "sw", 0,    0, "Swahili"                     },
     250  { "ta", 0,    0, "Tamil"                       },
     251  { "te", 0,    0, "Telugu"                      },
     252  { "tg", 0,    0, "Tajik"                       },
     253  { "th", 0,    0, "Thai"                        },
     254  { "th", "TH", 0, "Thai (Thailand)"             },
     255  { "ti", 0,    0, "Tigrinya"                    },
     256  { "tk", 0,    0, "Turkmen"                     },
     257  { "tl", 0,    0, "Tagalog"                     },
     258  { "to", 0,    0, "Tonga"                       },
     259  { "tr", 0,    0, "Turkish"                     },
     260  { "tr", "TR", 0, "Turkish (Turkey)"            },
     261  { "ts", 0,    0, "Tsonga"                      },
     262  { "tt", 0,    0, "Tatar"                       },
     263  { "ug", 0,    0, "Uighur"                      },
     264  { "uk", 0,    0, "Ukrainian"                   },
     265  { "uk", "UA", 0, "Ukrainian (Ukraine)"         },
     266  { "ur", 0,    0, "Urdu"                        },
     267  { "ur", "PK", 0, "Urdu (Pakistan)"             },
     268  { "uz", 0,    0, "Uzbek"                       },
     269  { "uz", 0, "cyrillic", "Uzbek"                 },
     270  { "vi", 0,    0, "Vietnamese"                  },
     271  { "vi", "VN", 0, "Vietnamese (Vietnam)"        },
     272  { "wa", 0,    0, "Walloon"                     },
     273  { "wo", 0,    0, "Wolof"                       },
     274  { "xh", 0,    0, "Xhosa"                       },
     275  { "yi", 0,    0, "Yiddish"                     },
     276  { "yo", 0,    0, "Yoruba"                      },
     277  { "zh", 0,    0, "Chinese"                     },
     278  { "zh", "CN", 0, "Chinese (simplified)"        },
     279  { "zh", "HK", 0, "Chinese (Hong Kong)"         },
     280  { "zh", "TW", 0, "Chinese (traditional)"       },
     281  { "zu", 0,    0, "Zulu"                        },
     282  { NULL, 0,    0, NULL                          }
     283};
     284//*}
     285
    2286
     287std::string
     288resolve_language_alias(const std::string& name)
     289{
     290  typedef std::map<std::string, std::string> Aliases;
     291  static Aliases language_aliases;
     292  if (language_aliases.empty())
     293  {
     294    // FIXME: Many of those are not useful for us, since we leave
     295    // encoding to the app, not to the language, we could/should
     296    // also match against all language names, not just aliases from
     297    // locale.alias
     298
     299    // Aliases taken from /etc/locale.alias
     300    language_aliases["bokmal"]           = "nb_NO.ISO-8859-1";
     301    language_aliases["bokmål"]           = "nb_NO.ISO-8859-1";
     302    language_aliases["catalan"]          = "ca_ES.ISO-8859-1";
     303    language_aliases["croatian"]         = "hr_HR.ISO-8859-2";
     304    language_aliases["czech"]            = "cs_CZ.ISO-8859-2";
     305    language_aliases["danish"]           = "da_DK.ISO-8859-1";
     306    language_aliases["dansk"]            = "da_DK.ISO-8859-1";
     307    language_aliases["deutsch"]          = "de_DE.ISO-8859-1";
     308    language_aliases["dutch"]            = "nl_NL.ISO-8859-1";
     309    language_aliases["eesti"]            = "et_EE.ISO-8859-1";
     310    language_aliases["estonian"]         = "et_EE.ISO-8859-1";
     311    language_aliases["finnish"]          = "fi_FI.ISO-8859-1";
     312    language_aliases["français"]         = "fr_FR.ISO-8859-1";
     313    language_aliases["french"]           = "fr_FR.ISO-8859-1";
     314    language_aliases["galego"]           = "gl_ES.ISO-8859-1";
     315    language_aliases["galician"]         = "gl_ES.ISO-8859-1";
     316    language_aliases["german"]           = "de_DE.ISO-8859-1";
     317    language_aliases["greek"]            = "el_GR.ISO-8859-7";
     318    language_aliases["hebrew"]           = "he_IL.ISO-8859-8";
     319    language_aliases["hrvatski"]         = "hr_HR.ISO-8859-2";
     320    language_aliases["hungarian"]        = "hu_HU.ISO-8859-2";
     321    language_aliases["icelandic"]        = "is_IS.ISO-8859-1";
     322    language_aliases["italian"]          = "it_IT.ISO-8859-1";
     323    language_aliases["japanese"]         = "ja_JP.eucJP";
     324    language_aliases["japanese.euc"]     = "ja_JP.eucJP";
     325    language_aliases["ja_JP"]            = "ja_JP.eucJP";
     326    language_aliases["ja_JP.ujis"]       = "ja_JP.eucJP";
     327    language_aliases["japanese.sjis"]    = "ja_JP.SJIS";
     328    language_aliases["korean"]           = "ko_KR.eucKR";
     329    language_aliases["korean.euc"]       = "ko_KR.eucKR";
     330    language_aliases["ko_KR"]            = "ko_KR.eucKR";
     331    language_aliases["lithuanian"]       = "lt_LT.ISO-8859-13";
     332    language_aliases["no_NO"]            = "nb_NO.ISO-8859-1";
     333    language_aliases["no_NO.ISO-8859-1"] = "nb_NO.ISO-8859-1";
     334    language_aliases["norwegian"]        = "nb_NO.ISO-8859-1";
     335    language_aliases["nynorsk"]          = "nn_NO.ISO-8859-1";
     336    language_aliases["polish"]           = "pl_PL.ISO-8859-2";
     337    language_aliases["portuguese"]       = "pt_PT.ISO-8859-1";
     338    language_aliases["romanian"]         = "ro_RO.ISO-8859-2";
     339    language_aliases["russian"]          = "ru_RU.ISO-8859-5";
     340    language_aliases["slovak"]           = "sk_SK.ISO-8859-2";
     341    language_aliases["slovene"]          = "sl_SI.ISO-8859-2";
     342    language_aliases["slovenian"]        = "sl_SI.ISO-8859-2";
     343    language_aliases["spanish"]          = "es_ES.ISO-8859-1";
     344    language_aliases["swedish"]          = "sv_SE.ISO-8859-1";
     345    language_aliases["thai"]             = "th_TH.TIS-620";
     346    language_aliases["turkish"]          = "tr_TR.ISO-8859-9";
     347  }
     348
     349  std::string name_lowercase;
     350  name_lowercase.resize(name.size());
     351  for(std::string::size_type i = 0; i < name.size(); ++i)
     352    name_lowercase[i] = static_cast<char>(tolower(name[i]));
     353
     354  Aliases::iterator i = language_aliases.find(name_lowercase);
     355  if (i != language_aliases.end())
     356  {
     357    return i->second;
     358  }
     359  else
     360  {
     361    return name;
     362  }
     363}
     364
    3365
     366Language
     367Language::from_spec(const std::string& language, const std::string& country, const std::string& modifier)
     368{
     369  static std::map<std::string, std::vector<LanguageSpec*> > language_map;
     370
     371  if (language_map.empty())
     372  { // Init language_map
     373    for(int i = 0; languages[i].language != NULL; ++i)
     374      language_map[languages[i].language].push_back(&languages[i]);
     375  }
     376 
     377  std::map<std::string, std::vector<LanguageSpec*> >::iterator i = language_map.find(language);
     378  if (i != language_map.end())
     379  {
     380    std::vector<LanguageSpec*>& lst = i->second;
     381
     382    LanguageSpec tmpspec;
     383    tmpspec.language = language.c_str();
     384    tmpspec.country  = country.c_str();
     385    tmpspec.modifier = modifier.c_str();
     386    Language tmplang(&tmpspec);
     387     
     388    LanguageSpec* best_match = 0;
     389    int best_match_score = 0;
     390    for(std::vector<LanguageSpec*>::iterator j = lst.begin(); j != lst.end(); ++j)
     391    { // Search for the language that best matches the given spec, value country more then modifier
     392      int score = Language::match(Language(*j), tmplang);
     393
     394      if (score > best_match_score)
     395      {
     396        best_match = *j;
     397        best_match_score = score;
     398      }
     399    }
     400    assert(best_match);
     401    return Language(best_match);
     402  }
     403  else
     404  {
     405    return Language();
     406  }
     407}
     408
     409Language
     410Language::from_name(const std::string& spec_str)
     411{
     412  return from_env(resolve_language_alias(spec_str));
     413}
     414
     415Language
     416Language::from_env(const std::string& env)
     417{
     418  // Split LANGUAGE_COUNTRY.CODESET@MODIFIER into parts
     419  std::string::size_type ln = env.find('_');
     420  std::string::size_type dt = env.find('.');
     421  std::string::size_type at = env.find('@');
     422
     423  std::string language;
     424  std::string country;
     425  std::string codeset;
     426  std::string modifier;
     427
     428  //std::cout << ln << " " << dt << " " << at << std::endl;
     429
     430  language = env.substr(0, std::min(std::min(ln, dt), at));
     431
     432  if (ln != std::string::npos && ln+1 < env.size()) // _
     433  {
     434    country = env.substr(ln+1, (std::min(dt, at) == std::string::npos) ? std::string::npos : std::min(dt, at) - (ln+1));
     435  }
     436
     437  if (dt != std::string::npos && dt+1 < env.size()) // .
     438  {
     439    codeset = env.substr(dt+1, (at == std::string::npos) ? std::string::npos : (at - (dt+1)));
     440  }
     441
     442  if (at != std::string::npos && at+1 < env.size()) // @
     443  {
     444    modifier = env.substr(at+1);
     445  }
     446
     447  return from_spec(language, country, modifier);
     448}
     449
    4450
     451Language::Language(LanguageSpec* language_spec_)
     452  : language_spec(language_spec_)
     453{
     454}
     455
     456Language::Language()
     457  : language_spec(0)
     458{
     459}
     460
     461int
     462Language::match(const Language& lhs, const Language& rhs)
     463{
     464  if (lhs.get_language() != rhs.get_language())
     465  {
     466    return 0;
     467  }
     468  else
     469  {
     470    static int match_tbl[3][3] = {
     471      // modifier match, wildchard, miss
     472      { 9, 8, 5 }, // country match
     473      { 7, 6, 3 }, // country wildcard
     474      { 4, 2, 1 }, // country miss
     475    };
     476 
     477    int c;
     478    if (lhs.get_country() == rhs.get_country())
     479      c = 0;
     480    else if (lhs.get_country().empty() || rhs.get_country().empty())
     481      c = 1;
     482    else
     483      c = 2;
     484 
     485    int m;
     486    if (lhs.get_modifier() == rhs.get_modifier())
     487      m = 0;
     488    else if (lhs.get_modifier().empty() || rhs.get_modifier().empty())
     489      m = 1;
     490    else
     491      m = 2;
     492
     493    return match_tbl[c][m];
     494  }
     495}
     496
     497std::string
     498Language::get_language() const
     499{
     500  if (language_spec)
     501    return language_spec->language;
     502  else
     503    return "";
     504}
     505
     506std::string
     507Language::get_country()  const
     508{
     509  if (language_spec && language_spec->country)
     510    return language_spec->country;
     511  else
     512    return "";
     513}
     514
     515std::string
     516Language::get_modifier() const
     517{
     518  if (language_spec && language_spec->modifier)
     519    return language_spec->modifier;
     520  else
     521    return "";
     522}
     523
     524std::string
     525Language::get_name()  const
     526{
     527  if (language_spec)
     528    return language_spec->name;
     529  else
     530    return "";
     531}
     532
     533std::string
     534Language::str() const
     535{
     536  if (language_spec)
     537  {
     538    std::string var;
     539    var += language_spec->language;
     540    if (language_spec->country)
     541    {
     542      var += "_";
     543      var += language_spec->country;
     544    }
     545
     546    if (language_spec->modifier)
     547    {
     548      var += "@";
     549      var += language_spec->modifier;
     550    }
     551    return var;
     552  }
     553  else
     554  {
     555    return "";
     556  }
     557}
     558
     559bool
     560Language::operator==(const Language& rhs) const
     561{
     562  return language_spec == rhs.language_spec;
     563}
     564
     565bool
     566Language::operator!=(const Language& rhs) const
     567{
     568  return language_spec != rhs.language_spec;
  • new file libraries/source/tinygettext/tinygettext/language.hpp

    +}
    +
    
    +} // namespace tinygettext
    +
    +/* EOF */
    diff --git a/libraries/source/tinygettext/tinygettext/language.hpp b/libraries/source/tinygettext/tinygettext/language.hpp
    new file mode 100644
    index 0000000..b997a13
    - +  
     1//  tinygettext - A gettext replacement that works directly on .po files
     2//  Copyright (C) 2006 Ingo Ruhnke <grumbel@gmx.de>
     3//
     4//  This program is free software; you can redistribute it and/or
     5//  modify it under the terms of the GNU General Public License
     6//  as published by the Free Software Foundation; either version 2
     7//  of the License, or (at your option) any later version.
     8//
     9//  This program is distributed in the hope that it will be useful,
     10//  but WITHOUT ANY WARRANTY; without even the implied warranty of
     11//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     12//  GNU General Public License for more details.
     13//
     14//  You should have received a copy of the GNU General Public License
     15//  along with this program; if not, write to the Free Software
     16//  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
     17
     18#ifndef HEADER_TINYGETTEXT_LANGUAGE_HPP
     19#define HEADER_TINYGETTEXT_LANGUAGE_HPP
     20
     21#include <string>
     22
     23namespace tinygettext {
     24
     25struct LanguageSpec;
     26
     27/** Lightweight wrapper around LanguageSpec */
     28class Language
     29{
     30private:
     31  LanguageSpec* language_spec;
     32
     33  Language(LanguageSpec* language_spec);
     34
     35public:
     36  /** Create a language from language and country code:
     37      Example: Languge("de", "DE"); */
     38  static Language from_spec(const std::string& language,
     39                            const std::string& country = std::string(),
     40                            const std::string& modifier = std::string());
     41
     42  /** Create a language from language and country code:
     43      Example: Languge("deutsch");
     44      Example: Languge("de_DE"); */
     45  static Language from_name(const std::string& str);
     46
     47  /** Create a language from an environment variable style string (e.g de_DE.UTF-8@modifier) */
     48  static Language from_env(const std::string& env);
     49
     50  /** Compares two Languages, returns 0 on missmatch and a score
     51      between 1 and 9 on match, the higher the score the better the
     52      match */
     53  static int match(const Language& lhs, const Language& rhs);
     54
     55  /** Create an undefined Language object */
     56  Language();
     57 
     58  operator bool() const { return language_spec; }
     59
     60  /** Returns the language code (i.e. de, en, fr) */
     61  std::string get_language() const;
     62
     63  /** Returns the country code (i.e. DE, AT, US) */
     64  std::string get_country()  const;
     65
     66  /** Returns the modifier of the language (i.e. latn or Latn for
     67      Serbian with non-cyrilic characters) */
     68  std::string get_modifier()  const;
     69
     70  /** Returns the human readable name of the Language */
     71  std::string get_name() const;
     72
     73  /** Returns the Language as string in the form of an environment
     74      variable: {language}_{country}@{modifier} */
     75  std::string str() const;
     76
     77  bool operator==(const Language& rhs) const;
     78  bool operator!=(const Language& rhs) const;
     79
     80  friend bool operator<(const Language& lhs, const Language& rhs);
     81};
     82
     83inline bool operator<(const Language& lhs, const Language& rhs) {
     84  return lhs.language_spec < rhs.language_spec;
     85}
     86
     87} // namespace tinygettext
     88
     89#endif
     90
     91/* EOF */
  • new file libraries/source/tinygettext/tinygettext/log.cpp

    diff --git a/libraries/source/tinygettext/tinygettext/log.cpp b/libraries/source/tinygettext/tinygettext/log.cpp
    new file mode 100644
    index 0000000..55c89df
    - +  
     1//  tinygettext - A gettext replacement that works directly on .po files
     2//  Copyright (C) 2009 Ingo Ruhnke <grumbel@gmx.de>
     3//
     4//  This program is free software; you can redistribute it and/or
     5//  modify it under the terms of the GNU General Public License
     6//  as published by the Free Software Foundation; either version 2
     7//  of the License, or (at your option) any later version.
     8//
     9//  This program is distributed in the hope that it will be useful,
     10//  but WITHOUT ANY WARRANTY; without even the implied warranty of
     11//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     12//  GNU General Public License for more details.
     13//
     14//  You should have received a copy of the GNU General Public License
     15//  along with this program; if not, write to the Free Software
     16//  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
     17
     18#include <iostream>
     19#include "log.hpp"
     20
     21namespace tinygettext {
     22
    023
     24Log::log_callback_t Log::log_info_callback    = &Log::default_log_callback;
     25Log::log_callback_t Log::log_warning_callback = &Log::default_log_callback;
     26Log::log_callback_t Log::log_error_callback   = &Log::default_log_callback;
     27
    128
     29void
     30Log::default_log_callback(const std::string& str)
     31{
     32//   std::cerr << "tinygettext: " << str;
     33}
     34
     35void
     36Log::set_log_info_callback(log_callback_t callback)
     37{
     38  log_info_callback = callback;
     39}
     40
     41void
     42Log::set_log_warning_callback(log_callback_t callback)
     43{
     44  log_warning_callback = callback;
     45}
     46
     47void
     48Log::set_log_error_callback(log_callback_t callback)
     49{
     50  log_error_callback = callback;
     51}
     52
    253
     54Log::Log(log_callback_t callback_) :
     55  callback(callback_),
     56  out()
     57{
     58}
     59
     60Log::~Log()
     61{
     62  callback(out.str());
     63}
     64
     65std::ostream&
     66Log::get()
     67{
     68  return out;
     69}
     70
  • new file libraries/source/tinygettext/tinygettext/log.hpp

    +} // namespace tinygettext
    +
    +/* EOF */
    diff --git a/libraries/source/tinygettext/tinygettext/log.hpp b/libraries/source/tinygettext/tinygettext/log.hpp
    new file mode 100644
    index 0000000..a8eadb4
    - +  
     1//  tinygettext - A gettext replacement that works directly on .po files
     2//  Copyright (C) 2009 Ingo Ruhnke <grumbel@gmx.de>
     3//
     4//  This program is free software; you can redistribute it and/or
     5//  modify it under the terms of the GNU General Public License
     6//  as published by the Free Software Foundation; either version 2
     7//  of the License, or (at your option) any later version.
     8//
     9//  This program is distributed in the hope that it will be useful,
     10//  but WITHOUT ANY WARRANTY; without even the implied warranty of
     11//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     12//  GNU General Public License for more details.
     13//
     14//  You should have received a copy of the GNU General Public License
     15//  along with this program; if not, write to the Free Software
     16//  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
     17
     18#ifndef HEADER_TINYGETTEXT_LOG_HPP
     19#define HEADER_TINYGETTEXT_LOG_HPP
     20
     21#include <sstream>
     22
     23namespace tinygettext {
     24
     25class Log
     26{
     27public:
     28  typedef void (*log_callback_t)(const std::string&);
     29
     30  static log_callback_t log_info_callback;
     31  static log_callback_t log_warning_callback;
     32  static log_callback_t log_error_callback;
     33
     34
     35  static void default_log_callback(const std::string& str);
     36
     37  static void set_log_info_callback(log_callback_t callback);
     38  static void set_log_warning_callback(log_callback_t callback);
     39  static void set_log_error_callback(log_callback_t callback);
     40
     41private:
     42  log_callback_t callback;
     43  std::ostringstream out;
     44
     45public:
     46  Log(log_callback_t callback);
     47  ~Log();
     48 
     49  std::ostream& get();
     50};
     51
     52} // namespace tinygettext
     53
     54#endif
     55
     56/* EOF */
  • new file libraries/source/tinygettext/tinygettext/log_stream.hpp

    diff --git a/libraries/source/tinygettext/tinygettext/log_stream.hpp b/libraries/source/tinygettext/tinygettext/log_stream.hpp
    new file mode 100644
    index 0000000..8ad4c02
    - +  
     1//  tinygettext - A gettext replacement that works directly on .po files
     2//  Copyright (C) 2009 Ingo Ruhnke <grumbel@gmx.de>
     3//
     4//  This program is free software; you can redistribute it and/or
     5//  modify it under the terms of the GNU General Public License
     6//  as published by the Free Software Foundation; either version 2
     7//  of the License, or (at your option) any later version.
     8//
     9//  This program is distributed in the hope that it will be useful,
     10//  but WITHOUT ANY WARRANTY; without even the implied warranty of
     11//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     12//  GNU General Public License for more details.
     13//
     14//  You should have received a copy of the GNU General Public License
     15//  along with this program; if not, write to the Free Software
     16//  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
     17
     18#ifndef HEADER_TINYGETTEXT_LOG_STREAM_HPP
     19#define HEADER_TINYGETTEXT_LOG_STREAM_HPP
     20
     21#include "log.hpp"
     22
     23namespace tinygettext {
     24
     25// FIXME: very bad to have such things in the API
     26#define log_error   if (!Log::log_error_callback);   else (Log(Log::log_error_callback)).get()
     27#define log_warning if (!Log::log_warning_callback); else (Log(Log::log_warning_callback)).get()
     28#define log_info    if (!Log::log_info_callback);    else (Log(Log::log_warning_callback)).get()
     29
     30} // namespace tinygettext
     31
     32#endif
     33
     34/* EOF */
  • new file libraries/source/tinygettext/tinygettext/plural_forms.cpp

    diff --git a/libraries/source/tinygettext/tinygettext/plural_forms.cpp b/libraries/source/tinygettext/tinygettext/plural_forms.cpp
    new file mode 100644
    index 0000000..8271437
    - +  
     1//  tinygettext - A gettext replacement that works directly on .po files
     2//  Copyright (C) 2006 Ingo Ruhnke <grumbel@gmx.de>
     3//
     4//  This program is free software; you can redistribute it and/or
     5//  modify it under the terms of the GNU General Public License
     6//  as published by the Free Software Foundation; either version 2
     7//  of the License, or (at your option) any later version.
     8//
     9//  This program is distributed in the hope that it will be useful,
     10//  but WITHOUT ANY WARRANTY; without even the implied warranty of
     11//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     12//  GNU General Public License for more details.
     13//
     14//  You should have received a copy of the GNU General Public License
     15//  along with this program; if not, write to the Free Software
     16//  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
     17
     18#include "plural_forms.hpp"
     19
     20#include <map>
     21
     22namespace tinygettext {
     23
    024
     25/**
     26 *  Plural functions are used to select a string that matches a given
     27 *  count. \a n is the count and the return value is the string index
     28 *  used in the .po file, for example:
     29 *   
     30 *   msgstr[0] = "You got %d error";
     31 *   msgstr[1] = "You got %d errors";       
     32 *          ^-- return value of plural function
     33 */
     34unsigned int plural1(int )     { return 0; }
     35unsigned int plural2_1(int n)  { return (n != 1); }
     36unsigned int plural2_2(int n)  { return (n > 1); }
     37unsigned int plural2_mk(int n) { return n==1 || n%10==1 ? 0 : 1; }
     38unsigned int plural3_lv(int n) { return static_cast<unsigned int>(n%10==1 && n%100!=11 ? 0 : n != 0 ? 1 : 2); }
     39unsigned int plural3_ga(int n) { return static_cast<unsigned int>(n==1 ? 0 : n==2 ? 1 : 2); }
     40unsigned int plural3_lt(int n) { return static_cast<unsigned int>(n%10==1 && n%100!=11 ? 0 : n%10>=2 && (n%100<10 || n%100>=20) ? 1 : 2); }
     41unsigned int plural3_1(int n)  { return static_cast<unsigned int>(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2); }
     42unsigned int plural3_sk(int n) { return static_cast<unsigned int>( (n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2 ); }
     43unsigned int plural3_pl(int n) { return static_cast<unsigned int>(n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2); }
     44unsigned int plural3_sl(int n) { return static_cast<unsigned int>(n%100==1 ? 0 : n%100==2 ? 1 : n%100==3 || n%100==4 ? 2 : 3); }
     45unsigned int plural4_ar(int n) { return static_cast<unsigned int>( n==1 ? 0 : n==2 ? 1 : n>=3 && n<=10 ? 2 : 3 ); }
     46
    147
     48PluralForms
     49PluralForms::from_string(const std::string& str)
     50{
     51  static std::map<std::string, struct PluralForms> plural_forms;
     52   
     53  if (plural_forms.empty())
     54  {
     55    // Note that the plural forms here shouldn't contain any spaces
     56    plural_forms["Plural-Forms:nplurals=1;plural=0;"] = PluralForms(1, plural1);
     57    plural_forms["Plural-Forms:nplurals=2;plural=(n!=1);"] = PluralForms(2, plural2_1);
     58    plural_forms["Plural-Forms:nplurals=2;plural=n!=1;"] = PluralForms(2, plural2_1);
     59    plural_forms["Plural-Forms:nplurals=2;plural=(n>1);"] = PluralForms(2, plural2_2);
     60    plural_forms["Plural-Forms:nplurals=2;plural=n==1||n%10==1?0:1;"] = PluralForms(2, plural2_mk);
     61    plural_forms["Plural-Forms:nplurals=3;plural=n%10==1&&n%100!=11?0:n!=0?1:2);"] = PluralForms(2, plural3_lv);
     62    plural_forms["Plural-Forms:nplurals=3;plural=n==1?0:n==2?1:2;"] = PluralForms(3, plural3_ga);
     63    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);
     64    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);
     65    plural_forms["Plural-Forms:nplurals=3;plural=(n==1)?0:(n>=2&&n<=4)?1:2;"] = PluralForms(3, plural3_sk);
     66    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);
     67    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);
     68
     69    plural_forms["Plural-Forms:nplurals=4;plural=n==1?0:n==2?1:n>=3&&n<=10?2:3;"]=PluralForms(4, plural4_ar);
     70  }
     71 
     72  // Remove spaces from string before lookup
     73  std::string space_less_str;
     74  for(std::string::size_type i = 0; i < str.size(); ++i)
     75    if (!isspace(str[i]))
     76      space_less_str += str[i];
     77 
     78  std::map<std::string, struct PluralForms>::const_iterator it= plural_forms.find(space_less_str);
     79  if (it != plural_forms.end())
     80  {
     81    return it->second;
     82  }
     83  else
     84  {
     85    return PluralForms();
     86  }
     87}
     88
     89} // namespace tinygettext
  • new file libraries/source/tinygettext/tinygettext/plural_forms.hpp

    +
    +/* EOF */
    diff --git a/libraries/source/tinygettext/tinygettext/plural_forms.hpp b/libraries/source/tinygettext/tinygettext/plural_forms.hpp
    new file mode 100644
    index 0000000..0b06449
    - +  
     1//  tinygettext - A gettext replacement that works directly on .po files
     2//  Copyright (C) 2006 Ingo Ruhnke <grumbel@gmx.de>
     3//
     4//  This program is free software; you can redistribute it and/or
     5//  modify it under the terms of the GNU General Public License
     6//  as published by the Free Software Foundation; either version 2
     7//  of the License, or (at your option) any later version.
     8//
     9//  This program is distributed in the hope that it will be useful,
     10//  but WITHOUT ANY WARRANTY; without even the implied warranty of
     11//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     12//  GNU General Public License for more details.
     13//
     14//  You should have received a copy of the GNU General Public License
     15//  along with this program; if not, write to the Free Software
     16//  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
     17
     18#ifndef HEADER_TINYGETTEXT_PLURAL_FORMS_HPP
     19#define HEADER_TINYGETTEXT_PLURAL_FORMS_HPP
     20
     21#include <string>
     22
     23namespace tinygettext {
     24
     25typedef unsigned int (*PluralFunc)(int n);
     26
     27class PluralForms
     28{
     29private:
     30  unsigned int nplural;
     31  PluralFunc   plural;
     32
     33public:
     34  static PluralForms from_string(const std::string& str);
     35
     36  PluralForms()
     37    : nplural(0),
     38      plural(0)
     39  {}
     40
     41  PluralForms(unsigned int nplural_, PluralFunc plural_)
     42    : nplural(nplural_),
     43      plural(plural_)
     44  {}
     45
     46  unsigned int get_nplural() const { return nplural; }
     47  unsigned int get_plural(int n) const { if (plural) return plural(n); else return 0; }
     48
     49  bool operator==(const PluralForms& other) { return nplural == other.nplural && plural == other.plural; }
     50  bool operator!=(const PluralForms& other) { return !(*this == other); }
     51
     52  operator bool() const {
     53    return plural;
     54  }
     55};
     56
     57} // namespace tinygettext
     58
     59#endif
     60
     61/* EOF */
  • new file libraries/source/tinygettext/tinygettext/po_parser.cpp

    diff --git a/libraries/source/tinygettext/tinygettext/po_parser.cpp b/libraries/source/tinygettext/tinygettext/po_parser.cpp
    new file mode 100644
    index 0000000..ec73eed
    - +  
     1//  tinygettext - A gettext replacement that works directly on .po files
     2//  Copyright (C) 2009 Ingo Ruhnke <grumbel@gmx.de>
     3//
     4//  This program is free software; you can redistribute it and/or
     5//  modify it under the terms of the GNU General Public License
     6//  as published by the Free Software Foundation; either version 2
     7//  of the License, or (at your option) any later version.
     8//
     9//  This program is distributed in the hope that it will be useful,
     10//  but WITHOUT ANY WARRANTY; without even the implied warranty of
     11//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     12//  GNU General Public License for more details.
     13//
     14//  You should have received a copy of the GNU General Public License
     15//  along with this program; if not, write to the Free Software
     16//  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
     17
     18#include "po_parser.hpp"
     19
     20#include <iostream>
     21#include <ctype.h>
     22#include <string>
     23#include <istream>
     24#include <string.h>
     25#include <map>
     26#include <stdlib.h>
     27
     28#include "language.hpp"
     29#include "log_stream.hpp"
     30#include "iconv.hpp"
     31#include "dictionary.hpp"
     32#include "plural_forms.hpp"
     33
     34namespace tinygettext {
     35
     36bool POParser::pedantic = true;
     37
     38void
     39POParser::parse(const std::string& filename, std::istream& in, Dictionary& dict, bool use_fuzzy_)
     40{
     41  POParser parser(filename, in, dict, use_fuzzy_);
     42  parser.parse();
     43}
     44
    045
     46class POParserError {};
     47
     48POParser::POParser(const std::string& filename_, std::istream& in_, Dictionary& dict_, bool use_fuzzy_) :
     49  filename(filename_),
     50  in(in_),
     51  dict(dict_),
     52  use_fuzzy(use_fuzzy_),
     53  running(false),
     54  eof(false),
     55  big5(false),
     56  line_number(0),
     57  current_line(),
     58  conv()
     59{
     60}
     61
     62POParser::~POParser()
     63{
     64}
     65
     66void
     67POParser::warning(const std::string& msg)
     68{
     69  log_warning << filename << ":" << line_number << ": warning: " << msg << ": " << current_line << std::endl;
     70  //log_warning << "Line: " << current_line << std::endl;
     71}
     72
     73void
     74POParser::error(const std::string& msg)
     75{
     76  log_error << filename << ":" << line_number << ": error: " << msg  << ": " << current_line << std::endl;
     77
     78  // Try to recover from an error by searching for start of another entry
     79  do
     80    next_line();
     81  while(!eof && !is_empty_line());
     82
     83  throw POParserError();
     84}
     85
     86void
     87POParser::next_line()
     88{
     89  line_number += 1;
     90  if (!std::getline(in, current_line))
     91    eof = true;
     92}
     93
     94void
     95POParser::get_string_line(std::ostringstream& out,std::string::size_type skip)
     96{
     97  if (skip+1 >= static_cast<std::string::size_type>(current_line.size()))
     98    error("unexpected end of line");
     99
     100  if (current_line[skip] != '"')
     101    error("expected start of string '\"'");
     102 
     103  std::string::size_type i;
     104  for(i = skip+1; current_line[i] != '\"'; ++i)
     105  {
     106    if (big5 && static_cast<unsigned char>(current_line[i]) >= 0x81 && static_cast<unsigned char>(current_line[i]) <= 0xfe)
     107    {
     108      out << current_line[i];
     109
     110      i += 1;
     111         
     112      if (i >= current_line.size())
     113        error("invalid big5 encoding");
     114         
     115      out << current_line[i];
     116    }
     117    else if (i >= current_line.size())
     118    {
     119      error("unexpected end of string");
     120    }
     121    else if (current_line[i] == '\\')
     122    {
     123      i += 1;
     124
     125      if (i >= current_line.size())
     126        error("unexpected end of string in handling '\\'");
     127
     128      switch (current_line[i])
     129      {
     130        case 'a':  out << '\a'; break;
     131        case 'b':  out << '\b'; break;
     132        case 'v':  out << '\v'; break;
     133        case 'n':  out << '\n'; break;
     134        case 't':  out << '\t'; break;
     135        case 'r':  out << '\r'; break;
     136        case '"':  out << '"'; break;
     137        case '\\': out << '\\'; break;
     138        default:
     139          std::ostringstream err;
     140          err << "unhandled escape '\\" << current_line[i] << "'";
     141          warning(err.str());
     142
     143          out << current_line[i-1] << current_line[i];
     144          break;
     145      }
     146    }
     147    else
     148    {
     149      out << current_line[i];
     150    }
     151  }
     152
     153  // process trailing garbage in line and warn if there is any
     154  for(i = i+1; i < current_line.size(); ++i)
     155    if (!isspace(current_line[i]))
     156    {
     157      warning("unexpected garbage after string ignoren");
     158      break;
     159    }
     160}
     161
     162std::string
     163POParser::get_string(std::string::size_type skip)
     164{
     165  std::ostringstream out;
     166
     167  if (skip+1 >= static_cast<std::string::size_type>(current_line.size()))
     168    error("unexpected end of line");
     169
     170  if (current_line[skip] == ' ' && current_line[skip+1] == '"')
     171  {
     172    get_string_line(out, skip+1);
     173  }
     174  else
     175  {
     176    if (pedantic)
     177      warning("keyword and string must be seperated by a single space");
     178
     179    for(;;)
     180    {
     181      if (skip >= static_cast<std::string::size_type>(current_line.size()))
     182        error("unexpected end of line");
     183      else if (current_line[skip] == '\"')
     184      {
     185        get_string_line(out, skip);
     186        break;
     187      }
     188      else if (!isspace(current_line[skip]))
     189      {
     190        error("string must start with '\"'");
     191      }
     192      else
     193      {
     194        // skip space
     195      }
     196
     197      skip += 1;
     198    }
     199  }
     200 
     201next:
     202  next_line();
     203  for(std::string::size_type i = 0; i < current_line.size(); ++i)
     204  {
     205    if (current_line[i] == '"')
     206    {
     207      if (i == 1)
     208        if (pedantic)
     209          warning("leading whitespace before string");
     210
     211      get_string_line(out, i);
     212      goto next;
     213    }
     214    else if (isspace(current_line[i]))
     215    {
     216      // skip
     217    }
     218    else
     219    {
     220      break;
     221    }
     222  }
     223
     224  return out.str();
     225}
     226
     227static bool has_prefix(const std::string& lhs, const std::string rhs)
     228{
     229  if (lhs.length() < rhs.length())
     230    return false;
     231  else
     232    return lhs.compare(0, rhs.length(), rhs) == 0;
     233}
     234
     235void
     236POParser::parse_header(const std::string& header)
     237{
     238  std::string from_charset;
     239  std::string::size_type start = 0;
     240  for(std::string::size_type i = 0; i < header.length(); ++i)
     241  {
     242    if (header[i] == '\n')
     243    {
     244      std::string line = header.substr(start, i - start);
     245
     246      if (has_prefix(line, "Content-Type:"))
     247      {
     248        // from_charset = line.substr(len);
     249        std::string::size_type len = strlen("Content-Type: text/plain; charset=");
     250        if (line.compare(0, len, "Content-Type: text/plain; charset=") == 0)
     251        {
     252          from_charset = line.substr(len);
     253
     254          for(std::string::iterator ch = from_charset.begin(); ch != from_charset.end(); ++ch)
     255            *ch = static_cast<char>(toupper(*ch));
     256        }
     257        else
     258        {
     259          warning("malformed Content-Type header");
     260        }
     261      }
     262      else if (has_prefix(line, "Plural-Forms:"))
     263      {
     264        PluralForms plural_forms = PluralForms::from_string(line);
     265        if (!plural_forms)
     266        {
     267          warning("unknown Plural-Forms given");
     268        }
     269        else
     270        {
     271          if (!dict.get_plural_forms())
     272          {
     273            dict.set_plural_forms(plural_forms);
     274          }
     275          else
     276          {
     277            if (dict.get_plural_forms() != plural_forms)
     278            {
     279              warning("Plural-Forms missmatch between .po file and dictionary");
     280            }
     281          }
     282        }
     283      }
     284      start = i+1;
     285    }
     286  }
     287
     288  if (from_charset.empty() || from_charset == "CHARSET")
     289  {
     290    warning("charset not specified for .po, fallback to utf-8");
     291    from_charset = "UTF-8";
     292  }
     293  else if (from_charset == "BIG5")
     294  {
     295    big5 = true;
     296  }
     297
     298  conv.set_charsets(from_charset, dict.get_charset());
     299}
     300
     301bool
     302POParser::is_empty_line()
     303{
     304  if (current_line.empty())
     305  {
     306    return true;
     307  }
     308  else if (current_line[0] == '#')
     309  { // handle comments as empty lines
     310    if (current_line.size() == 1 || (current_line.size() >= 2 && isspace(current_line[1])))
     311      return true;
     312    else
     313      return false;
     314  }
     315  else
     316  {
     317    for(std::string::iterator i = current_line.begin(); i != current_line.end(); ++i)
     318    {
     319      if (!isspace(*i))
     320        return false;
     321    }
     322  }
     323  return true;
     324}
     325
     326bool
     327POParser::prefix(const char* prefix_str)
     328{
     329  return current_line.compare(0, strlen(prefix_str), prefix_str) == 0;
     330}
     331
     332void
     333POParser::parse()
     334{
     335  next_line();
     336
     337  // skip UTF-8 intro that some text editors produce
     338  // see http://en.wikipedia.org/wiki/Byte-order_mark
     339  if (current_line.size() >= 3 &&
     340      current_line[0] == static_cast<char>(0xef) &&
     341      current_line[1] == static_cast<char>(0xbb) &&
     342      current_line[2] == static_cast<char>(0xbf))
     343  {
     344    current_line = current_line.substr(3);
     345  }
     346
     347  // Parser structure
     348  while(!eof)
     349  {
     350    try
     351    {
     352      bool fuzzy =  false;
     353      bool has_msgctxt = false;
     354      std::string msgctxt;
     355      std::string msgid;
     356
     357      while(prefix("#"))
     358      {
     359        if (current_line.size() >= 2 && current_line[1] == ',')
     360        {
     361          // FIXME: Rather simplistic hunt for fuzzy flag
     362          if (current_line.find("fuzzy", 2) != std::string::npos)
     363            fuzzy = true;
     364        }
     365
     366        next_line();
     367      }
     368
     369      if (!is_empty_line())
     370      {
     371        if (prefix("msgctxt"))
     372        {
     373          has_msgctxt = true;
     374          msgctxt = get_string(7);
     375        }
     376
     377        if (prefix("msgid"))
     378          msgid = get_string(5);
     379        else
     380          error("expected 'msgid'");
     381
     382        if (prefix("msgid_plural"))
     383        {
     384          std::string msgid_plural = get_string(12);
     385          std::vector<std::string> msgstr_num;
     386      bool saw_nonempty_msgstr = false;
     387
     388        next:
     389          if (is_empty_line())
     390          {
     391            if (msgstr_num.empty())
     392              error("expected 'msgstr[N] (0 <= N <= 9)'");
     393          }
     394          else if (prefix("msgstr[") &&
     395                   current_line.size() > 8 &&
     396                   isdigit(current_line[7]) && current_line[8] == ']')
     397          {
     398            std::string::size_type number = static_cast<std::string::size_type>(current_line[7] - '0');
     399        std::string msgstr = get_string(9);
     400
     401        if(!msgstr.empty())
     402          saw_nonempty_msgstr = true;
     403
     404            if (number >= msgstr_num.size())
     405              msgstr_num.resize(number+1);
     406
     407            msgstr_num[number] = conv.convert(msgstr);
     408            goto next;
     409          }
     410          else
     411          {
     412            error("expected 'msgstr[N]'");
     413          }
     414
     415          if (!is_empty_line())
     416            error("expected 'msgstr[N]' or empty line");
     417
     418      if (saw_nonempty_msgstr)
     419      {
     420        if (use_fuzzy || !fuzzy)
     421            {
     422          if (!dict.get_plural_forms())
     423          {
     424        warning("msgstr[N] seen, but no Plural-Forms given");
     425          }
     426          else
     427          {
     428        if (msgstr_num.size() != dict.get_plural_forms().get_nplural())
     429        {
     430          warning("msgstr[N] count doesn't match Plural-Forms.nplural");
     431        }
     432          }
     433
     434          if (has_msgctxt)
     435        dict.add_translation(msgctxt, msgid, msgid_plural, msgstr_num);
     436          else
     437        dict.add_translation(msgid, msgid_plural, msgstr_num);
     438        }
     439
     440        if (0)
     441        {
     442          std::cout << (fuzzy?"fuzzy":"not-fuzzy") << std::endl;
     443          std::cout << "msgid \"" << msgid << "\"" << std::endl;
     444          std::cout << "msgid_plural \"" << msgid_plural << "\"" << std::endl;
     445          for(std::vector<std::string>::size_type i = 0; i < msgstr_num.size(); ++i)
     446        std::cout << "msgstr[" << i << "] \"" << conv.convert(msgstr_num[i]) << "\"" << std::endl;
     447          std::cout << std::endl;
     448        }
     449      }
     450        }
     451        else if (prefix("msgstr"))
     452        {
     453          std::string msgstr = get_string(6);
     454
     455          if (msgid.empty())
     456          {
     457            parse_header(msgstr);
     458          }
     459          else if(!msgstr.empty())
     460          {
     461            if (use_fuzzy || !fuzzy)
     462            {
     463              if (has_msgctxt)
     464                dict.add_translation(msgctxt, msgid, conv.convert(msgstr));
     465              else
     466                dict.add_translation(msgid, conv.convert(msgstr));
     467            }
     468
     469            if (0)
     470            {
     471              std::cout << (fuzzy?"fuzzy":"not-fuzzy") << std::endl;
     472              std::cout << "msgid \"" << msgid << "\"" << std::endl;
     473              std::cout << "msgstr \"" << conv.convert(msgstr) << "\"" << std::endl;
     474              std::cout << std::endl;
     475            }
     476          }
     477        }
     478        else
     479        {
     480          error("expected 'msgstr' or 'msgid_plural'");
     481        }
     482      }
     483     
     484      if (!is_empty_line())
     485        error("expected empty line");
     486
     487      next_line();
     488    }
     489    catch(POParserError&)
     490    {         
     491    }
     492  }
     493}
     494
     495} // namespace tinygettext
     496
  • new file libraries/source/tinygettext/tinygettext/po_parser.hpp

    +/* EOF */
    diff --git a/libraries/source/tinygettext/tinygettext/po_parser.hpp b/libraries/source/tinygettext/tinygettext/po_parser.hpp
    new file mode 100644
    index 0000000..865597a
    - +  
     1//  tinygettext - A gettext replacement that works directly on .po files
     2//  Copyright (C) 2009 Ingo Ruhnke <grumbel@gmx.de>
     3//
     4//  This program is free software; you can redistribute it and/or
     5//  modify it under the terms of the GNU General Public License
     6//  as published by the Free Software Foundation; either version 2
     7//  of the License, or (at your option) any later version.
     8//
     9//  This program is distributed in the hope that it will be useful,
     10//  but WITHOUT ANY WARRANTY; without even the implied warranty of
     11//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     12//  GNU General Public License for more details.
     13//
     14//  You should have received a copy of the GNU General Public License
     15//  along with this program; if not, write to the Free Software
     16//  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
     17
     18#ifndef HEADER_TINYGETTEXT_PO_PARSER_HPP
     19#define HEADER_TINYGETTEXT_PO_PARSER_HPP
     20
     21#include <iosfwd>
     22
     23#include "iconv.hpp"
     24
     25namespace tinygettext {
     26
     27class Dictionary;
     28
     29class POParser
     30{
     31private:
     32  std::string filename;
     33  std::istream& in;
     34  Dictionary& dict;
     35  bool  use_fuzzy;
     36
     37  bool running;
     38  bool eof;
     39  bool big5;
     40
     41  int line_number;
     42  std::string current_line;
     43
     44  IConv conv;
     45 
     46  POParser(const std::string& filename, std::istream& in_, Dictionary& dict_, bool use_fuzzy = true);
     47  ~POParser();
     48
     49  void parse_header(const std::string& header);
     50  void parse();
     51  void next_line();
     52  std::string get_string(std::string::size_type skip);
     53  void get_string_line(std::ostringstream& str,std::string::size_type skip);
     54  bool is_empty_line();
     55  bool prefix(const char* );
     56  void error(const std::string& msg);
     57  void warning(const std::string& msg);
     58
     59public:
     60  /** @param filename name of the istream, only used in error messages
     61      @param in stream from which the PO file is read.
     62      @param dict dictionary to which the strings are written */
     63  static void parse(const std::string& filename, std::istream& in, Dictionary& dict, bool use_fuzzy = true);
     64  static bool pedantic;
     65
     66private:
     67  POParser (const POParser&);
     68  POParser& operator= (const POParser&);
     69};
     70
     71} // namespace tinygettext
     72
     73#endif
     74
     75/* EOF */
  • new file libraries/source/tinygettext/tinygettext/tinygettext.cpp

    diff --git a/libraries/source/tinygettext/tinygettext/tinygettext.cpp b/libraries/source/tinygettext/tinygettext/tinygettext.cpp
    new file mode 100644
    index 0000000..7f5adc8
    - +  
     1//  tinygettext - A gettext replacement that works directly on .po files
     2//  Copyright (C) 2006 Ingo Ruhnke <grumbel@gmx.de>
     3//
     4//  This program is free software; you can redistribute it and/or
     5//  modify it under the terms of the GNU General Public License
     6//  as published by the Free Software Foundation; either version 2
     7//  of the License, or (at your option) any later version.
     8//
     9//  This program is distributed in the hope that it will be useful,
     10//  but WITHOUT ANY WARRANTY; without even the implied warranty of
     11//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     12//  GNU General Public License for more details.
     13//
     14//  You should have received a copy of the GNU General Public License
     15//  along with this program; if not, write to the Free Software
     16//  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
     17
     18namespace tinygettext {
     19
     20} // namespace tinygettext
     21
     22/* EOF */
  • new file libraries/source/tinygettext/tinygettext/tinygettext.hpp

    diff --git a/libraries/source/tinygettext/tinygettext/tinygettext.hpp b/libraries/source/tinygettext/tinygettext/tinygettext.hpp
    new file mode 100644
    index 0000000..19fd4c6
    - +  
     1//  tinygettext - A gettext replacement that works directly on .po files
     2//  Copyright (C) 2006 Ingo Ruhnke <grumbel@gmx.de>
     3//
     4//  This program is free software; you can redistribute it and/or
     5//  modify it under the terms of the GNU General Public License
     6//  as published by the Free Software Foundation; either version 2
     7//  of the License, or (at your option) any later version.
     8//
     9//  This program is distributed in the hope that it will be useful,
     10//  but WITHOUT ANY WARRANTY; without even the implied warranty of
     11//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     12//  GNU General Public License for more details.
     13//
     14//  You should have received a copy of the GNU General Public License
     15//  along with this program; if not, write to the Free Software
     16//  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
     17
     18#ifndef HEADER_TINYGETTEXT_TINYGETTEXT_HPP
     19#define HEADER_TINYGETTEXT_TINYGETTEXT_HPP
     20
     21#include "dictionary.hpp"
     22#include "dictionary_manager.hpp"
     23#include "language.hpp"
     24
     25#endif
     26
     27/* EOF */
  • new file libraries/source/tinygettext/tinygettext/unix_file_system.cpp

    diff --git a/libraries/source/tinygettext/tinygettext/unix_file_system.cpp b/libraries/source/tinygettext/tinygettext/unix_file_system.cpp
    new file mode 100644
    index 0000000..5e14d17
    - +  
     1//  tinygettext - A gettext replacement that works directly on .po files
     2//  Copyright (C) 2009 Ingo Ruhnke <grumbel@gmx.de>
     3//
     4//  This program is free software; you can redistribute it and/or
     5//  modify it under the terms of the GNU General Public License
     6//  as published by the Free Software Foundation; either version 2
     7//  of the License, or (at your option) any later version.
     8//
     9//  This program is distributed in the hope that it will be useful,
     10//  but WITHOUT ANY WARRANTY; without even the implied warranty of
     11//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     12//  GNU General Public License for more details.
     13//
     14//  You should have received a copy of the GNU General Public License
     15//  along with this program; if not, write to the Free Software
     16//  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
     17
     18#include "unix_file_system.hpp"
     19
     20#include <sys/types.h>
     21#include <fstream>
     22#include <dirent.h>
     23#include <stdlib.h>
     24#include <dirent.h>
     25#include <string.h>
     26
     27namespace tinygettext {
     28
     29UnixFileSystem::UnixFileSystem()
     30{
     31}
     32
     33std::vector<std::string>
     34UnixFileSystem::open_directory(const std::string& pathname)
     35{
     36  DIR* dir = opendir(pathname.c_str());
     37  if (!dir)
     38  {
     39    // FIXME: error handling
     40    return std::vector<std::string>();
     41  }
     42  else
     43  {
     44    std::vector<std::string> files;
     45
     46    struct dirent* dp;
     47    while((dp = readdir(dir)) != 0)
     48    {
     49      files.push_back(dp->d_name);
     50    }
     51    closedir(dir);
     52
     53    return files;
     54  }
     55}
     56 
     57std::auto_ptr<std::istream>
     58UnixFileSystem::open_file(const std::string& filename)
     59{
     60  return std::auto_ptr<std::istream>(new std::ifstream(filename.c_str()));
     61}
     62
     63} // namespace tinygettext
     64
     65/* EOF */
  • new file libraries/source/tinygettext/tinygettext/unix_file_system.hpp

    diff --git a/libraries/source/tinygettext/tinygettext/unix_file_system.hpp b/libraries/source/tinygettext/tinygettext/unix_file_system.hpp
    new file mode 100644
    index 0000000..80f3e6d
    - +  
     1//  tinygettext - A gettext replacement that works directly on .po files
     2//  Copyright (C) 2009 Ingo Ruhnke <grumbel@gmx.de>
     3//
     4//  This program is free software; you can redistribute it and/or
     5//  modify it under the terms of the GNU General Public License
     6//  as published by the Free Software Foundation; either version 2
     7//  of the License, or (at your option) any later version.
     8//
     9//  This program is distributed in the hope that it will be useful,
     10//  but WITHOUT ANY WARRANTY; without even the implied warranty of
     11//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     12//  GNU General Public License for more details.
     13//
     14//  You should have received a copy of the GNU General Public License
     15//  along with this program; if not, write to the Free Software
     16//  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
     17
     18#ifndef HEADER_TINYGETTEXT_UNIX_FILE_SYSTEM_HPP
     19#define HEADER_TINYGETTEXT_UNIX_FILE_SYSTEM_HPP
     20
     21#include "file_system.hpp"
     22
     23namespace tinygettext {
     24
     25class UnixFileSystem : public FileSystem
     26{
     27public:
     28  UnixFileSystem();
     29
     30  std::vector<std::string>    open_directory(const std::string& pathname);
     31  std::auto_ptr<std::istream> open_file(const std::string& filename);
     32};
     33
     34} // namespace tinygettext
     35
     36#endif
     37
     38/* EOF */
  • source/gui/CGUI.cpp

    diff --git a/source/gui/CGUI.cpp b/source/gui/CGUI.cpp
    index 6ad0c60..ab03039 100644
    a b CGUI  
    4646#include "graphics/TextRenderer.h"
    4747#include "lib/input.h"
    4848#include "lib/bits.h"
     49#include "i18n/L10n.h"
    4950#include "lib/timer.h"
    5051#include "lib/sysdep/sysdep.h"
     52#include "lib/utf8.h"
    5153#include "ps/CLogger.h"
    5254#include "ps/Filesystem.h"
    5355#include "ps/Hotkey.h"
    void CGUI::Xeromyces_ReadObject(XMBElement Element, CXeromyces* pFile, IGUIObjec  
    11841186    ELMT(object);
    11851187    ELMT(action);
    11861188    ELMT(repeat);
     1189    ELMT(translatableAttribute);
     1190    ELMT(translate);
     1191    ELMT(attribute);
     1192    ELMT(keep);
    11871193    ATTR(style);
    11881194    ATTR(type);
    11891195    ATTR(name);
    void CGUI::Xeromyces_ReadObject(XMBElement Element, CXeromyces* pFile, IGUIObjec  
    11911197    ATTR(z);
    11921198    ATTR(on);
    11931199    ATTR(file);
     1200    ATTR(id);
    11941201
    11951202    //
    11961203    //  Read Style and set defaults
    void CGUI::Xeromyces_ReadObject(XMBElement Element, CXeromyces* pFile, IGUIObjec  
    13311338                code = scriptfile.DecodeUTF8(); // assume it's UTF-8
    13321339            }
    13331340
    1334             // Read the inline code (concatenating to the file code, if both are specified)
    1335             code += CStr(child.GetText());
     1341            XMBElementList grandchildren = child.GetChildNodes();
     1342            if (grandchildren.Count > 0) // The <action> element contains <keep> and <translate> tags.
     1343            {
     1344                for (int i = 0; i < grandchildren.Count; ++i)
     1345                {
     1346                    XMBElement grandchild = grandchildren.Item(i);
     1347                    if (grandchild.GetNodeName() == elmt_translate)
     1348                    {
     1349                        code += L10n::instance().translate(grandchild.GetText());
     1350                    }
     1351                    else if (grandchild.GetNodeName() == elmt_keep)
     1352                    {
     1353                        code += grandchild.GetText();
     1354                    }
     1355                }
     1356            }
     1357            else // It’s pure JavaScript code.
     1358            {
     1359                // Read the inline code (concatenating to the file code, if both are specified)
     1360                code += CStr(child.GetText());
     1361            }
    13361362
    13371363            CStr action = CStr(child.GetAttributes().GetNamedItem(attr_on));
    13381364            object->RegisterScriptHandler(action.LowerCase(), code, this);
    void CGUI::Xeromyces_ReadObject(XMBElement Element, CXeromyces* pFile, IGUIObjec  
    13411367        {
    13421368            Xeromyces_ReadRepeat(child, pFile, object, Paths);
    13431369        }
     1370        else if (element_name == elmt_translatableAttribute)
     1371        {
     1372            // This is an element in the form “<translatableAttribute id="attributeName">attributeValue</translatableAttribute>”.
     1373            CStr attributeName(child.GetAttributes().GetNamedItem(attr_id)); // Read the attribute name.
     1374            if (!attributeName.empty())
     1375            {
     1376                CStr value(child.GetText());
     1377                if (!value.empty())
     1378                {
     1379                    CStr translatedValue(L10n::instance().translate(value));
     1380                    object->SetSetting(attributeName, translatedValue.UnescapeBackslashes().FromUTF8(), true);
     1381                }
     1382            }
     1383            else // Ignore.
     1384            {
     1385                LOGERROR(L"GUI: ‘attribute’ XML element with empty ‘id’ XML attribute found. (object: %hs)", object->GetPresentableName().c_str());
     1386            }
     1387        }
     1388        else if (element_name == elmt_attribute)
     1389        {
     1390            // This is an element in the form “<attribute id="attributeName"><keep>Don’t translate this part
     1391            // </keep><translate>but translate this one.</translate></attribute>”.
     1392            CStr attributeName(child.GetAttributes().GetNamedItem(attr_id)); // Read the attribute name.
     1393            if (!attributeName.empty())
     1394            {
     1395                CStr translatedValue;
     1396
     1397                XMBElementList grandchildren = child.GetChildNodes();
     1398                for (int i = 0; i < grandchildren.Count; ++i)
     1399                {
     1400                    XMBElement grandchild = grandchildren.Item(i);
     1401                    if (grandchild.GetNodeName() == elmt_translate)
     1402                    {
     1403                        translatedValue += L10n::instance().translate(grandchild.GetText());
     1404                    }
     1405                    else if (grandchild.GetNodeName() == elmt_keep)
     1406                    {
     1407                        translatedValue += grandchild.GetText();
     1408                    }
     1409                }
     1410                object->SetSetting(attributeName, translatedValue.UnescapeBackslashes().FromUTF8(), true);
     1411            }
     1412            else // Ignore.
     1413            {
     1414                LOGERROR(L"GUI: ‘attribute’ XML element with empty ‘id’ XML attribute found. (object: %hs)", object->GetPresentableName().c_str());
     1415            }
     1416        }
    13441417        else
    13451418        {
    13461419            // Try making the object read the tag.
  • source/gui/GUIRenderer.cpp

    diff --git a/source/gui/GUIRenderer.cpp b/source/gui/GUIRenderer.cpp
    index 9531158..4113a8d 100644
    a b  
    2222#include "graphics/ShaderManager.h"
    2323#include "graphics/TextureManager.h"
    2424#include "gui/GUIutil.h"
     25#include "i18n/L10n.h"
    2526#include "lib/ogl.h"
    2627#include "lib/utf8.h"
    2728#include "lib/res/h_mgr.h"
    void GUIRenderer::UpdateDrawCallCache(DrawCalls &Calls, const CStr& SpriteName,  
    200201
    201202        if (! cit->m_TextureName.empty())
    202203        {
    203             CTextureProperties textureProps(cit->m_TextureName);
     204            CTextureProperties textureProps(L10n::instance().localizePath(cit->m_TextureName));
    204205            textureProps.SetWrap(cit->m_WrapMode);
    205206            CTexturePtr texture = g_Renderer.GetTextureManager().CreateTexture(textureProps);
    206207            texture->Prefetch();
  • source/gui/scripting/ScriptFunctions.cpp

    diff --git a/source/gui/scripting/ScriptFunctions.cpp b/source/gui/scripting/ScriptFunctions.cpp
    index 6913c2b..e95477f 100644
    a b  
    2424#include "graphics/MapReader.h"
    2525#include "gui/GUIManager.h"
    2626#include "graphics/scripting/JSInterface_GameView.h"
     27#include "i18n/L10n.h"
     28#include "lib/svn_revision.h"
    2729#include "lib/timer.h"
    2830#include "lib/utf8.h"
    2931#include "lib/sysdep/sysdep.h"
    void SetBoundingBoxDebugOverlay(void* UNUSED(cbdata), bool enabled)  
    650652    ICmpSelectable::ms_EnableDebugOverlays = enabled;
    651653}
    652654
     655// Return the date/time at which the current executable was compiled.
     656// params: none (-> "date time (svn revision)") OR an integer specifying
     657//   what to display: 0 for date, 1 for time, 2 for svn revision
     658// returns: string with the requested timestamp info
     659// notes:
     660// - Displayed on main menu screen; tells non-programmers which auto-build
     661//   they are running. Could also be determined via .EXE file properties,
     662//   but that's a bit more trouble.
     663// - To be exact, the date/time returned is when scriptglue.cpp was
     664//   last compiled, but the auto-build does full rebuilds.
     665// - svn revision is generated by calling svnversion and cached in
     666//   lib/svn_revision.cpp. it is useful to know when attempting to
     667//   reproduce bugs (the main EXE and PDB should be temporarily reverted to
     668//   that revision so that they match user-submitted crashdumps).
     669std::wstring GetBuildTimestamp(void* UNUSED(cbdata), int mode)
     670{
     671    char buf[200];
     672    if (mode == -1) // Date, time and revision.
     673    {
     674        UDate dateTime = L10n::instance().parseDateTime(__DATE__ " " __TIME__, "MMM d yyyy HH:mm:ss", Locale::getUS());
     675        std::string dateTimeString = L10n::instance().localizeDateTime(dateTime, L10n::DateTime, SimpleDateFormat::DATE_TIME);
     676        char svnRevision[32];
     677        sprintf_s(svnRevision, ARRAY_SIZE(svnRevision), "%ls", svn_revision);
     678        if (strcmp(svnRevision, "custom build") == 0)
     679        {
     680            // Translation: First item is a date and time, item between parenthesis is the Subversion revision number of the current build.
     681            sprintf_s(buf, ARRAY_SIZE(buf), L10n::instance().translate("%s (custom build)").c_str(), dateTimeString.c_str());
     682        }
     683        else
     684        {
     685            // Translation: First item is a date and time, item between parenthesis is the Subversion revision number of the current build.
     686            sprintf_s(buf, ARRAY_SIZE(buf), L10n::instance().translate("%s (%ls)").c_str(), dateTimeString.c_str(), svn_revision);
     687        }
     688    }
     689    else if (mode == 0) // Date.
     690    {
     691        UDate dateTime = L10n::instance().parseDateTime(__DATE__, "MMM d yyyy", Locale::getUS());
     692        std::string dateTimeString = L10n::instance().localizeDateTime(dateTime, L10n::Date, SimpleDateFormat::MEDIUM);
     693        sprintf_s(buf, ARRAY_SIZE(buf), "%s", dateTimeString.c_str());
     694    }
     695    else if (mode == 1) // Time.
     696    {
     697        UDate dateTime = L10n::instance().parseDateTime(__TIME__, "HH:mm:ss", Locale::getUS());
     698        std::string dateTimeString = L10n::instance().localizeDateTime(dateTime, L10n::Time, SimpleDateFormat::MEDIUM);
     699        sprintf_s(buf, ARRAY_SIZE(buf), "%s", dateTimeString.c_str());
     700    }
     701    else if (mode == 2) // Revision.
     702    {
     703        char svnRevision[32];
     704        sprintf_s(svnRevision, ARRAY_SIZE(svnRevision), "%ls", svn_revision);
     705        if (strcmp(svnRevision, "custom build") == 0)
     706        {
     707            sprintf_s(buf, ARRAY_SIZE(buf), L10n::instance().translate("custom build").c_str());
     708        }
     709        else
     710        {
     711            sprintf_s(buf, ARRAY_SIZE(buf), "%ls", svn_revision);
     712        }
     713    }
     714
     715    return wstring_from_utf8(buf);
     716}
     717
     718// Return the current locale code.
     719std::string getCurrentLocale(void* UNUSED(cbdata))
     720{
     721    return L10n::instance().getCurrentLocale().getLanguage();
     722}
     723
     724// Returns a translation of the specified English string into the current language.
     725std::wstring translate(void* UNUSED(cbdata), std::wstring sourceString)
     726{
     727    return wstring_from_utf8(L10n::instance().translate(utf8_from_wstring(sourceString)));
     728}
     729
     730// Returns a translation of the specified English string, for the specified context.
     731std::wstring translateWithContext(void* UNUSED(cbdata), std::string context, std::wstring sourceString)
     732{
     733    return wstring_from_utf8(L10n::instance().translateWithContext(context, utf8_from_wstring(sourceString)));
     734}
     735
     736// Return a translated version of the given strings (singular and plural) depending on an integer value.
     737std::wstring translatePlural(void* UNUSED(cbdata), std::wstring singularSourceString, std::wstring pluralSourceString, int number)
     738{
     739    return wstring_from_utf8(L10n::instance().translatePlural(utf8_from_wstring(singularSourceString), utf8_from_wstring(pluralSourceString), number));
     740}
     741
     742// Return a translated version of the given strings (singular and plural) depending on an integer value, for the specified context.
     743std::wstring translatePluralWithContext(void* UNUSED(cbdata), std::string context, std::wstring singularSourceString, std::wstring pluralSourceString, int number)
     744{
     745    return wstring_from_utf8(L10n::instance().translatePluralWithContext(context, utf8_from_wstring(singularSourceString), utf8_from_wstring(pluralSourceString), number));
     746}
     747
     748// Return a translated version of the given string, localizing it line by line.
     749std::wstring translateLines(void* UNUSED(cbdata), std::wstring sourceString)
     750{
     751    return wstring_from_utf8(L10n::instance().translateLines(utf8_from_wstring(sourceString)));
     752}
     753
     754// Return a translated version of the items in the specified array.
     755std::vector<std::wstring> translateArray(void* UNUSED(cbdata), std::vector<std::wstring> sourceArray)
     756{
     757    std::vector<std::wstring> translatedArray;
     758    for (std::vector<std::wstring>::iterator iterator = sourceArray.begin(); iterator != sourceArray.end(); ++iterator)
     759    {
     760        translatedArray.push_back(wstring_from_utf8(L10n::instance().translate(utf8_from_wstring(*iterator))));
     761    }
     762    return translatedArray;
     763}
     764
     765// Return a localized version of a time given in milliseconds.
     766std::wstring formatMillisecondsIntoDateString(void* UNUSED(cbdata), int milliseconds, std::wstring formatString)
     767{
     768    return wstring_from_utf8(L10n::instance().formatMillisecondsIntoDateString(milliseconds, utf8_from_wstring(formatString)));
     769}
     770
     771// Return a localized version of the given decimal number.
     772std::wstring formatDecimalNumberIntoString(void* UNUSED(cbdata), double number)
     773{
     774    return wstring_from_utf8(L10n::instance().formatDecimalNumberIntoString(number));
     775}
     776
     777// Return a translated version of the given decimal number.
     778std::wstring markToTranslate(void* UNUSED(cbdata), std::wstring sourceString)
     779{
     780    return sourceString;
     781}
     782
     783std::vector<std::string> GetSupportedLocaleCodes(void* UNUSED(cbdata))
     784{
     785    return L10n::instance().getSupportedLocaleCodes();
     786}
     787
     788std::vector<std::wstring> GetSupportedLocaleDisplayNames(void* UNUSED(cbdata))
     789{
     790    return L10n::instance().getSupportedLocaleDisplayNames();
     791}
     792
     793int GetCurrentLocaleIndex(void* UNUSED(cbdata))
     794{
     795    return L10n::instance().getCurrentLocaleIndex();
     796}
     797
     798void SetLocale(void* UNUSED(cbdata), std::string locale)
     799{
     800    // Save the new locale in the settings file.
     801    g_ConfigDB.CreateValue(CFG_USER, "locale")->m_String = locale;
     802    g_ConfigDB.WriteFile(CFG_USER);
     803
     804    // Reload the localization singleton to use the selected locale.
     805    L10n::instance().setCurrentLocale(locale);
     806}
     807
    653808} // namespace
    654809
    655810void GuiScriptingInit(ScriptInterface& scriptInterface)
    void GuiScriptingInit(ScriptInterface& scriptInterface)  
    743898    scriptInterface.RegisterFunction<void, unsigned int, &EnableTimeWarpRecording>("EnableTimeWarpRecording");
    744899    scriptInterface.RegisterFunction<void, &RewindTimeWarp>("RewindTimeWarp");
    745900    scriptInterface.RegisterFunction<void, bool, &SetBoundingBoxDebugOverlay>("SetBoundingBoxDebugOverlay");
     901
     902    // Internationalization and localization functions
     903    scriptInterface.RegisterFunction<std::wstring, int, &GetBuildTimestamp>("GetBuildTimestamp");
     904    scriptInterface.RegisterFunction<std::string, &getCurrentLocale>("getCurrentLocale");
     905    scriptInterface.RegisterFunction<std::wstring, std::wstring, &translate>("translate");
     906    scriptInterface.RegisterFunction<std::wstring, std::string, std::wstring, &translateWithContext>("translateWithContext");
     907    scriptInterface.RegisterFunction<std::wstring, std::wstring, std::wstring, int, &translatePlural>("translatePlural");
     908    scriptInterface.RegisterFunction<std::wstring, std::string, std::wstring, std::wstring, int, &translatePluralWithContext>("translatePluralWithContext");
     909    scriptInterface.RegisterFunction<std::wstring, std::wstring, &translateLines>("translateLines");
     910    scriptInterface.RegisterFunction<std::vector<std::wstring>, std::vector<std::wstring>, &translateArray>("translateArray");
     911    scriptInterface.RegisterFunction<std::wstring, int, std::wstring, &formatMillisecondsIntoDateString>("formatMillisecondsIntoDateString");
     912    scriptInterface.RegisterFunction<std::wstring, double, &formatDecimalNumberIntoString>("formatDecimalNumberIntoString");
     913    scriptInterface.RegisterFunction<std::wstring, std::wstring, &markToTranslate>("markToTranslate");
     914    scriptInterface.RegisterFunction<std::vector<std::string>, &GetSupportedLocaleCodes>("GetSupportedLocaleCodes");
     915    scriptInterface.RegisterFunction<std::vector<std::wstring>, &GetSupportedLocaleDisplayNames>("GetSupportedLocaleDisplayNames");
     916    scriptInterface.RegisterFunction<int, &GetCurrentLocaleIndex>("GetCurrentLocaleIndex");
     917    scriptInterface.RegisterFunction<void, std::string, &SetLocale>("SetLocale");
    746918}
  • new file source/i18n/L10n.cpp

    diff --git a/source/i18n/L10n.cpp b/source/i18n/L10n.cpp
    new file mode 100644
    index 0000000..2a9ca1a
    - +  
     1/* Copyright (c) 2013 Wildfire Games
     2 *
     3 * Permission is hereby granted, free of charge, to any person obtaining
     4 * a copy of this software and associated documentation files (the
     5 * "Software"), to deal in the Software without restriction, including
     6 * without limitation the rights to use, copy, modify, merge, publish,
     7 * distribute, sublicense, and/or sell copies of the Software, and to
     8 * permit persons to whom the Software is furnished to do so, subject to
     9 * the following conditions:
     10 *
     11 * The above copyright notice and this permission notice shall be included
     12 * in all copies or substantial portions of the Software.
     13 *
     14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
     15 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
     16 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
     17 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
     18 * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
     19 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
     20 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
     21 */
     22
     23#include "i18n/L10n.h"
     24
     25#include <iostream>
     26#include <string>
     27#include <boost/concept_check.hpp>
     28
     29#include "lib/file/file_system.h"
     30#include "lib/utf8.h"
     31
     32#include "ps/CLogger.h"
     33#include "ps/ConfigDB.h"
     34#include "ps/Filesystem.h"
     35#include "ps/GameSetup/GameSetup.h"
     36
     37
     38L10n& L10n::instance()
     39{
     40    static L10n m_instance;
     41    return m_instance;
     42}
     43
     44L10n::L10n()
     45: currentLocaleIsOriginalGameLocale(false) // determineCurrentLocale() takes care of setting this value to true.
     46{
     47    loadListOfAvailableLocales();
     48    setCurrentLocale(getConfiguredOrSystemLocale());
     49}
     50
     51L10n::~L10n()
     52{
     53    delete dictionary;
     54}
     55
     56Locale L10n::getCurrentLocale()
     57{
     58    return currentLocale;
     59}
     60
     61void L10n::setCurrentLocale(const std::string& localeCode)
     62{
     63    setCurrentLocale(Locale(Locale::createCanonical(localeCode.c_str())));
     64}
     65
     66void L10n::setCurrentLocale(Locale locale)
     67{
     68    bool reload = (currentLocale != locale);
     69    currentLocale = locale;
     70    currentLocaleIsOriginalGameLocale = (currentLocale == Locale::getUS());
     71    if (reload && !currentLocaleIsOriginalGameLocale)
     72        loadDictionaryForCurrentLocale();
     73}
     74
     75std::vector< std::string > L10n::getSupportedLocaleCodes()
     76{
     77    std::vector<std::string> supportedLocaleCodes;
     78    for (std::vector<Locale*>::iterator iterator = availableLocales.begin(); iterator != availableLocales.end(); ++iterator)
     79    {
     80        if (!InDevelopmentCopy() && strcmp((*iterator)->getBaseName(), "long") == 0)
     81            continue;
     82        supportedLocaleCodes.push_back((*iterator)->getBaseName());
     83    }
     84    return supportedLocaleCodes;
     85}
     86
     87std::vector< std::wstring > L10n::getSupportedLocaleDisplayNames()
     88{
     89    std::vector<std::wstring> supportedLocaleDisplayNames;
     90    for (std::vector<Locale*>::iterator iterator = availableLocales.begin(); iterator != availableLocales.end(); ++iterator)
     91    {
     92        if (strcmp((*iterator)->getBaseName(), "long") == 0)
     93        {
     94            if (InDevelopmentCopy())
     95                supportedLocaleDisplayNames.push_back(wstring_from_utf8(L10n::instance().translate("Long strings")));
     96            continue;
     97        }
     98
     99        UnicodeString utf16LocaleDisplayName;
     100        (**iterator).getDisplayName(**iterator, utf16LocaleDisplayName);
     101        std::string localeDisplayName;
     102        utf16LocaleDisplayName.toUTF8String(localeDisplayName);
     103        supportedLocaleDisplayNames.push_back(wstring_from_utf8(localeDisplayName));
     104    }
     105    return supportedLocaleDisplayNames;
     106}
     107
     108int L10n::getCurrentLocaleIndex()
     109{
     110    std::vector<std::string> supportedLocaleCodes;
     111
     112    // Try to match a whole code first.
     113    for (std::vector<Locale*>::iterator iterator = availableLocales.begin(); iterator != availableLocales.end(); ++iterator)
     114    {
     115        if (strcmp((**iterator).getBaseName(), getCurrentLocale().getBaseName()) == 0)
     116        {
     117            return iterator - availableLocales.begin();
     118        }
     119    }
     120
     121    // Match language code only if no whole code matched.
     122    for (std::vector<Locale*>::iterator iterator = availableLocales.begin(); iterator != availableLocales.end(); ++iterator)
     123    {
     124        if (strcmp((**iterator).getLanguage(), getCurrentLocale().getLanguage()) == 0)
     125        {
     126            return iterator - availableLocales.begin();
     127        }
     128    }
     129
     130    // Use en_US, the default locale.
     131    for (std::vector<Locale*>::iterator iterator = availableLocales.begin(); iterator != availableLocales.end(); ++iterator)
     132    {
     133        if (strcmp((**iterator).getLanguage(), Locale::getUS().getLanguage()) == 0)
     134        {
     135            return iterator - availableLocales.begin();
     136        }
     137    }
     138
     139    return 0; // It should never get this far.
     140}
     141
     142std::string L10n::translate(const std::string& sourceString)
     143{
     144    if (!currentLocaleIsOriginalGameLocale)
     145    {
     146        return dictionary->translate(sourceString);
     147    }
     148    else
     149    {
     150        return sourceString;
     151    }
     152}
     153
     154std::string L10n::translateWithContext(const std::string& context, const std::string& sourceString)
     155{
     156    if (!currentLocaleIsOriginalGameLocale)
     157    {
     158        return dictionary->translate_ctxt(context, sourceString);
     159    }
     160    else
     161    {
     162        return sourceString;
     163    }
     164}
     165
     166std::string L10n::translatePlural(const std::string& singularSourceString, const std::string& pluralSourceString, int number)
     167{
     168    if (!currentLocaleIsOriginalGameLocale)
     169    {
     170        return dictionary->translate_plural(singularSourceString, pluralSourceString, number);
     171    }
     172    else
     173    {
     174        if (number == 1)
     175        {
     176            return singularSourceString;
     177        }
     178        else
     179        {
     180            return pluralSourceString;
     181        }
     182    }
     183}
     184
     185std::string L10n::translatePluralWithContext(const std::string& context, const std::string& singularSourceString, const std::string& pluralSourceString, int number)
     186{
     187    if (!currentLocaleIsOriginalGameLocale)
     188    {
     189        return dictionary->translate_ctxt_plural(context, singularSourceString, pluralSourceString, number);
     190    }
     191    else
     192    {
     193        if (number == 1)
     194        {
     195            return singularSourceString;
     196        }
     197        else
     198        {
     199            return pluralSourceString;
     200        }
     201    }
     202}
     203
     204std::string L10n::translateLines(const std::string& sourceString)
     205{
     206    std::string targetString;
     207    std::stringstream stringOfLines(sourceString);
     208    std::string line;
     209
     210    while (std::getline(stringOfLines, line)) {
     211        targetString.append(translate(line));
     212        targetString.append("\n");
     213    }
     214
     215    return targetString;
     216}
     217
     218UDate L10n::parseDateTime(const std::string& dateTimeString, const std::string& dateTimeFormat, const Locale& locale)
     219{
     220    UErrorCode success = U_ZERO_ERROR;
     221    UnicodeString utf16DateTimeString = UnicodeString::fromUTF8(dateTimeString);
     222    UnicodeString utf16DateTimeFormat = UnicodeString::fromUTF8(dateTimeFormat);
     223
     224    DateFormat* dateFormatter = new SimpleDateFormat(utf16DateTimeFormat, locale, success);
     225    UDate date = dateFormatter->parse(utf16DateTimeString, success);
     226    delete dateFormatter;
     227
     228    return date;
     229}
     230
     231std::string L10n::localizeDateTime(const UDate& dateTime, DateTimeType type, DateFormat::EStyle style)
     232{
     233    UnicodeString utf16Date;
     234    std::string utf8Date;
     235
     236    DateFormat* dateFormatter = createDateTimeInstance(type, style, currentLocale);
     237    dateFormatter->format(dateTime, utf16Date);
     238    utf16Date.toUTF8String(utf8Date);
     239    delete dateFormatter;
     240
     241    return utf8Date;
     242}
     243
     244std::string L10n::formatMillisecondsIntoDateString(int milliseconds, const std::string& formatString)
     245{
     246    UErrorCode success = U_ZERO_ERROR;
     247    std::string utf8Date;
     248    UnicodeString utf16Date;
     249    UnicodeString utf16SourceDateTimeFormat = UnicodeString::fromUTF8("A");
     250    UnicodeString utf16LocalizedDateTimeFormat = UnicodeString::fromUTF8(formatString);
     251    char buffer[32];
     252    std::string utf8MillisecondsString(std::string(buffer, sprintf(buffer, "%d", milliseconds)));
     253    UnicodeString utf16MillisecondsString = UnicodeString::fromUTF8(utf8MillisecondsString);
     254
     255    SimpleDateFormat* dateFormatter = new SimpleDateFormat(utf16SourceDateTimeFormat, currentLocale, success);
     256    UDate dateTime = dateFormatter->parse(utf16MillisecondsString, success);
     257    dateFormatter->applyLocalizedPattern(utf16LocalizedDateTimeFormat, success);
     258    dateFormatter->format(dateTime, utf16Date);
     259    utf16Date.toUTF8String(utf8Date);
     260    delete dateFormatter;
     261
     262    return utf8Date;
     263}
     264
     265std::string L10n::formatDecimalNumberIntoString(double number)
     266{
     267    UErrorCode success = U_ZERO_ERROR;
     268    UnicodeString utf16Number;
     269    std::string utf8Number;
     270    NumberFormat* numberFormatter = NumberFormat::createInstance(currentLocale, UNUM_DECIMAL, success);
     271    numberFormatter->format(number, utf16Number);
     272    utf16Number.toUTF8String(utf8Number);
     273    return utf8Number;
     274}
     275
     276VfsPath L10n::localizePath(VfsPath sourcePath)
     277{
     278    VfsPath path = sourcePath;
     279
     280    VfsPath localizedPath = sourcePath.Parent() / L"l10n" / wstring_from_utf8(currentLocale.getLanguage()) / sourcePath.Filename();
     281    if (VfsFileExists(localizedPath))
     282    {
     283        path = localizedPath;
     284    }
     285
     286    return path;
     287}
     288
     289Locale L10n::getConfiguredOrSystemLocale()
     290{
     291    CConfigValue *value = g_ConfigDB.GetValue(CFG_COMMAND, "locale");
     292    if (value)
     293        return Locale(Locale::createCanonical(value->m_String.c_str()));
     294    else
     295        return Locale::getDefault();
     296}
     297
     298void L10n::loadDictionaryForCurrentLocale()
     299{
     300    delete dictionary;
     301    dictionary = new tinygettext::Dictionary();
     302
     303    VfsPaths filenames;
     304    if (vfs::GetPathnames(g_VFS, L"l10n/", (wstring_from_utf8(currentLocale.getLanguage()) + L".*.po").c_str(), filenames) < 0)
     305        return;
     306
     307    for (VfsPaths::iterator it = filenames.begin(); it != filenames.end(); ++it)
     308    {
     309        VfsPath filename = *it;
     310        CVFSFile file;
     311        file.Load(g_VFS, filename);
     312        std::string content = file.DecodeUTF8();
     313        readPoIntoDictionary(content, dictionary);
     314    }
     315}
     316
     317void L10n::loadListOfAvailableLocales()
     318{
     319    for (std::vector<Locale*>::iterator iterator = availableLocales.begin(); iterator != availableLocales.end(); ++iterator)
     320    {
     321        delete *iterator;
     322    }
     323    availableLocales.clear();
     324
     325    Locale* defaultLocale = new Locale(Locale::getUS());
     326    availableLocales.push_back(defaultLocale); // Always available.
     327
     328    VfsPaths filenames;
     329    if (vfs::GetPathnames(g_VFS, L"l10n/", L"*.po", filenames) < 0)
     330        return;
     331
     332    for (VfsPaths::iterator it = filenames.begin(); it != filenames.end(); ++it)
     333    {
     334        // Note: PO files follow this naming convention: “l10n/<locale code>.<mod name>.po”. For example: “l10n/gl.public.po”.
     335        VfsPath filepath = *it;
     336        std::string filename = utf8_from_wstring(filepath.string()).substr(strlen("l10n/"));
     337        std::size_t lengthToFirstDot = filename.find('.');
     338        std::string localeCode = filename.substr(0, lengthToFirstDot);
     339        Locale* locale = new Locale(Locale::createCanonical(localeCode.c_str()));
     340
     341        bool localeIsAlreadyAvailable = false;
     342        for (std::vector<Locale*>::iterator iterator = availableLocales.begin(); iterator != availableLocales.end(); ++iterator)
     343        {
     344            if (*locale == **iterator)
     345            {
     346                localeIsAlreadyAvailable = true;
     347                break;
     348            }
     349        }
     350
     351        if (!localeIsAlreadyAvailable)
     352        {
     353            availableLocales.push_back(locale);
     354        }
     355    }
     356}
     357
     358void L10n::readPoIntoDictionary(const std::string& poContent, tinygettext::Dictionary* dictionary)
     359{
     360    try
     361    {
     362        std::istringstream inputStream(poContent);
     363        tinygettext::POParser::parse("virtual PO file", inputStream, *dictionary, false);
     364    }
     365    catch(std::exception& e)
     366    {
     367        LOGERROR(L"[Localization] Exception while reading virtual PO file");
     368    }
     369}
     370
     371DateFormat* L10n::createDateTimeInstance(L10n::DateTimeType type, DateFormat::EStyle style, const Locale& locale)
     372{
     373    if (type == Date)
     374    {
     375        return SimpleDateFormat::createDateInstance(style, locale);
     376    }
     377    else if (type == Time)
     378    {
     379        return SimpleDateFormat::createTimeInstance(style, locale);
     380    }
     381    else // Provide DateTime by default.
     382    {
     383        return SimpleDateFormat::createDateTimeInstance(style, style, locale);
     384    }
     385}
  • new file source/i18n/L10n.h

    diff --git a/source/i18n/L10n.h b/source/i18n/L10n.h
    new file mode 100644
    index 0000000..54f660c
    - +  
     1/* Copyright (c) 2013 Wildfire Games
     2 *
     3 * Permission is hereby granted, free of charge, to any person obtaining
     4 * a copy of this software and associated documentation files (the
     5 * "Software"), to deal in the Software without restriction, including
     6 * without limitation the rights to use, copy, modify, merge, publish,
     7 * distribute, sublicense, and/or sell copies of the Software, and to
     8 * permit persons to whom the Software is furnished to do so, subject to
     9 * the following conditions:
     10 *
     11 * The above copyright notice and this permission notice shall be included
     12 * in all copies or substantial portions of the Software.
     13 *
     14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
     15 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
     16 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
     17 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
     18 * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
     19 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
     20 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
     21 */
     22
     23#ifndef L10N_H
     24#define L10N_H
     25
     26#include <string>
     27#include <vector>
     28
     29#include "lib/code_annotation.h"
     30#include "lib/external_libraries/icu.h"
     31#include "lib/external_libraries/tinygettext.h"
     32
     33#include "lib/file/vfs/vfs_path.h"
     34
     35class L10n
     36{
     37    NONCOPYABLE(L10n);
     38public:
     39
     40    L10n();
     41    ~L10n();
     42
     43    enum DateTimeType { DateTime, Date, Time };
     44
     45    static L10n& instance();
     46
     47    Locale getCurrentLocale();
     48    void setCurrentLocale(const std::string& localeCode);
     49    void setCurrentLocale(Locale locale);
     50    std::vector<std::string> getSupportedLocaleCodes();
     51    std::vector<std::wstring> getSupportedLocaleDisplayNames();
     52    int getCurrentLocaleIndex();
     53
     54    std::string translate(const std::string& sourceString);
     55    std::string translateWithContext(const std::string& context, const std::string& sourceString);
     56    std::string translatePlural(const std::string& singularSourceString, const std::string& pluralSourceString, int number);
     57    std::string translatePluralWithContext(const std::string& context, const std::string& singularSourceString, const std::string& pluralSourceString, int number);
     58    std::string translateLines(const std::string& sourceString);
     59
     60    UDate parseDateTime(const std::string& dateTimeString, const std::string& dateTimeFormat, const Locale& locale);
     61    std::string localizeDateTime(const UDate& dateTime, DateTimeType type, DateFormat::EStyle style);
     62    std::string formatMillisecondsIntoDateString(int milliseconds, const std::string& formatString);
     63    std::string formatDecimalNumberIntoString(double number);
     64
     65    VfsPath localizePath(VfsPath sourcePath);
     66
     67private:
     68
     69    tinygettext::Dictionary* dictionary;
     70    bool isRtlLanguage;
     71    Locale currentLocale;
     72    std::vector<Locale*> availableLocales;
     73    bool currentLocaleIsOriginalGameLocale;
     74
     75    Locale getConfiguredOrSystemLocale();
     76    void loadDictionaryForCurrentLocale();
     77    void loadListOfAvailableLocales();
     78
     79    void readPoIntoDictionary(const std::string& poContent, tinygettext::Dictionary* dictionary);
     80
     81    DateFormat* createDateTimeInstance(DateTimeType type, DateFormat::EStyle style, const Locale& locale);
     82};
     83
     84#endif // L10N_H
  • new file source/lib/external_libraries/icu.h

    diff --git a/source/lib/external_libraries/icu.h b/source/lib/external_libraries/icu.h
    new file mode 100644
    index 0000000..07b8ba2
    - +  
     1/* Copyright (c) 2013 Wildfire Games
     2 *
     3 * Permission is hereby granted, free of charge, to any person obtaining
     4 * a copy of this software and associated documentation files (the
     5 * "Software"), to deal in the Software without restriction, including
     6 * without limitation the rights to use, copy, modify, merge, publish,
     7 * distribute, sublicense, and/or sell copies of the Software, and to
     8 * permit persons to whom the Software is furnished to do so, subject to
     9 * the following conditions:
     10 *
     11 * The above copyright notice and this permission notice shall be included
     12 * in all copies or substantial portions of the Software.
     13 *
     14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
     15 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
     16 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
     17 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
     18 * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
     19 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
     20 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
     21 */
     22
     23#ifndef INCLUDED_ICU
     24#define INCLUDED_ICU
     25
     26#include <unicode/smpdtfmt.h>
     27
     28#endif  // #ifndef INCLUDED_ICU
  • new file source/lib/external_libraries/tinygettext.h

    diff --git a/source/lib/external_libraries/tinygettext.h b/source/lib/external_libraries/tinygettext.h
    new file mode 100644
    index 0000000..4232924
    - +  
     1/* Copyright (c) 2013 Wildfire Games
     2 *
     3 * Permission is hereby granted, free of charge, to any person obtaining
     4 * a copy of this software and associated documentation files (the
     5 * "Software"), to deal in the Software without restriction, including
     6 * without limitation the rights to use, copy, modify, merge, publish,
     7 * distribute, sublicense, and/or sell copies of the Software, and to
     8 * permit persons to whom the Software is furnished to do so, subject to
     9 * the following conditions:
     10 *
     11 * The above copyright notice and this permission notice shall be included
     12 * in all copies or substantial portions of the Software.
     13 *
     14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
     15 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
     16 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
     17 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
     18 * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
     19 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
     20 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
     21 */
     22
     23/*
     24 * Bring in the TinyGettext header file.
     25 */
     26
     27#ifndef INCLUDED_TINYGETTEXT
     28#define INCLUDED_TINYGETTEXT
     29
     30#include <tinygettext/tinygettext.hpp>
     31#include <tinygettext/po_parser.hpp>
     32
     33#endif  // INCLUDED_TINYGETTEXT
  • source/ps/CLogger.cpp

    diff --git a/source/ps/CLogger.cpp b/source/ps/CLogger.cpp
    index 1a68943..f2bc86a 100644
    a b  
    2222#include "graphics/FontMetrics.h"
    2323#include "graphics/ShaderManager.h"
    2424#include "graphics/TextRenderer.h"
     25#include "i18n/L10n.h"
    2526#include "lib/ogl.h"
    2627#include "lib/timer.h"
    2728#include "lib/utf8.h"
    void CLogger::Render()  
    300301
    301302    for (std::deque<RenderedMessage>::iterator it = m_RenderMessages.begin(); it != m_RenderMessages.end(); ++it)
    302303    {
    303         const wchar_t* type;
     304        CMatrix3D savedTransform = textRenderer.GetTransform();
     305
    304306        if (it->method == Normal)
    305307        {
    306             type = L"info";
    307308            textRenderer.Color(0.0f, 0.8f, 0.0f);
     309            textRenderer.PrintfAdvance(wstring_from_utf8(L10n::instance().translate("[%8.3f] info: ")).c_str(), it->time);
    308310        }
    309311        else if (it->method == Warning)
    310312        {
    311             type = L"warning";
    312313            textRenderer.Color(1.0f, 1.0f, 0.0f);
     314            textRenderer.PrintfAdvance(wstring_from_utf8(L10n::instance().translate("[%8.3f] warning: ")).c_str(), it->time);
    313315        }
    314316        else
    315317        {
    316             type = L"error";
    317318            textRenderer.Color(1.0f, 0.0f, 0.0f);
     319            textRenderer.PrintfAdvance(wstring_from_utf8(L10n::instance().translate("[%8.3f] error: ")).c_str(), it->time);
    318320        }
    319321
    320         CMatrix3D savedTransform = textRenderer.GetTransform();
    321 
    322         textRenderer.PrintfAdvance(L"[%8.3f] %ls: ", it->time, type);
    323322        // Display the actual message in white so it's more readable
    324323        textRenderer.Color(1.0f, 1.0f, 1.0f);
    325324        textRenderer.Put(0.0f, 0.0f, it->message.c_str());
  • source/ps/GameSetup/GameSetup.cpp

    diff --git a/source/ps/GameSetup/GameSetup.cpp b/source/ps/GameSetup/GameSetup.cpp
    index ba0fc8d..7999680 100644
    a b bool g_DoRenderCursor = true;  
    117117
    118118static const int SANE_TEX_QUALITY_DEFAULT = 5;  // keep in sync with code
    119119
     120bool g_InDevelopmentCopy;
     121bool g_CheckedIfInDevelopmentCopy = false;
     122
    120123static void SetTextureQuality(int quality)
    121124{
    122125    int q_flags;
    ErrorReactionInternal psDisplayError(const wchar_t* UNUSED(text), size_t UNUSED(  
    411414    return ERI_NOT_IMPLEMENTED;
    412415}
    413416
    414 static std::vector<CStr> GetMods(const CmdLineArgs& args, bool dev)
     417static std::vector<CStr> GetMods(const CmdLineArgs& args)
    415418{
    416419    std::vector<CStr> mods = args.GetMultiple("mod");
    417420    // TODO: It would be nice to remove this hard-coding
    static std::vector<CStr> GetMods(const CmdLineArgs& args, bool dev)  
    419422
    420423    // Add the user mod if not explicitly disabled or we have a dev copy so
    421424    // that saved files end up in version control and not in the user mod.
    422     if (!dev && !args.Has("noUserMod"))
     425    if (!InDevelopmentCopy() && !args.Has("noUserMod"))
    423426        mods.push_back("user");
    424427
    425428    return mods;
    static void InitVfs(const CmdLineArgs& args, int flags)  
    453456    // (maps, etc) end up in version control.
    454457    const OsPath readonlyConfig = paths.RData()/"config"/"";
    455458    g_VFS->Mount(L"config/", readonlyConfig);
    456     bool dev = (g_VFS->GetFileInfo(L"config/dev.cfg", NULL) == INFO::OK);
    457459
    458     const std::vector<CStr> mods = GetMods(args, dev);
     460    // Engine localization files.
     461    g_VFS->Mount(L"l10n/", paths.RData()/"l10n"/"");
     462
     463    const std::vector<CStr> mods = GetMods(args);
    459464
    460465    OsPath modPath = paths.RData()/"mods";
    461466    OsPath modUserPath = paths.UserData()/"mods";
    static void InitVfs(const CmdLineArgs& args, int flags)  
    466471        size_t baseFlags = userFlags|VFS_MOUNT_MUST_EXIST;
    467472       
    468473        OsPath modName(mods[i]);
    469         if (dev)
     474        if (InDevelopmentCopy())
    470475        {
    471476            // We are running a dev copy, so only mount mods in the user mod path
    472477            // if the mod does not exist in the data path.
    void CancelLoad(const CStrW& message)  
    13431348            JS_CallFunctionValue(cx, g_GUI->GetScriptObject(), fval, 1, &msgval, &rval);
    13441349    }
    13451350}
     1351
     1352bool InDevelopmentCopy()
     1353{
     1354    if (!g_CheckedIfInDevelopmentCopy)
     1355        g_InDevelopmentCopy = (g_VFS->GetFileInfo(L"config/dev.cfg", NULL) == INFO::OK);
     1356    return g_InDevelopmentCopy;
     1357}
     1358 No newline at end of file
  • source/ps/GameSetup/GameSetup.h

    diff --git a/source/ps/GameSetup/GameSetup.h b/source/ps/GameSetup/GameSetup.h
    index 87ae022..d9b588a 100644
    a b extern void InitGraphics(const CmdLineArgs& args, int flags);  
    6767extern void Shutdown(int flags);
    6868extern void CancelLoad(const CStrW& message);
    6969
     70extern bool InDevelopmentCopy();
     71
    7072#endif // INCLUDED_GAMESETUP
  • source/ps/SavedGame.cpp

    diff --git a/source/ps/SavedGame.cpp b/source/ps/SavedGame.cpp
    index 274d22f..ab954fb 100644
    a b  
    2222#include "gui/GUIManager.h"
    2323#include "lib/allocators/shared_ptr.h"
    2424#include "lib/file/archive/archive_zip.h"
     25#include "i18n/L10n.h"
     26#include "lib/utf8.h"
    2527#include "ps/CLogger.h"
    2628#include "ps/Filesystem.h"
    2729#include "scriptinterface/ScriptInterface.h"
    Status SavedGames::Save(const std::wstring& name, const std::wstring& descriptio  
    106108
    107109    OsPath realPath;
    108110    WARN_RETURN_STATUS_IF_ERR(g_VFS->GetRealPath(filename, realPath));
    109     LOGMESSAGERENDER(L"Saved game to %ls\n", realPath.string().c_str());
     111    LOGMESSAGERENDER(wstring_from_utf8(L10n::instance().translate("Saved game to %ls") + "\n").c_str(), realPath.string().c_str());
    110112
    111113    return INFO::OK;
    112114}
    std::vector<CScriptValRooted> SavedGames::GetSavedGames(ScriptInterface& scriptI  
    198200        if (!archiveReader)
    199201        {
    200202            // Triggered by e.g. the file being open in another program
    201             LOGWARNING(L"Failed to read saved game '%ls'", realPath.string().c_str());
     203            LOGWARNING(wstring_from_utf8(L10n::instance().translate("Failed to read saved game '%ls'") + "\n").c_str(), realPath.string().c_str());
    202204            continue; // skip this file
    203205        }
    204206
  • source/scripting/ScriptGlue.cpp

    diff --git a/source/scripting/ScriptGlue.cpp b/source/scripting/ScriptGlue.cpp
    index b2c7353..ecb1686 100644
    a b  
    3434#include "gui/GUIManager.h"
    3535#include "gui/IGUIObject.h"
    3636#include "lib/frequency_filter.h"
    37 #include "lib/svn_revision.h"
    3837#include "lib/timer.h"
    3938#include "lib/sysdep/sysdep.h"  // sys_OpenFile
    4039#include "maths/scripting/JSInterface_Vector3D.h"
    JSBool GetGUIObjectByName(JSContext* cx, uintN argc, jsval* vp)  
    229228    }
    230229}
    231230
    232 //-----------------------------------------------------------------------------
    233 // Miscellany
    234 //-----------------------------------------------------------------------------
    235 
    236 // Return the date/time at which the current executable was compiled.
    237 // params: none (-> "date time (svn revision)") OR an integer specifying
    238 //   what to display: 0 for date, 1 for time, 2 for svn revision
    239 // returns: string with the requested timestamp info
    240 // notes:
    241 // - Displayed on main menu screen; tells non-programmers which auto-build
    242 //   they are running. Could also be determined via .EXE file properties,
    243 //   but that's a bit more trouble.
    244 // - To be exact, the date/time returned is when scriptglue.cpp was
    245 //   last compiled, but the auto-build does full rebuilds.
    246 // - svn revision is generated by calling svnversion and cached in
    247 //   lib/svn_revision.cpp. it is useful to know when attempting to
    248 //   reproduce bugs (the main EXE and PDB should be temporarily reverted to
    249 //   that revision so that they match user-submitted crashdumps).
    250 JSBool GetBuildTimestamp(JSContext* cx, uintN argc, jsval* vp)
    251 {
    252     JSU_REQUIRE_MAX_PARAMS(1);
    253 
    254     char buf[200];
    255 
    256     // see function documentation
    257     const int mode = argc? JSVAL_TO_INT(JS_ARGV(cx, vp)[0]) : -1;
    258     switch(mode)
    259     {
    260     case -1:
    261         sprintf_s(buf, ARRAY_SIZE(buf), "%s %s (%ls)", __DATE__, __TIME__, svn_revision);
    262         break;
    263     case 0:
    264         sprintf_s(buf, ARRAY_SIZE(buf), "%s", __DATE__);
    265         break;
    266     case 1:
    267         sprintf_s(buf, ARRAY_SIZE(buf), "%s", __TIME__);
    268         break;
    269     case 2:
    270         sprintf_s(buf, ARRAY_SIZE(buf), "%ls", svn_revision);
    271         break;
    272     }
    273 
    274     JS_SET_RVAL(cx, vp, STRING_TO_JSVAL(JS_NewStringCopyZ(cx, buf)));
    275     return JS_TRUE;
    276 }
    277 
    278231#if MOZJS_DEBUG_ABI
    279232void DumpHeap(const char* basename, int idx, JSContext* cx)
    280233{
    JSFunctionSpec ScriptFunctionTable[] =  
    395348    JS_FUNC("getGUIObjectByName", GetGUIObjectByName, 1)
    396349
    397350    // Miscellany
    398     JS_FUNC("buildTime", GetBuildTimestamp, 0)
    399351    JS_FUNC("dumpHeaps", DumpHeaps, 0)
    400352
    401353    // end of table marker