changeset 769:43b49f1de828 pyntnclick-i18n

Merge i18n for before the pyntnclick split
author Stefano Rivera <stefano@rivera.za.net>
date Sat, 26 Jan 2013 16:57:33 +0200
parents afe7b1cb16c0 (current diff) 202f6a2fe091 (diff)
children a35f5364437d 6d77d60ba20b
files data/fonts/DejaVu-Copyright.txt data/fonts/Vera-Copyright.txt data/fonts/Vera.ttf data/fonts/VeraBd.ttf data/ru/images/bridge/bridge_nav_life_support.png data/ru/images/bridge/comp_alert_ai_looping.png data/ru/images/bridge/comp_alert_ai_offline.png data/ru/images/bridge/comp_alert_base.png data/ru/images/bridge/comp_alert_engine_offline.png data/ru/images/bridge/comp_alert_life_support.png data/ru/images/bridge/comp_alert_life_support_partial.png data/ru/images/bridge/comp_log_1.png data/ru/images/bridge/comp_log_end.png data/ru/images/bridge/comp_log_start.png data/ru/images/cryo/comp_info_detail.png data/ru/images/cryo/comp_info_detail_fixed.png data/ru/images/engine/ec_cryo_leaking.png data/ru/images/engine/ec_cryo_reservoir_empty.png data/ru/images/engine/engine_comp_detail.png data/ru/images/engine/engine_room.png data/ru/images/machine/machine_room.png gamelib/constants.py gamelib/scenes/bridge.py gamelib/scenes/crew_quarters.py gamelib/scenes/cryo.py gamelib/scenes/engine.py gamelib/scenes/game_widgets.py gamelib/scenes/machine.py gamelib/scenes/map.py gamelib/scenes/mess.py install-po.sh pyntnclick/constants.py pyntnclick/gamescreen.py pyntnclick/i18n.py pyntnclick/main.py pyntnclick/resources.py
diffstat 41 files changed, 2305 insertions(+), 474 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/README-i18n.txt	Sat Jan 26 16:57:33 2013 +0200
@@ -0,0 +1,41 @@
+These are notes on internationalization and translation. They are
+suitable for Unix like systems. As prerequisites you need `gettext'
+being installed and (if you want to translate) some editor for
+gettext catalogs like `poedit' or `virtaal'. In case you are familiar
+with gettext ".po" format any text editor will do.
+
+
+== How do I translate suspended-sentence into my language? ==
+
+First of all look if there is already translation catalog for
+your locale in `po/' subdirectory. The file should be named like
+`<locale>.po' where <locale> is the language code for your locale.
+For example, catalog for German is called `de.po'. If it is there
+you can start translating.
+
+If there is no file for your locale you need to generate it. To do
+this navigate to the `po/' directory in terminal and type command
+
+  msginit -l <locale>
+
+where <locale> is two-letters-language-code you need. Then translate
+generated file using your preferred editor.
+
+To get new translation to work you need to compile and install it by
+executing `install-po.sh' script.
+
+
+== How can I mark the string in code as translatable? ==
+
+Just surround it with _( and ) like 
+  "Hello, world"    ->    _("Hello, world!")
+
+_() is a function in `gamelib/i18n.py' file, so you might want to
+import it first.
+
+  from gamelib.i18n import _
+
+And don't forget to update message catalogs with new strings. To do
+that just execute `update-po.sh' script. It collects all translatable
+strings from files that are specified in `po/POTFILES'. Make sure the
+file you worked on is in there.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/data/fonts/DejaVu-Copyright.txt	Sat Jan 26 16:57:33 2013 +0200
@@ -0,0 +1,50 @@
+Copyright:
+
+Fonts are (c) Bitstream (see below). DejaVu changes are in public domain.
+
+Bitstream Vera Fonts Copyright
+------------------------------
+
+Copyright (c) 2003 by Bitstream, Inc. All Rights Reserved. Bitstream Vera is
+a trademark of Bitstream, Inc.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of the fonts accompanying this license ("Fonts") and associated
+documentation files (the "Font Software"), to reproduce and distribute the
+Font Software, including without limitation the rights to use, copy, merge,
+publish, distribute, and/or sell copies of the Font Software, and to permit
+persons to whom the Font Software is furnished to do so, subject to the
+following conditions:
+
+The above copyright and trademark notices and this permission notice shall
+be included in all copies of one or more of the Font Software typefaces.
+
+The Font Software may be modified, altered, or added to, and in particular
+the designs of glyphs or characters in the Fonts may be modified and
+additional glyphs or characters may be added to the Fonts, only if the fonts
+are renamed to names not containing either the words "Bitstream" or the word
+"Vera".
+
+This License becomes null and void to the extent applicable to Fonts or Font
+Software that has been modified and is distributed under the "Bitstream
+Vera" names.
+
+The Font Software may be sold as part of a larger software package but no
+copy of one or more of the Font Software typefaces may be sold by itself.
+
+THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF COPYRIGHT, PATENT,
+TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL BITSTREAM OR THE GNOME
+FOUNDATION BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, INCLUDING
+ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL DAMAGES,
+WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
+THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM OTHER DEALINGS IN THE
+FONT SOFTWARE.
+
+Except as contained in this notice, the names of Gnome, the Gnome
+Foundation, and Bitstream Inc., shall not be used in advertising or
+otherwise to promote the sale, use or other dealings in this Font Software
+without prior written authorization from the Gnome Foundation or Bitstream
+Inc., respectively. For further information, contact: fonts at gnome dot
+org. 
--- a/data/fonts/Vera-Copyright.txt	Sat Jan 26 13:24:01 2013 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,124 +0,0 @@
-Bitstream Vera Fonts Copyright
-
-The fonts have a generous copyright, allowing derivative works (as
-long as "Bitstream" or "Vera" are not in the names), and full
-redistribution (so long as they are not *sold* by themselves). They
-can be be bundled, redistributed and sold with any software.
-
-The fonts are distributed under the following copyright:
-
-Copyright
-=========
-
-Copyright (c) 2003 by Bitstream, Inc. All Rights Reserved. Bitstream
-Vera is a trademark of Bitstream, Inc.
-
-Permission is hereby granted, free of charge, to any person obtaining
-a copy of the fonts accompanying this license ("Fonts") and associated
-documentation files (the "Font Software"), to reproduce and distribute
-the Font Software, including without limitation the rights to use,
-copy, merge, publish, distribute, and/or sell copies of the Font
-Software, and to permit persons to whom the Font Software is furnished
-to do so, subject to the following conditions:
-
-The above copyright and trademark notices and this permission notice
-shall be included in all copies of one or more of the Font Software
-typefaces.
-
-The Font Software may be modified, altered, or added to, and in
-particular the designs of glyphs or characters in the Fonts may be
-modified and additional glyphs or characters may be added to the
-Fonts, only if the fonts are renamed to names not containing either
-the words "Bitstream" or the word "Vera".
-
-This License becomes null and void to the extent applicable to Fonts
-or Font Software that has been modified and is distributed under the
-"Bitstream Vera" names.
-
-The Font Software may be sold as part of a larger software package but
-no copy of one or more of the Font Software typefaces may be sold by
-itself.
-
-THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
-MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
-OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL
-BITSTREAM OR THE GNOME FOUNDATION BE LIABLE FOR ANY CLAIM, DAMAGES OR
-OTHER LIABILITY, INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL,
-OR CONSEQUENTIAL DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR
-OTHERWISE, ARISING FROM, OUT OF THE USE OR INABILITY TO USE THE FONT
-SOFTWARE OR FROM OTHER DEALINGS IN THE FONT SOFTWARE.
-
-Except as contained in this notice, the names of Gnome, the Gnome
-Foundation, and Bitstream Inc., shall not be used in advertising or
-otherwise to promote the sale, use or other dealings in this Font
-Software without prior written authorization from the Gnome Foundation
-or Bitstream Inc., respectively. For further information, contact:
-fonts at gnome dot org.
-
-Copyright FAQ
-=============
-
-   1. I don't understand the resale restriction... What gives?
-
-      Bitstream is giving away these fonts, but wishes to ensure its
-      competitors can't just drop the fonts as is into a font sale system
-      and sell them as is. It seems fair that if Bitstream can't make money
-      from the Bitstream Vera fonts, their competitors should not be able to
-      do so either. You can sell the fonts as part of any software package,
-      however.
-
-   2. I want to package these fonts separately for distribution and
-      sale as part of a larger software package or system.  Can I do so?
-
-      Yes. A RPM or Debian package is a "larger software package" to begin 
-      with, and you aren't selling them independently by themselves. 
-      See 1. above.
-
-   3. Are derivative works allowed?
-      Yes!
-
-   4. Can I change or add to the font(s)?
-      Yes, but you must change the name(s) of the font(s).
-
-   5. Under what terms are derivative works allowed?
-
-      You must change the name(s) of the fonts. This is to ensure the
-      quality of the fonts, both to protect Bitstream and Gnome. We want to
-      ensure that if an application has opened a font specifically of these
-      names, it gets what it expects (though of course, using fontconfig,
-      substitutions could still could have occurred during font
-      opening). You must include the Bitstream copyright. Additional
-      copyrights can be added, as per copyright law. Happy Font Hacking!
-
-   6. If I have improvements for Bitstream Vera, is it possible they might get 
-       adopted in future versions?
-
-      Yes. The contract between the Gnome Foundation and Bitstream has
-      provisions for working with Bitstream to ensure quality additions to
-      the Bitstream Vera font family. Please contact us if you have such
-      additions. Note, that in general, we will want such additions for the
-      entire family, not just a single font, and that you'll have to keep
-      both Gnome and Jim Lyles, Vera's designer, happy! To make sense to add
-      glyphs to the font, they must be stylistically in keeping with Vera's
-      design. Vera cannot become a "ransom note" font. Jim Lyles will be
-      providing a document describing the design elements used in Vera, as a
-      guide and aid for people interested in contributing to Vera.
-
-   7. I want to sell a software package that uses these fonts: Can I do so?
-
-      Sure. Bundle the fonts with your software and sell your software
-      with the fonts. That is the intent of the copyright.
-
-   8. If applications have built the names "Bitstream Vera" into them, 
-      can I override this somehow to use fonts of my choosing?
-
-      This depends on exact details of the software. Most open source
-      systems and software (e.g., Gnome, KDE, etc.) are now converting to
-      use fontconfig (see www.fontconfig.org) to handle font configuration,
-      selection and substitution; it has provisions for overriding font
-      names and subsituting alternatives. An example is provided by the
-      supplied local.conf file, which chooses the family Bitstream Vera for
-      "sans", "serif" and "monospace".  Other software (e.g., the XFree86
-      core server) has other mechanisms for font substitution.
-
Binary file data/fonts/Vera.ttf has changed
Binary file data/fonts/VeraBd.ttf has changed
Binary file data/ru/images/bridge/bridge_nav_life_support.png has changed
Binary file data/ru/images/bridge/comp_alert_ai_looping.png has changed
Binary file data/ru/images/bridge/comp_alert_ai_offline.png has changed
Binary file data/ru/images/bridge/comp_alert_base.png has changed
Binary file data/ru/images/bridge/comp_alert_engine_offline.png has changed
Binary file data/ru/images/bridge/comp_alert_life_support.png has changed
Binary file data/ru/images/bridge/comp_alert_life_support_partial.png has changed
Binary file data/ru/images/bridge/comp_log_1.png has changed
Binary file data/ru/images/bridge/comp_log_end.png has changed
Binary file data/ru/images/bridge/comp_log_start.png has changed
Binary file data/ru/images/cryo/comp_info_detail.png has changed
Binary file data/ru/images/cryo/comp_info_detail_fixed.png has changed
Binary file data/ru/images/engine/ec_cryo_leaking.png has changed
Binary file data/ru/images/engine/ec_cryo_reservoir_empty.png has changed
Binary file data/ru/images/engine/engine_comp_detail.png has changed
Binary file data/ru/images/engine/engine_room.png has changed
Binary file data/ru/images/machine/machine_room.png has changed
--- a/gamelib/constants.py	Sat Jan 26 13:24:01 2013 +0200
+++ b/gamelib/constants.py	Sat Jan 26 16:57:33 2013 +0200
@@ -4,3 +4,4 @@
 class SSConstants(GameConstants):
     title = 'Suspended Sentence'
     icon = 'suspended_sentence24x24.png'
+    i18n_name = 'suspended-sentence'
--- a/gamelib/scenes/bridge.py	Sat Jan 26 13:24:01 2013 +0200
+++ b/gamelib/scenes/bridge.py	Sat Jan 26 16:57:33 2013 +0200
@@ -6,6 +6,7 @@
 from pygame.color import Color
 from pygame.rect import Rect
 
+from pyntnclick.i18n import _
 from pyntnclick.cursor import CursorSprite
 from pyntnclick.state import Scene, Item, Thing, Result
 from pyntnclick.scenewidgets import (InteractNoImage, InteractRectUnion,
@@ -54,16 +55,16 @@
         self.add_thing(JimPanel())
         self.add_thing(StarField())
         self.add_thing(GenericDescThing('bridge.wires', 1,
-            "The brightly coloured wires contrast with the drab walls.",
+            _("The brightly coloured wires contrast with the drab walls."),
             ((46, 4, 711, 143),)))
         self.add_thing(GenericDescThing('bridge.note', 2,
-            "\"Dammit JIM, I'm a doctor, not an engineer!\"",
+            _("\"Dammit JIM, I'm a doctor, not an engineer!\""),
             (
                 (491, 494, 194, 105),
                 (422, 533, 71, 66),
                 )))
         self.doctor = GenericDescThing('bridge.skel', 3,
-                "A skeleton hangs improbably from the wires.",
+                _("A skeleton hangs improbably from the wires."),
                 (
                     (632, 148, 40, 29),
                     (683, 176, 30, 101),
@@ -108,13 +109,13 @@
         return Result(detail_view='bridge_comp_detail')
 
     def interact_with_titanium_leg(self, item):
-        return Result("You can't break the duraplastic screen.")
+        return Result(_("You can't break the duraplastic screen."))
 
     def interact_with_machete(self, item):
-        return Result("Scratching the screen won't help you.")
+        return Result(_("Scratching the screen won't help you."))
 
     def get_description(self):
-        return "The main bridge computer screen."
+        return _("The main bridge computer screen.")
 
 
 class MassageChairBase(Thing):
@@ -137,9 +138,9 @@
 
     def get_description(self):
         if self.get_data('contains_superconductor'):
-            return ("A top of the line Massage-o-Matic Captain's Executive"
-                    " Command Chair. It's massaging a skeleton.")
-        return "The chair won't work any more, it has no power."
+            return _("A top of the line Massage-o-Matic Captain's Executive"
+                     " Command Chair. It's massaging a skeleton.")
+        return _("The chair won't work any more, it has no power.")
 
 
 class MassageChair(Thing):
@@ -188,15 +189,15 @@
     INITIAL = 'stethoscope'
 
     def get_description(self):
-        return "A stethoscope hangs from the neck of the skeleton."
+        return _("A stethoscope hangs from the neck of the skeleton.")
 
     def interact_without(self):
         self.game.add_inventory_item('stethoscope')
         self.scene.remove_thing(self)
         # Fill in the doctor's rect
         self.scene.doctor.rect.append(self.rect)
-        return Result("You pick up the stethoscope and verify that the"
-                      " doctor's heart has stopped. Probably a while ago.")
+        return Result(_("You pick up the stethoscope and verify that the"
+                        " doctor's heart has stopped. Probably a while ago."))
 
 
 class TapedSuperconductor(Item):
@@ -216,9 +217,9 @@
         taped_superconductor = TapedSuperconductor('taped_superconductor')
         self.game.add_item(taped_superconductor)
         self.game.replace_inventory_item(self.name, taped_superconductor.name)
-        return Result("You rip off a piece of duct tape and stick it on the"
-                      " superconductor. It almost sticks to itself, but you"
-                      " successfully avoid disaster.")
+        return Result(_("You rip off a piece of duct tape and stick it on the"
+                        " superconductor. It almost sticks to itself, but you"
+                        " successfully avoid disaster."))
 
 
 class SuperconductorThing(Thing):
@@ -237,11 +238,11 @@
         self.game.scenes['bridge'].things['bridge.massagechair_base'] \
                           .set_data('contains_superconductor', False)
         self.scene.remove_thing(self)
-        return (Result("The superconductor module unclips easily."),
-                make_jim_dialog(("Prisoner %s. That chair you've destroyed"
-                                 " was property of the ship's captain. "
-                                 "You will surely be punished."
-                                 % PLAYER_ID), self.game))
+        return (Result(_("The superconductor module unclips easily.")),
+                make_jim_dialog(_("Prisoner %s. That chair you've destroyed"
+                                  " was property of the ship's captain. "
+                                  "You will surely be punished.")
+                                  % PLAYER_ID, self.game))
 
 
 class StarField(Thing):
@@ -271,9 +272,9 @@
 
     def leave(self):
         self.description = random.choice([
-            "The lights flash in interesting patterns.",
-            "The flashing lights don't mean anything to you.",
-            "The console lights flash and flicker.",
+            _("The lights flash in interesting patterns."),
+            _("The flashing lights don't mean anything to you."),
+            _("The console lights flash and flicker."),
             ])
 
     def get_description(self):
@@ -327,7 +328,7 @@
 
     def get_description(self):
         if self.scene.get_data('ai panel') == 'closed':
-            return "The sign reads 'Warning: Authorized Techinicians Only'."
+            return _("The sign reads 'Warning: Authorized Techinicians Only'.")
 
     def select_interact(self):
         status = self.get_data('ai panel')
@@ -338,13 +339,13 @@
         if ai_status == 'online':
             return self.interact_default(None)
         elif self.scene.get_data('ai panel') == 'closed':
-            return Result("You are unable to open the panel with your"
-                          " bare hands.")
+            return Result(_("You are unable to open the panel with your"
+                            " bare hands."))
         elif self.scene.get_data('ai panel') == 'open':
             self.scene.set_data('ai panel', 'broken')
             self.state.break_ai()
             self.set_interact()
-            return Result("You unplug various important-looking wires.")
+            return Result(_("You unplug various important-looking wires."))
 
     def interact_with_machete(self, item):
         ai_status = self.state.get_jim_state()
@@ -353,20 +354,20 @@
         elif self.scene.get_data('ai panel') == 'closed':
             self.scene.set_data('ai panel', 'open')
             self.set_interact()
-            return Result("Using the machete, you lever the panel off.")
+            return Result(_("Using the machete, you lever the panel off."))
         elif self.scene.get_data('ai panel') == 'open':
             self.scene.set_data('ai panel', 'broken')
             self.state.break_ai()
             self.set_interact()
-            return Result("You smash various delicate components with"
-                          " the machete.")
+            return Result(_("You smash various delicate components with"
+                            " the machete."))
 
     def interact_default(self, item):
         if self.state.get_jim_state() == 'online':
-            return (Result('You feel a shock from the panel.'),
-                    make_jim_dialog("Prisoner %s. Please step away from the"
-                                    " panel. You are not an authorized"
-                                    " technician." % PLAYER_ID, self.game))
+            return (Result(_('You feel a shock from the panel.')),
+                    make_jim_dialog(_("Prisoner %s. Please step away from the"
+                                      " panel. You are not an authorized"
+                                      " technician.") % PLAYER_ID, self.game))
 
 
 class ChairDetail(Scene):
@@ -467,16 +468,16 @@
 
     def interact_without(self):
         if self.game.scenes['bridge'].get_data('ai status') == 'online':
-            return make_jim_dialog("You are not authorized to change the"
-                                   " destination.", self.game)
+            return make_jim_dialog(_("You are not authorized to change the"
+                                     " destination."), self.game)
         if not self.ai_blocked:
-            return Result("There's no good reason to choose to go to the"
-                          " penal colony.")
+            return Result(_("There's no good reason to choose to go to the"
+                            " penal colony."))
         if self.game.scenes['bridge'].get_data('ai status') == 'looping':
-            return Result("You could change the destination, but when JIM"
-                          " recovers, it'll just get reset.")
+            return Result(_("You could change the destination, but when JIM"
+                            " recovers, it'll just get reset."))
         if self.game.scenes['bridge'].get_data('ai status') == 'dead':
-            return Result("You change the destination.",
+            return Result(_("You change the destination."),
                           soundfile="beep550.ogg", end_game=True)
 
 
--- a/gamelib/scenes/crew_quarters.py	Sat Jan 26 13:24:01 2013 +0200
+++ b/gamelib/scenes/crew_quarters.py	Sat Jan 26 16:57:33 2013 +0200
@@ -1,5 +1,6 @@
 """Crew quarters."""
 
+from pyntnclick.i18n import _
 from pyntnclick.cursor import CursorSprite
 from pyntnclick.state import Scene, Item, Thing, Result
 from pyntnclick.scenewidgets import (InteractNoImage, InteractImage,
@@ -26,10 +27,10 @@
         self.add_thing(PosterThing())
         self.add_thing(MonitorCamera())
         self.add_thing(GenericDescThing('crew.plant', 1,
-            "The plant is doing surprisingly well for centuries of neglect",
+            _("The plant is doing surprisingly well for centuries of neglect"),
             ((624, 215, 61, 108),)))
         self.add_thing(GenericDescThing('crew.cat', 2,
-            "A picture of a cat labelled 'Clementine'",
+            _("A picture of a cat labelled 'Clementine'"),
             ((722, 382, 66, 72),)))
 
 
@@ -75,33 +76,34 @@
                 self.set_data('has_tape', False)
                 self.game.add_inventory_item('duct_tape')
                 self.set_interact()
-                return Result("Duct tape. It'll stick to everything except "
-                              "ducts, apparently.")
-            return Result("The perfectly balanced door swings frictionlessly "
-                          "to and fro. What craftsmanship!")
-        return Result("The safe is locked. This might be an interesting "
-                      "challenge, if suitable equipment can be found.")
+                return Result(_("Duct tape. It'll stick to everything except "
+                                "ducts, apparently."))
+            return Result(_("The perfectly balanced door swings "
+                            "frictionlessly to and fro. What craftsmanship!"))
+        return Result(_("The safe is locked. This might be an interesting "
+                        "challenge, if suitable equipment can be found."))
 
     def interact_with_stethoscope(self, item):
         if self.get_data('is_cracked'):
-            return Result("It's already unlocked. There's no more challenge.")
+            return Result(_("It's already unlocked. "
+                            "There's no more challenge."))
         # TODO: Add years to the sentence for safecracking.
         # TODO: Wax lyrical some more about safecracking.
         self.set_data('is_cracked', True)
         self.set_interact()
-        return (Result("Even after centuries of neglect, the tumblers slide"
-                      " almost silently into place. Turns out the combination"
-                      " was '1 2 3 4 5'. An idiot must keep his luggage in"
-                      " here."),
-                      make_jim_dialog("Prisoner %s, you have been observed"
-                          " committing a felony violation. This will go onto"
-                          " your permanent record, and your sentence may be"
-                          " extended by up to twenty years."
-                          % PLAYER_ID, self.game))
+        return (Result(_("Even after centuries of neglect, the tumblers slide"
+                         " almost silently into place. Turns out the"
+                         " combination was '1 2 3 4 5'. An idiot must keep his"
+                         " luggage in here.")),
+                make_jim_dialog(_("Prisoner %s, you have been observed"
+                                  " committing a felony violation. This will"
+                                  " go onto your permanent record, and your"
+                                  " sentence may be extended by up to twenty"
+                                  " years.") % PLAYER_ID, self.game))
 
     def get_description(self):
-        return "Ah, a vintage Knoxx & Co. model QR3. Quaint, but" \
-                " reasonably secure."
+        return _("Ah, a vintage Knoxx & Co. model QR3. Quaint, but"
+                 " reasonably secure.")
 
 
 class FishbowlThing(Thing):
@@ -127,20 +129,20 @@
 
     def interact_without(self):
         if not self.get_data('has_bowl'):
-            return Result("What's the point of lugging around a very dead"
-                    " fish and a kilogram or so of sand?")
+            return Result(_("What's the point of lugging around a very dead"
+                            " fish and a kilogram or so of sand?"))
         self.set_data('has_bowl', False)
         self.set_interact()
         self.game.add_inventory_item('fishbowl')
-        return Result("The fishbowl is useful, but its contents aren't.")
+        return Result(_("The fishbowl is useful, but its contents aren't."))
 
     def get_description(self):
         if self.get_data('has_bowl'):
-            return "This fishbowl looks exactly like an old science fiction" \
-                    " space helmet."
+            return _("This fishbowl looks exactly like an old science fiction"
+                     " space helmet.")
         else:
-            return "An evicted dead fish and some sand lie forlornly on the" \
-                    " table"
+            return _("An evicted dead fish and some sand lie forlornly on the"
+                     " table")
 
 
 class Fishbowl(Item):
@@ -154,8 +156,9 @@
         helmet = FishbowlHelmet('helmet')
         self.game.add_item(helmet)
         self.game.replace_inventory_item(self.name, helmet.name)
-        return Result("You duct tape the edges of the helmet. The seal is"
-                " crude, but it will serve as a workable helmet if needed.")
+        return Result(_("You duct tape the edges of the helmet. The seal is"
+                        " crude, but it will serve as a workable helmet if"
+                        " needed."))
 
 
 class FishbowlHelmet(Item):
@@ -201,10 +204,10 @@
     def interact_without(self):
         self.game.add_inventory_item('escher_poster')
         self.scene.remove_thing(self)
-        return Result("This poster will go nicely on your bedroom wall.")
+        return Result(_("This poster will go nicely on your bedroom wall."))
 
     def get_description(self):
-        return "A paradoxical poster hangs below the security camera."
+        return _("A paradoxical poster hangs below the security camera.")
 
 
 class EscherPoster(Item):
--- a/gamelib/scenes/cryo.py	Sat Jan 26 13:24:01 2013 +0200
+++ b/gamelib/scenes/cryo.py	Sat Jan 26 16:57:33 2013 +0200
@@ -2,6 +2,7 @@
 
 import random
 
+from pyntnclick.i18n import _
 from pyntnclick.cursor import CursorSprite
 from pyntnclick.state import Scene, Item, CloneableItem, Thing, Result
 from pyntnclick.scenewidgets import (InteractNoImage, InteractRectUnion,
@@ -45,7 +46,7 @@
         # Flavour items
         # pipes
         self.add_thing(GenericDescThing('cryo.pipes', 1,
-            "These pipes carry cooling fluid to the cryo units.",
+            _("These pipes carry cooling fluid to the cryo units."),
             (
                 (552, 145, 129, 66),
                 (636, 82, 165, 60),
@@ -56,8 +57,8 @@
 
         # cryo units
         self.add_thing(GenericCryoUnit(2,
-            "An empty cryo chamber.",
-            "Prisoner 81E4-C8900480E635. Embezzlement. 20 years.",
+            _("An empty cryo chamber."),
+            _("Prisoner 81E4-C8900480E635. Embezzlement. 20 years."),
             (
                 (155, 430, 50, 35),
                 (125, 450, 60, 35),
@@ -66,9 +67,9 @@
                 )))
 
         self.add_thing(GenericCryoUnit(3,
-            "A working cryo chamber. The frosted glass obscures the details"
-            " of the occupant.",
-            "Prisoner 9334-CE1EB0243BAB. Murder. 40 years.",
+            _("A working cryo chamber. The frosted glass obscures the details"
+              " of the occupant."),
+            _("Prisoner 9334-CE1EB0243BAB. Murder. 40 years."),
             (
                 (215, 430, 50, 35),
                 (205, 450, 50, 35),
@@ -77,10 +78,10 @@
                 )))
 
         self.add_thing(GenericCryoUnit(4,
-            "A broken cryo chamber. The skeleton inside has been picked"
-            " clean.",
-            "Prisoner BFBC-8BF4C6B7492B. Importing illegal alien biomatter."
-            " 15 years.",
+            _("A broken cryo chamber. The skeleton inside has been picked"
+              " clean."),
+            _("Prisoner BFBC-8BF4C6B7492B. Importing illegal alien biomatter."
+              " 15 years."),
             (
                 (275, 430, 50, 70),
                 (255, 460, 50, 70),
@@ -88,25 +89,26 @@
                 )))
 
         self.add_thing(GenericCryoUnit(5,
-            "A working cryo chamber. The frosted glass obscures the details of"
-            " the occupant.",
-            "Prisoner B520-99495B8C41CE. Copyright infringement. 60 years.",
+            _("A working cryo chamber. The frosted glass obscures the details "
+              "of the occupant."),
+            _("Prisoner B520-99495B8C41CE. Copyright infringement. 60 years."),
             (
                 (340, 430, 50, 70),
                 (330, 500, 60, 50),
                 )))
 
         self.add_thing(GenericCryoUnit(6,
-            "An empty cryo unit. Recently filled by you.",
-            "Prisoner %s. Safecracking, grand larceny. 30 years." % PLAYER_ID,
+            _("An empty cryo unit. Recently filled by you."),
+            _("Prisoner %s. Safecracking, grand larceny. 30 years.")
+            % PLAYER_ID,
             (
                 (399, 426, 70, 56),
                 (404, 455, 69, 120),
                 )))
 
         self.add_thing(GenericCryoUnit(7,
-            "An empty cryo unit.",
-            "Prisoner 83F1-CE32D3234749. Spamming. 5 years.",
+            _("An empty cryo unit."),
+            _("Prisoner 83F1-CE32D3234749. Spamming. 5 years."),
             (
                 (472, 432, 58, 51),
                 (488, 455, 41, 134),
@@ -114,8 +116,8 @@
                 )))
 
         self.add_thing(GenericCryoUnit(8,
-            "An empty cryo unit.",
-            "Prisoner A455-9DF9F43C43E5. Medical malpractice. 10 years.",
+            _("An empty cryo unit."),
+            _("Prisoner A455-9DF9F43C43E5. Medical malpractice. 10 years."),
             (
                 (596, 419, 69, 39),
                 (616, 442, 82, 40),
@@ -132,14 +134,14 @@
         if self.get_data('greet'):
             self.set_data('greet', False)
             return make_jim_dialog(
-                    "Greetings, Prisoner %s. I am the Judicial "
-                    "Incarceration Monitor. "
-                    "You have been woken early under the terms of the "
-                    "emergency conscription act to assist with repairs to "
-                    "the ship. Your behaviour during this time will "
-                    "be noted on your record and will be relayed to "
-                    "prison officials when we reach the destination. "
-                    "Please report to the bridge." % PLAYER_ID, self.game)
+                    _("Greetings, Prisoner %s. I am the Judicial "
+                      "Incarceration Monitor. "
+                      "You have been woken early under the terms of the "
+                      "emergency conscription act to assist with repairs to "
+                      "the ship. Your behaviour during this time will "
+                      "be noted on your record and will be relayed to "
+                      "prison officials when we reach the destination. "
+                      "Please report to the bridge.") % PLAYER_ID, self.game)
 
     def leave(self):
         # Stop music
@@ -167,15 +169,15 @@
             self.game.add_item(pipe)
             self.game.add_inventory_item(pipe.name)
             self.set_interact()
-            responses = [Result("It takes more effort than one would expect,"
-                " but eventually the pipe is separated from the wall.",
-                soundfile="chop-chop.ogg")]
+            responses = [Result(_("It takes more effort than one would expect,"
+                                  " but eventually the pipe is separated from"
+                                  " the wall."), soundfile="chop-chop.ogg")]
             if self.game.current_scene.get_data('vandalism_warn'):
                 self.game.current_scene.set_data('vandalism_warn', False)
                 responses.append(make_jim_dialog(
-                    ("Prisoner %s. Vandalism is an offence punishable by a "
-                     "minimum of an additional 6 months to your sentence."
-                    ) % PLAYER_ID, self.game))
+                    _("Prisoner %s. Vandalism is an offence punishable by a "
+                      "minimum of an additional 6 months to your sentence."
+                     ) % PLAYER_ID, self.game))
             return responses
 
     def is_interactive(self, tool=None):
@@ -183,14 +185,14 @@
 
     def interact_without(self):
         if self.get_data('fixed'):
-            return Result("These pipes aren't attached to the wall very"
-                    " solidly.")
+            return Result(_("These pipes aren't attached to the wall very"
+                            " solidly."))
         return None
 
     def get_description(self):
         if self.get_data('fixed'):
-            return "These pipes carry cooling fluid to empty cryo units."
-        return "There used to be a pipe carrying cooling fluid here."
+            return _("These pipes carry cooling fluid to empty cryo units.")
+        return _("There used to be a pipe carrying cooling fluid here.")
 
 
 class UncuttableCryoPipes(Thing):
@@ -207,17 +209,18 @@
     INITIAL = "fixed"
 
     def interact_with_machete(self, item):
-        return Result("These pipes carry fluid to the working cryo units."
-                " Chopping them down doesn't seem sensible.")
+        return Result(_("These pipes carry fluid to the working cryo units."
+                        " Chopping them down doesn't seem sensible."))
 
     def is_interactive(self, tool=None):
         return True
 
     def interact_without(self):
-        return Result("These pipes aren't attached to the wall very solidly.")
+        return Result(_("These pipes aren't attached to the wall very solidly."
+                       ))
 
     def get_description(self):
-        return "These pipes carry cooling fluid to the working cryo units."
+        return _("These pipes carry cooling fluid to the working cryo units.")
 
 
 class TubeFragment(CloneableItem):
@@ -289,15 +292,15 @@
         return Result(detail_view='cryo_detail')
 
     def interact_with_titanium_leg(self, item):
-        return Result("You hit the chamber that used to hold this very leg."
-                " Nothing happens as a result.",
-                soundfile="clang2.ogg")
+        return Result(_("You hit the chamber that used to hold this very leg."
+                        " Nothing happens as a result."),
+                      soundfile="clang2.ogg")
 
     def get_description(self):
         if self.get_data('contains_titanium_leg'):
-            return "A broken cryo chamber, with a poor unfortunate corpse" \
-                    " inside."
-        return "A broken cryo chamber. The corpse inside is missing a leg."
+            return _("A broken cryo chamber, with a poor unfortunate corpse"
+                     " inside.")
+        return _("A broken cryo chamber. The corpse inside is missing a leg.")
 
 
 class GenericCryoUnit(GenericDescThing):
@@ -319,11 +322,11 @@
 
     def interact_with_titanium_leg(self, item):
         return Result(random.choice([
-                "You bang on the chamber with the titanium femur. Nothing"
-                " much happens.",
-                "Hitting the cryo unit with the femur doesn't achieve"
-                " anything.",
-                "You hit the chamber with the femur. Nothing happens.",
+                _("You bang on the chamber with the titanium femur. Nothing"
+                  " much happens."),
+                _("Hitting the cryo unit with the femur doesn't achieve"
+                  " anything."),
+                _("You hit the chamber with the femur. Nothing happens."),
                 ]), soundfile="clang2.ogg")
 
 
@@ -347,24 +350,25 @@
     def interact_with_titanium_leg(self, item):
         if self.get_data('door') == "ajar":
             self.open_door()
-            return Result("You wedge the titanium femur into the chain and"
-                    " twist. With a satisfying *snap*, the chain breaks and"
-                    " the door opens.", soundfile='break.ogg')
+            return Result(_("You wedge the titanium femur into the chain and"
+                            " twist. With a satisfying *snap*, the chain"
+                            " breaks and the door opens."),
+                          soundfile='break.ogg')
         elif self.get_data('door') == "shut":
-            text = ("You bang on the door with the titanium femur. It makes a"
-                    " clanging sound.")
+            text = _("You bang on the door with the titanium femur. It makes a"
+                     " clanging sound.")
             return Result(text, soundfile='clang.ogg')
         else:
-            return Result("You wave the femur in the doorway. Nothing"
-                    " happens.")
+            return Result(_("You wave the femur in the doorway. Nothing"
+                            " happens."))
 
     def interact_without(self):
         if self.get_data('door') == "shut":
             self.half_open_door()
         if self.get_data('door') != "open":
-            return Result("It moves slightly and then stops. A chain on the"
-                    " other side is preventing it from opening completely.",
-                    soundfile='chain.ogg')
+            return Result(_("It moves slightly and then stops. A chain on the"
+                            " other side is preventing it from opening"
+                            " completely."), soundfile='chain.ogg')
         else:
             self.game.change_scene('map')
             return None
@@ -385,11 +389,11 @@
 
     def get_description(self):
         if self.get_data('door') == "open":
-            return 'An open doorway leads to the rest of the ship.'
+            return _('An open doorway leads to the rest of the ship.')
         elif self.get_data('door') == "ajar":
-            return ("A rusty door. It can't open all the way because of a "
-                    "chain on the other side.")
-        return 'A rusty door. It is currently closed.'
+            return _("A rusty door. It can't open all the way because of a "
+                     "chain on the other side.")
+        return _('A rusty door. It is currently closed.')
 
 
 class CryoComputer(Thing):
@@ -410,10 +414,10 @@
         return Result(detail_view='cryo_comp_detail')
 
     def interact_with_titanium_leg(self, item):
-        return Result("Hitting it with the leg accomplishes nothing.")
+        return Result(_("Hitting it with the leg accomplishes nothing."))
 
     def get_description(self):
-        return "A computer terminal, with some text on it."
+        return _("A computer terminal, with some text on it.")
 
 
 class TitaniumLegThing(Thing):
@@ -432,11 +436,11 @@
         self.game.scenes['cryo'].things['cryo.unit.1'].set_data(
                 'contains_titanium_leg', False)
         self.scene.remove_thing(self)
-        return Result("The skeletal occupant of this cryo unit has an"
-                " artificial femur made of titanium. You take it.")
+        return Result(_("The skeletal occupant of this cryo unit has an"
+                        " artificial femur made of titanium. You take it."))
 
     def get_description(self):
-        return "This femur looks synthetic."
+        return _("This femur looks synthetic.")
 
 
 class PlaqueThing(Thing):
@@ -451,10 +455,11 @@
     INITIAL = "plaque"
 
     def interact_without(self):
-        return Result("The plaque is welded to the unit. You can't shift it.")
+        return Result(_("The plaque is welded to the unit. You can't shift it."
+                       ))
 
     def get_description(self):
-        return "'Prisoner 98CC-764E646391EE. War crimes. 45 years."
+        return _("'Prisoner 98CC-764E646391EE. War crimes. 45 years.")
 
 
 class FullBottle(Item):
@@ -478,16 +483,16 @@
     INITIAL = 'pools'
 
     def get_description(self):
-        return "Coolant leaks disturbingly from the bulkheads."
+        return _("Coolant leaks disturbingly from the bulkheads.")
 
     def interact_without(self):
-        return Result("It's gooey")
+        return Result(_("It's gooey"))
 
     def interact_with_detergent_bottle(self, item):
         full = FullBottle('full_detergent_bottle')
         self.game.add_item(full)
         self.game.replace_inventory_item(item.name, full.name)
-        return Result("You scoop up some coolant and fill the bottle.")
+        return Result(_("You scoop up some coolant and fill the bottle."))
 
 
 class CryoCompDetail(Scene):
--- a/gamelib/scenes/engine.py	Sat Jan 26 13:24:01 2013 +0200
+++ b/gamelib/scenes/engine.py	Sat Jan 26 16:57:33 2013 +0200
@@ -1,5 +1,6 @@
 """Engine room where things need to be repaired."""
 
+from pyntnclick.i18n import _
 from pyntnclick.cursor import CursorSprite
 from pyntnclick.state import Scene, Item, Thing, Result
 from pyntnclick.scenewidgets import (InteractNoImage, InteractRectUnion,
@@ -37,14 +38,14 @@
         self.add_thing(ComputerConsole())
         self.add_thing(ToMap())
         self.add_thing(GenericDescThing('engine.body', 1,
-            "Dead. Those cans must have been past their sell-by date.",
+            _("Dead. Those cans must have been past their sell-by date."),
             (
                 (594, 387, 45, 109),
                 (549, 479, 60, 55),
             )
         ))
         self.add_thing(GenericDescThing('engine.superconductors', 4,
-            "Superconductors. The engines must be power hogs.",
+            _("Superconductors. The engines must be power hogs."),
             (
                 (679, 246, 50, 56),
                 (473, 280, 28, 23),
@@ -52,8 +53,8 @@
             )
         ))
         self.add_thing(GenericDescThing('engine.floor_hole', 5,
-            "A gaping hole in the floor of the room. "
-            "It is clearly irreparable.",
+            _("A gaping hole in the floor of the room. "
+              "It is clearly irreparable."),
             (
                 (257, 493, 141, 55),
                 (301, 450, 95, 45),
@@ -62,27 +63,27 @@
             )
         ))
         self.add_thing(GenericDescThing('engine.empty_cans', 7,
-            "Empty chocolate-covered bacon cans? Poor guy, he must have"
-            " found them irresistible.",
+            _("Empty chocolate-covered bacon cans? Poor guy, he must have"
+              " found them irresistible."),
             (
                 (562, 422, 30, 31),
             )
         ))
         self.add_thing(GenericDescThing('engine.engines', 8,
-            "The engines. They don't look like they are working.",
+            _("The engines. They don't look like they are working."),
             (
                 (342, 261, 109, 81),
             )
         ))
         self.add_thing(GenericDescThing('engine.laser_cutter', 9,
-            "A burned-out laser cutter. It may be responsible for the"
-            " hole in the floor.",
+            _("A burned-out laser cutter. It may be responsible for the"
+              " hole in the floor."),
             (
                 (120, 466, 115, 67),
             )
         ))
         self.add_thing(GenericDescThing('engine.fuel_lines', 10,
-            "The main fuel line for the engines.",
+            _("The main fuel line for the engines."),
             (
                 (220, 49, 59, 75),
                 (239, 84, 51, 66),
@@ -102,21 +103,21 @@
             )
         ))
         self.add_thing(GenericDescThing('engine.spare_fuel_line', 11,
-            "The spare fuel line. If something went wrong with the main"
-            " one, you would hook that one up.",
+            _("The spare fuel line. If something went wrong with the main"
+              " one, you would hook that one up."),
             (
                 (512, 49, 68, 44),
             )
         ))
         self.add_thing(GenericDescThing('engine.danger_area', 12,
-            "The sign says DANGER. You would be wise to listen to it.",
+            _("The sign says DANGER. You would be wise to listen to it."),
             (
                 (293, 343, 211, 46),
             )
         ))
         self.add_thing(GenericDescThing('engine.exit_sign', 13,
-            "It's one of those glow-in-the-dark signs needed to satisfy the "
-            "health and safety inspectors.",
+            _("It's one of those glow-in-the-dark signs needed to satisfy the "
+              "health and safety inspectors."),
             (
                 (681, 322, 80, 33),
             )
@@ -128,18 +129,17 @@
             self.set_data('engine online', True)
             self.remove_thing(self.things['engine.engines.8'])
             self.add_thing(Engines())
-            return make_jim_dialog("The engines are now operational. You have"
-                                   "done a satisfactory job, Prisoner %s."
-                                   % PLAYER_ID,
-                                   self.game)
+            return make_jim_dialog(_("The engines are now operational. You"
+                                     " have done a satisfactory job, Prisoner"
+                                     " %s.") % PLAYER_ID, self.game)
 
     def enter(self):
         if self.get_data('greet'):
             self.set_data('greet', False)
             return Result(
-                    "With your improvised helmet, the automatic airlock allows"
-                    " you into the engine room. Even if there wasn't a vacuum "
-                    "it would be eerily quiet.")
+                    _("With your improvised helmet, the automatic airlock"
+                      " allows you into the engine room. Even if there wasn't"
+                      " a vacuum it would be eerily quiet."))
 
 
 class Engines(Thing):
@@ -155,7 +155,7 @@
         return False
 
     def get_description(self):
-        return "All systems are go! Or at least the engines are."
+        return _("All systems are go! Or at least the engines are.")
 
 
 class CanOpener(Item):
@@ -173,13 +173,13 @@
     INITIAL = 'canopener'
 
     def get_description(self):
-        return "A can opener. Looks like you won't be starving"
+        return _("A can opener. Looks like you won't be starving")
 
     def interact_without(self):
         self.game.add_inventory_item('canopener')
         self.scene.remove_thing(self)
-        return Result("You pick up the can opener. It looks brand new; "
-                      "the vacuum has kept it in perfect condition.")
+        return Result(_("You pick up the can opener. It looks brand new; "
+                        "the vacuum has kept it in perfect condition."))
 
 
 class SuperconductorSocket(Thing):
@@ -200,12 +200,12 @@
 
     def get_description(self):
         if self.get_data('present') and not self.get_data('working'):
-            return ("That superconductor looks burned out. It's wedged"
-                    " in there pretty firmly.")
+            return _("That superconductor looks burned out. It's wedged"
+                     " in there pretty firmly.")
         elif not self.get_data('present'):
-            return "An empty superconductor socket"
+            return _("An empty superconductor socket")
         else:
-            return "A working superconductor."
+            return _("A working superconductor.")
 
     def select_interact(self):
         if not self.get_data('present'):
@@ -216,28 +216,28 @@
 
     def interact_without(self):
         if self.get_data('present') and not self.get_data('working'):
-            return Result("It's wedged in there pretty firmly, it won't"
-                          " come out.")
+            return Result(_("It's wedged in there pretty firmly, it won't"
+                            " come out."))
         elif self.get_data('working'):
-            return Result("You decide that working engines are more important"
-                          " than having a shiny superconductor.")
+            return Result(_("You decide that working engines are more "
+                            " important than having a shiny superconductor."))
 
     def interact_with_machete(self, item):
         if self.get_data('present') and not self.get_data('working'):
             self.set_data('present', False)
             self.set_interact()
-            return Result("With leverage, the burned-out superconductor"
-                          " snaps out. You discard it.")
+            return Result(_("With leverage, the burned-out superconductor"
+                            " snaps out. You discard it."))
 
     def interact_with_superconductor(self, item):
         if self.get_data('present'):
-            return Result("It might help to remove the broken"
-                          " superconductor first")
+            return Result(_("It might help to remove the broken"
+                            " superconductor first"))
         else:
-            return Result("You plug in the superconductor, and feel a hum "
-                          "as things kick into life. "
-                          "Unfortunately, it's the wrong size for the socket "
-                          "and just falls out again when you let go.")
+            return Result(_("You plug in the superconductor, and feel a hum "
+                            "as things kick into life. Unfortunately, it's "
+                            "the wrong size for the socket and just falls "
+                            "out again when you let go."))
 
     def interact_with_taped_superconductor(self, item):
         if not self.get_data('present'):
@@ -245,13 +245,13 @@
             self.set_data('working', True)
             self.set_interact()
             self.game.remove_inventory_item(item.name)
-            results = [Result("The chair's superconductor looks over-specced "
-                              "for this job, but it should work.")]
+            results = [Result(_("The chair's superconductor looks over-specced"
+                                " for this job, but it should work."))]
             results.append(self.scene.engine_online_check())
             return results
         else:
-            return Result("It might help to remove the broken superconductor"
-                          " first.")
+            return Result(_("It might help to remove the broken superconductor"
+                            " first."))
 
 
 class CryoContainers(Thing):
@@ -275,8 +275,8 @@
 
     def get_description(self):
         if not self.get_data('filled'):
-            return "Those are coolant reservoirs. They look empty."
-        return "The coolant reservoirs are full."
+            return _("Those are coolant reservoirs. They look empty.")
+        return _("The coolant reservoirs are full.")
 
     def is_interactive(self, tool=None):
         return False
@@ -296,22 +296,23 @@
     INITIAL = 'containers'
 
     def get_description(self):
-        return "The receptacles for the coolant reservoirs."
+        return _("The receptacles for the coolant reservoirs.")
 
     def interact_without(self):
-        return Result("You stick your finger in the receptacle. "
-                      "It almost gets stuck.")
+        return Result(_("You stick your finger in the receptacle. "
+                        "It almost gets stuck."))
 
     def interact_with_full_detergent_bottle(self, item):
         if not self.scene.things['engine.cracked_pipe'].get_data('fixed'):
-            return Result("Pouring the precious cryo fluid into a"
-                    " container connected to a cracked pipe would be a waste.")
+            return Result(_("Pouring the precious cryo fluid into a"
+                            " container connected to a cracked pipe would be a"
+                            " waste."))
         self.game.remove_inventory_item(item.name)
         self.scene.things['engine.cryo_containers'].set_data('filled', True)
         self.scene.things['engine.cryo_containers'].set_interact()
-        results = [Result("You fill the reservoirs. "
-                          "The detergent bottle was just big enough, which "
-                          "is handy, because it's sprung a leak.")]
+        results = [Result(_("You fill the reservoirs. "
+                            "The detergent bottle was just big enough, which "
+                            "is handy, because it's sprung a leak."))]
         results.append(self.scene.engine_online_check())
         return results
 
@@ -357,10 +358,10 @@
 
     def get_description(self):
         if not self.scene.things['engine.cryo_containers'].get_data('filled'):
-            return "These pipes carry coolant to the superconductors. " \
-                   "They feel warm."
-        return "These pipes carry coolant to the superconductors. " \
-               "They are very cold."
+            return _("These pipes carry coolant to the superconductors. "
+                     "They feel warm.")
+        return _("These pipes carry coolant to the superconductors. "
+                 "They are very cold.")
 
     def is_interactive(self, tool=None):
         return False
@@ -385,8 +386,8 @@
 
     def get_description(self):
         if self.scene.things['engine.superconductor'].get_data('working'):
-            return "Power lines. They are delivering power to the engines."
-        return "Power lines. It looks like they aren't working correctly."
+            return _("Power lines. They are delivering power to the engines.")
+        return _("Power lines. It looks like they aren't working correctly.")
 
     def is_interactive(self, tool=None):
         return False
@@ -476,8 +477,8 @@
         return False
 
     def get_description(self):
-        return "A gaping hole in the floor of the room. You're guessing" \
-            " that's why there's a vacuum in here."
+        return _("A gaping hole in the floor of the room. You're guessing"
+                 " that's why there's a vacuum in here.")
 
 
 class CrackedPipe(Thing):
@@ -496,10 +497,10 @@
 
     def get_description(self):
         if self.get_data('fixed'):
-            return "The duct tape appears to be holding."
+            return _("The duct tape appears to be holding.")
         else:
-            return "The pipe looks cracked and won't hold" \
-                   " fluid until it's fixed."
+            return _("The pipe looks cracked and won't hold"
+                     " fluid until it's fixed.")
 
     def select_interact(self):
         if self.get_data('fixed'):
@@ -508,13 +509,13 @@
 
     def interact_with_duct_tape(self, item):
         if self.get_data('fixed'):
-            return Result("The duct tape already there appears to be "
-                          "sufficient.")
+            return Result(_("The duct tape already there appears to be "
+                            "sufficient."))
         else:
             self.set_data('fixed', True)
             self.set_interact()
-            return Result("You apply your trusty duct tape to the "
-                          "creak, sealing it.")
+            return Result(_("You apply your trusty duct tape to the "
+                            "creak, sealing it."))
 
 
 class ComputerConsole(Thing):
@@ -533,7 +534,7 @@
         return Result(detail_view='engine_comp_detail')
 
     def get_description(self):
-        return "A computer console. It's alarmingly close to the engine."
+        return _("A computer console. It's alarmingly close to the engine.")
 
 
 class EngineCompDetail(Scene):
@@ -589,7 +590,7 @@
     INITIAL = "door"
 
     def get_description(self):
-        return "The airlock leads back to the rest of the ship."
+        return _("The airlock leads back to the rest of the ship.")
 
 
 SCENES = [Engine]
--- a/gamelib/scenes/game_widgets.py	Sat Jan 26 13:24:01 2013 +0200
+++ b/gamelib/scenes/game_widgets.py	Sat Jan 26 16:57:33 2013 +0200
@@ -1,6 +1,7 @@
 """Generic, game specific widgets"""
 
 
+from pyntnclick.i18n import _
 from pyntnclick.state import Thing, Result
 
 from gamelib.custom_widgets import JimLabel
@@ -24,7 +25,7 @@
         self.game.change_scene("map")
 
     def get_description(self):
-        return 'An open doorway leads to the rest of the ship.'
+        return _('An open doorway leads to the rest of the ship.')
 
     def interact_default(self, item):
         return self.interact_without()
@@ -49,12 +50,12 @@
     def get_description(self):
         status = self.state.get_jim_state()
         if status == 'online':
-            return "A security camera watches over the room"
+            return _("A security camera watches over the room")
         elif status == 'looping':
-            return "The security camera is currently offline but should be" \
-                    " working soon"
+            return _("The security camera is currently offline but should be"
+                     " working soon")
         else:
-            return "The security camera is powered down"
+            return _("The security camera is powered down")
 
     def is_interactive(self, tool=None):
         return self.state.get_jim_state() == 'online'
@@ -62,9 +63,10 @@
     def interact_with_escher_poster(self, item):
         # Order matters here, because of helper function
         if self.state.get_jim_state() == 'online':
-            ai_response = make_jim_dialog("3D scene reconstruction failed."
-                    " Critical error. Entering emergency shutdown.",
-                    self.game)
+            ai_response = make_jim_dialog(_("3D scene reconstruction failed."
+                                            " Critical error."
+                                            " Entering emergency shutdown."),
+                                          self.game)
             self.game.data.loop_ai()
             return ai_response
 
--- a/gamelib/scenes/machine.py	Sat Jan 26 13:24:01 2013 +0200
+++ b/gamelib/scenes/machine.py	Sat Jan 26 16:57:33 2013 +0200
@@ -1,5 +1,6 @@
 """Machine room where tools and machines are found."""
 
+from pyntnclick.i18n import _
 from pyntnclick.state import Scene, Item, Thing, Result
 from pyntnclick.cursor import CursorSprite
 from pyntnclick.scenewidgets import (InteractNoImage, InteractImage,
@@ -26,7 +27,7 @@
         self.add_item(CryoPipesThree('cryo_pipes_three'))
         self.add_item(Manual('manual'))
         self.add_thing(GenericDescThing('machine.wires', 2,
-            "Wires run to all the machines in the room",
+            _("Wires run to all the machines in the room"),
             (
                 (250, 172, 252, 12),
                 (388, 183, 114, 13),
@@ -46,16 +47,16 @@
                 (674, 54, 23, 36),
                 )))
         self.add_thing(GenericDescThing('machine.diagram', 3,
-            "A wiring diagram of some sort",
+            _("A wiring diagram of some sort"),
             ((694, 140, 94, 185),)))
         self.add_thing(GenericDescThing('machine.powerpoint', 4,
-            "The cables to this power point have been cut",
+            _("The cables to this power point have been cut"),
             ((155, 22, 92, 74),)))
         self.add_thing(GenericDescThing("machine.powerpoint", 5,
-            "All the machines run off this powerpoint",
+            _("All the machines run off this powerpoint"),
             ((593, 19, 74, 57),)))
         self.add_thing(GenericDescThing("machine.drill_press", 6,
-            "An impressive looking laser drill press",
+            _("An impressive looking laser drill press"),
             (
                 (519, 338, 36, 63),
                 (545, 348, 93, 46),
@@ -68,7 +69,7 @@
                 (605, 304, 26, 8),
             )))
         self.add_thing(GenericDescThing("machine.drill_press_block", 7,
-            "The block for the laser drill press",
+            _("The block for the laser drill press"),
             ((461, 446, 38, 27),)))
 
 
@@ -113,43 +114,43 @@
             return "can_and_tube"
 
     def interact_without(self):
-        return Result("You really don't want to put your hand in there.")
+        return Result(_("You really don't want to put your hand in there."))
 
     def interact_with_empty_can(self, item):
         contents = self.get_data('contents')
         if "can" in contents:
-            return Result("There is already a can in the welder.")
+            return Result(_("There is already a can in the welder."))
         self.game.remove_inventory_item(item.name)
         contents.add("can")
         self.set_interact()
-        return Result("You carefully place the can in the laser welder.")
+        return Result(_("You carefully place the can in the laser welder."))
 
     def interact_with_tube_fragment(self, item):
         contents = self.get_data('contents')
         if "tube" in contents:
-            return Result("There is already a tube fragment in the welder.")
+            return Result(_("There is already a tube fragment in the welder."))
         self.game.remove_inventory_item(item.name)
         contents.add("tube")
         self.set_interact()
-        return Result("You carefully place the tube fragments in the"
-                      " laser welder.")
+        return Result(_("You carefully place the tube fragments in the"
+                        " laser welder."))
 
     def get_description(self):
         contents = self.get_data('contents')
         if not contents:
-            return ("This is a Smith and Wesson 'zOMG' class high-precision"
-                    " laser welder.")
+            return (_("This is a Smith and Wesson 'zOMG' class high-precision"
+                      " laser welder."))
         if len(contents) == 1:
-            msg = "The laser welder looks hungry, somehow."
+            msg = _("The laser welder looks hungry, somehow.")
             if "can" in contents:
-                msg += " It currently contains an empty can."
+                msg += _(" It currently contains an empty can.")
             elif "tube" in contents:
-                msg += " It currently contains a tube fragment."
+                msg += _(" It currently contains a tube fragment.")
         elif len(contents) == 2:
-            msg = "The laser welder looks expectant. "
+            msg = _("The laser welder looks expectant. ")
             if "can" in contents and "tube" in contents:
-                msg += (" It currently contains an empty can and a"
-                        " tube fragment.")
+                msg += _(" It currently contains an empty can and a"
+                         " tube fragment.")
         return msg
 
 
@@ -167,41 +168,39 @@
         welder_slot = self.scene.things["machine.welder.slot"]
         contents = welder_slot.get_data("contents")
         if not contents:
-            return Result("The laser welder doesn't currently contain"
-                          " anything weldable.")
+            return Result(_("The laser welder doesn't currently contain"
+                            " anything weldable."))
         elif len(contents) == 1:
             if "can" in contents:
-                return Result("The laser welder needs something to weld the"
-                              " can to.")
+                return Result(_("The laser welder needs something to weld the"
+                                " can to."))
             elif "tube" in contents:
-                return Result("The laser welder needs something to weld the"
-                              " tube fragments to.")
+                return Result(_("The laser welder needs something to weld the"
+                                " tube fragments to."))
         else:
             welder_slot.set_data("contents", set())
             welder_slot.set_interact()
             if self.game.is_in_inventory("cryo_pipes_one"):
                 self.game.replace_inventory_item("cryo_pipes_one",
                                                   "cryo_pipes_two")
-                return Result("With high-precision spitzensparken, you weld"
-                              " together a second pipe. You bundle the two"
-                              " pipes together.",
-                        soundfile='laser.ogg')
+                return Result(_("With high-precision spitzensparken, you weld"
+                                " together a second pipe. You bundle the two"
+                                " pipes together."), soundfile='laser.ogg')
             elif self.game.is_in_inventory("cryo_pipes_two"):
                 self.game.replace_inventory_item("cryo_pipes_two",
                                                   "cryo_pipes_three")
-                return Result("With high-precision spitzensparken, you create"
-                              " yet another pipe. You store it with the other"
-                              " two.",
-                        soundfile='laser.ogg')
+                return Result(_("With high-precision spitzensparken, you"
+                                " create yet another pipe. You store it with"
+                                " the other two."), soundfile='laser.ogg')
             elif self.game.is_in_inventory("cryo_pipes_three"):
                 # just for safety
                 return None
             else:
                 self.game.add_inventory_item("cryo_pipes_one")
-                return Result("With high-precision spitzensparken, the can and"
-                              " tube are welded into a whole greater than the"
-                              " sum of the parts.",
-                        soundfile='laser.ogg')
+                return Result(_("With high-precision spitzensparken, the can"
+                                " and tube are welded into a whole greater"
+                                " than the sum of the parts."),
+                              soundfile='laser.ogg')
 
 
 class LaserWelderPowerLights(Thing):
@@ -217,7 +216,7 @@
     INITIAL = 'lights'
 
     def get_description(self):
-        return "The power lights pulse expectantly."
+        return _("The power lights pulse expectantly.")
 
 
 class CryoPipesOne(Item):
@@ -255,18 +254,19 @@
     INITIAL = "grind"
 
     def interact_without(self):
-        return Result("It looks like it eats fingers. Perhaps a different"
-                      " approach is in order?")
+        return Result(_("It looks like it eats fingers. Perhaps a different"
+                        " approach is in order?"))
 
     def interact_with_titanium_leg(self, item):
         self.game.replace_inventory_item(item.name, 'machete')
-        return Result("After much delicate grinding and a few close calls with"
-                      " various body parts, the titanium femur now resembles"
-                      " a machete more than a bone. Nice and sharp, too.",
-                      soundfile="grinder.ogg")
+        return Result(_("After much delicate grinding and a few close calls"
+                        " with various body parts, the titanium femur now"
+                        " resembles a machete more than a bone. Nice and"
+                        " sharp, too."), soundfile="grinder.ogg")
 
     def get_description(self):
-        return "A pretty ordinary, albeit rather industrial, grinding machine."
+        return _("A pretty ordinary, albeit rather industrial, grinding"
+                 " machine.")
 
 
 class TitaniumMachete(Item):
@@ -289,9 +289,9 @@
     def interact_without(self):
         self.scene.remove_thing(self)
         self.game.add_inventory_item("manual")
-        return Result("Ah! The ship's instruction manual. You'd feel better"
-                      " if the previous owner wasn't lying next to it with a"
-                      " gaping hole in his rib cage.")
+        return Result(_("Ah! The ship's instruction manual. You'd feel better"
+                        " if the previous owner wasn't lying next to it with a"
+                        " gaping hole in his rib cage."))
 
 
 class Manual(Item):
--- a/gamelib/scenes/map.py	Sat Jan 26 13:24:01 2013 +0200
+++ b/gamelib/scenes/map.py	Sat Jan 26 16:57:33 2013 +0200
@@ -7,6 +7,7 @@
    Many parts of the ship are derelict and inaccessible.
    """
 
+from pyntnclick.i18n import _
 from pyntnclick.state import Scene, Thing, Result
 from pyntnclick.scenewidgets import InteractRectUnion
 
@@ -37,15 +38,15 @@
         if self.get_data('implant'):
             self.set_data('implant', False)
             ai1 = make_jim_dialog(
-                "Under the terms of the emergency conscription "
-                "act, I have downloaded the ship's schematics to your "
-                "neural implant to help you navigate around the ship.",
+                _("Under the terms of the emergency conscription "
+                  "act, I have downloaded the ship's schematics to your "
+                  "neural implant to help you navigate around the ship."),
                 self.game)
             if ai1:
-                return ai1, make_jim_dialog("Prisoner %s, you are a "
+                return ai1, make_jim_dialog(_("Prisoner %s, you are a "
                 "class 1 felon. Obtaining access to the ship's schematics "
                 "constitutes a level 2 offence and carries a minimal penalty "
-                "of an additional 3 years on your sentence." % PLAYER_ID,
+                "of an additional 3 years on your sentence.") % PLAYER_ID,
                 self.game)
 
 
@@ -125,9 +126,9 @@
 
     def interact(self, item):
         if not self.game.is_in_inventory('helmet'):
-            return Result('The airlock refuses to open. The automated'
+            return Result(_('The airlock refuses to open. The automated'
                     ' voice says: "Hull breach beyond this door. Personnel'
-                    ' must be equipped for vacuum before entry."')
+                    ' must be equipped for vacuum before entry."'))
         else:
             return super(ToEngine, self).interact(item)
 
@@ -180,8 +181,9 @@
     INITIAL = 'areas'
 
     def interact(self, _item):
-        return Result("You look in the door, but just see empty space: "
-                      "that room appears to have been obliterated by meteors.")
+        return Result(_("You look in the door, but just see empty space: "
+                        "that room appears to have been obliterated by "
+                        "meteors."))
 
 
 class HydroponicsArea(Thing):
@@ -197,9 +199,9 @@
     INITIAL = 'areas'
 
     def interact(self, _item):
-        return Result("Peering in through the window, you see that the entire "
-                      "chamber is overgrown with giant broccoli. It would "
-                      "take you years to cut a path through that.")
+        return Result(_("Peering in through the window, you see that the "
+                        "entire chamber is overgrown with giant broccoli. "
+                        "It would take you years to cut a path through that."))
 
 
 SCENES = [Map]
--- a/gamelib/scenes/mess.py	Sat Jan 26 13:24:01 2013 +0200
+++ b/gamelib/scenes/mess.py	Sat Jan 26 16:57:33 2013 +0200
@@ -2,6 +2,7 @@
 
 from random import randint
 
+from pyntnclick.i18n import _
 from pyntnclick.state import Scene, Item, CloneableItem, Thing, Result
 from pyntnclick.cursor import CursorSprite
 from pyntnclick.scenewidgets import (InteractNoImage, InteractImage,
@@ -31,13 +32,13 @@
         # Flavour items
         # extra cans on shelf
         self.add_thing(GenericDescThing('mess.cans', 1,
-            "A large collection of rusted, useless cans.",
+            _("A large collection of rusted, useless cans."),
             (
                 (154, 335, 89, 106),
                 (152, 435, 63, 66),
                 )))
         self.add_thing(GenericDescThing('mess.broccoli', 2,
-            "An impressively overgrown broccoli.",
+            _("An impressively overgrown broccoli."),
             (
                 (503, 89, 245, 282),
                 (320, 324, 229, 142),
@@ -48,8 +49,8 @@
     """Base class for the cans"""
 
     def interact_with_full_can(self, item):
-        return Result("You bang the cans together. It sounds like two"
-                      " cans being banged together.",
+        return Result(_("You bang the cans together. It sounds like two"
+                        " cans being banged together."),
                       soundfile="can_hit.ogg")
 
     def interact_with_dented_can(self, item):
@@ -59,14 +60,14 @@
         return self.interact_with_full_can(item)
 
     def interact_with_machete(self, item):
-        return Result("You'd mangle it beyond usefulness.")
+        return Result(_("You'd mangle it beyond usefulness."))
 
     def interact_with_canopener(self, item):
         empty = EmptyCan('empty_can')
         self.game.add_item(empty)
         self.game.replace_inventory_item(self.name, empty.name)
-        return Result("You open both ends of the can, discarding the"
-                      " hideous contents.")
+        return Result(_("You open both ends of the can, discarding the"
+                        " hideous contents."))
 
 
 class EmptyCan(BaseCan):
@@ -76,11 +77,11 @@
     CURSOR = CursorSprite('empty_can_cursor.png')
 
     def interact_with_titanium_leg(self, item):
-        return Result("Flattening the can doesn't look like a useful"
-                      " thing to do.")
+        return Result(_("Flattening the can doesn't look like a useful"
+                        " thing to do."))
 
     def interact_with_canopener(self, item):
-        return Result("There's nothing left to open on this can")
+        return Result(_("There's nothing left to open on this can"))
 
 
 class FullCan(BaseCan):
@@ -93,8 +94,8 @@
         dented = DentedCan("dented_can")
         self.game.add_item(dented)
         self.game.replace_inventory_item(self.name, dented.name)
-        return Result("You club the can with the femur. The can gets dented,"
-                      " but doesn't open.", soundfile="can_hit.ogg")
+        return Result(_("You club the can with the femur. The can gets dented,"
+                        " but doesn't open."), soundfile="can_hit.ogg")
 
 
 class DentedCan(BaseCan):
@@ -104,8 +105,8 @@
     CURSOR = CursorSprite('dented_can_cursor.png')
 
     def interact_with_titanium_leg(self, item):
-        return Result("You club the can with the femur. The dents shift"
-                      " around, but it still doesn't open.",
+        return Result(_("You club the can with the femur. The dents shift"
+                        " around, but it still doesn't open."),
                       soundfile="can_hit.ogg")
 
 
@@ -140,16 +141,17 @@
             if starting_cans == 1:
                 self.scene.remove_thing(self)
             return Result({
-                    3: "Best before a long time in the past."
-                       " Better not eat these.",
-                    2: "Mmmm. Nutritious bacteria stew.",
-                    1: "Candied silkworms. Who stocked this place?!",
+                    3: _("Best before a long time in the past."
+                         " Better not eat these."),
+                    2: _("Mmmm. Nutritious bacteria stew."),
+                    1: _("Candied silkworms. Who stocked this place?!"),
                     }[starting_cans])
         else:
-            return Result("The rest of the cans are rusted beyond usefulness.")
+            return Result(_("The rest of the cans are rusted beyond "
+                            "usefulness."))
 
     def get_description(self):
-        return "The contents of these cans look synthetic."
+        return _("The contents of these cans look synthetic.")
 
 
 class Tubes(Thing):
@@ -171,15 +173,15 @@
 
     def get_description(self):
         if self.get_data('status') == "blocked":
-            return ("The broccoli seems to have become"
-                    " entangled with something.")
+            return _("The broccoli seems to have become"
+                     " entangled with something.")
         elif self.get_data("status") == "broken":
-            return "These broken pipes look important."
+            return _("These broken pipes look important.")
         elif self.get_data("status") == "replaced":
-            return ("The pipes have been repaired but are the repairs"
-                    " aren't airtight, yet")
+            return _("The pipes have been repaired but are the repairs"
+                     " aren't airtight, yet")
         else:
-            return "Your fix looks like it's holding up well."
+            return _("Your fix looks like it's holding up well.")
 
     def select_interact(self):
         return self.get_data('status')
@@ -188,56 +190,58 @@
         if self.get_data("status") == "blocked":
             self.set_data("status", "broken")
             self.set_interact()
-            return Result("With a flurry of disgusting mutant vegetable "
-                          "chunks, you clear the overgrown broccoli away from "
-                          "the access panel and reveal some broken tubes. "
-                          "They look important.",
+            return Result(_("With a flurry of disgusting mutant vegetable "
+                            "chunks, you clear the overgrown broccoli away "
+                            "from the access panel and reveal some broken "
+                            "tubes. They look important."),
                           soundfile='chopping.ogg')
         elif self.get_data("status") == "broken":
-            return Result("It looks broken enough already.")
+            return Result(_("It looks broken enough already."))
         elif self.get_data("status") == "replaced":
-            return Result("Cutting holes won't repair the leaks.")
+            return Result(_("Cutting holes won't repair the leaks."))
         else:
-            return Result("After all that effort fixing it, chopping it to "
-                          "bits doesn't seem very smart.")
+            return Result(_("After all that effort fixing it, chopping it to "
+                            "bits doesn't seem very smart."))
 
     def interact_with_cryo_pipes_three(self, item):
         if self.get_data("status") == "blocked":
-            return Result("It would get lost in the fronds.")
+            return Result(_("It would get lost in the fronds."))
         else:
             self.game.remove_inventory_item(item.name)
             self.set_data('status', 'replaced')
             self.set_interact()
             self.scene.set_data('life support status', 'replaced')
-            return Result("The pipes slot neatly into place, but don't make"
-                          " an airtight seal. One of the pipes has cracked"
-                          " slightly as well.")
+            return Result(_("The pipes slot neatly into place, but don't make"
+                            " an airtight seal. One of the pipes has cracked"
+                            " slightly as well."))
 
     def interact_with_duct_tape(self, item):
         if self.get_data("status") == "broken":
-            return Result("It would get lost in the fronds.")
+            return Result(_("It would get lost in the fronds."))
         elif self.get_data("status") == 'fixed':
-            return Result("There's quite enough tape on the ducting already.")
+            return Result(_("There's quite enough tape on the ducting already."
+                           ))
         else:
             self.set_data("fixed", True)
             self.set_data("status", "fixed")
             self.set_interact()
             self.scene.set_data('life support status', 'fixed')
-            return Result("It takes quite a lot of tape, but eventually"
-                          "everything is airtight and ready to hold pressure."
-                          " Who'd've thought duct tape could actually be used"
-                          " to tape ducts?")
+            return Result(_("It takes quite a lot of tape, but eventually "
+                            "everything is airtight and ready to hold "
+                            "pressure. Who'd've thought duct tape could "
+                            "actually be used to tape ducts?"))
 
     def interact_without(self):
         if self.get_data("status") == "blocked":
-            return Result("The mutant broccoli resists your best efforts.")
+            return Result(_("The mutant broccoli resists your best efforts."))
         elif self.get_data("status") == "broken":
-            return Result("Shoving the broken pipes around doesn't help much.")
+            return Result(_("Shoving the broken pipes around doesn't help "
+                            "much."))
         elif self.get_data("status") == "replaced":
-            return Result("Do you really want to hold it together for the "
-                          "rest of the voyage?")
+            return Result(_("Do you really want to hold it together for the "
+                            "rest of the voyage?"))
         else:
-            return Result("You don't find any leaks. Good job, Prisoner %s."
+            return Result(_("You don't find any leaks. Good job, Prisoner %s.")
                           % PLAYER_ID)
 
 
@@ -304,15 +308,16 @@
 
     def interact_without(self):
         if self.get_data('taken'):
-            return Result("The remaining bottles leak.")
+            return Result(_("The remaining bottles leak."))
         self.set_data('taken', True)
         self.set_interact()
         self.game.add_inventory_item('detergent_bottle')
-        return Result("You pick up an empty dishwashing liquid bottle. You"
-                      " can't find any sponges.")
+        return Result(_("You pick up an empty dishwashing liquid bottle. You"
+                        " can't find any sponges."))
 
     def get_description(self):
-        return "Empty plastic containers. They used to hold dishwasher soap."
+        return _("Empty plastic containers. "
+                 "They used to hold dishwasher soap.")
 
 
 class DetergentBottle(Item):
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/install-po.sh	Sat Jan 26 16:57:33 2013 +0200
@@ -0,0 +1,10 @@
+#!/bin/sh
+
+# Compiles and installs translation catalogs
+
+for pofile in po/*.po; do
+  molang=`echo $pofile | sed -e 's#po/\(.*\)\\.po#\\1#'`;
+  mofile=`echo $pofile | sed -e 's/\\.po/.mo/'`;
+  mkdir -p data/locale/$molang/LC_MESSAGES
+  msgfmt $pofile -o data/locale/$molang/LC_MESSAGES/suspended-sentence.mo
+done
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/po/POTFILES	Sat Jan 26 16:57:33 2013 +0200
@@ -0,0 +1,11 @@
+gamelib/widgets.py
+gamelib/gamescreen.py
+gamelib/scenes/bridge.py
+gamelib/scenes/crew_quarters.py
+gamelib/scenes/cryo.py
+gamelib/scenes/engine.py
+gamelib/scenes/machine.py
+gamelib/scenes/manual.py
+gamelib/scenes/map.py
+gamelib/scenes/mess.py
+gamelib/scenes/game_widgets.py
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/po/ru.po	Sat Jan 26 16:57:33 2013 +0200
@@ -0,0 +1,844 @@
+# Russian translations for suspended-sentence package
+# Русские переводы для пакета suspended-sentence.
+# Copyright (C) 2011 THE PACKAGE'S COPYRIGHT HOLDER
+# This file is distributed under the same license as the suspended-sentence package.
+# Sergey Basalaev <sbasalaev@gmail.com>, 2011.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: suspended-sentence 1.0.1\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2011-03-08 14:36+0200\n"
+"PO-Revision-Date: 2011-03-08 23:13+0600\n"
+"Last-Translator: Sergey Basalaev <sbasalaev@gmail.com>\n"
+"Language-Team: Russian\n"
+"Language: \n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"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);\n"
+
+#: gamelib/widgets.py:175
+msgid "Quit Game"
+msgstr "Выйти из игры"
+
+#: gamelib/widgets.py:176
+msgid "Exit to Main Menu"
+msgstr "Главное меню"
+
+#: gamelib/gamescreen.py:146
+msgid "Close"
+msgstr "Закрыть"
+
+#: gamelib/gamescreen.py:218
+msgid "Menu"
+msgstr "Меню"
+
+#: gamelib/scenes/bridge.py:63
+msgid "The brightly coloured wires contrast with the drab walls."
+msgstr "Яркие разноцветные провода контрастируют с блеклыми стенами."
+
+#: gamelib/scenes/bridge.py:66
+msgid "\"Dammit JIM, I'm a doctor, not an engineer!\""
+msgstr "«Проклятый JIM, я доктор, а не инженер!»"
+
+#: gamelib/scenes/bridge.py:72
+msgid "A skeleton hangs improbably from the wires."
+msgstr "Скелет неправдоподобно свисает с проводов."
+
+#: gamelib/scenes/bridge.py:117
+msgid "You can't break the duraplastic screen."
+msgstr "Вы не можете разбить дюралепластиковый экран."
+
+#: gamelib/scenes/bridge.py:120
+msgid "Scratching the screen won't help you."
+msgstr "Царапание экрана вам не поможет."
+
+#: gamelib/scenes/bridge.py:123
+msgid "The main bridge computer screen."
+msgstr "Экран главного компьютера капитанского моста."
+
+#: gamelib/scenes/bridge.py:146
+msgid "A top of the line Massage-o-Matic Captain's Executive Command Chair. It's massaging a skeleton."
+msgstr "Лучшее из линейки Массаж-о-матик Кресло Капитана Команды. Оно массажирует скелет."
+
+#: gamelib/scenes/bridge.py:148
+msgid "The chair won't work any more, it has no power."
+msgstr "Кресло больше не будет работать, оно лишено питания."
+
+#: gamelib/scenes/bridge.py:197
+msgid "A stethoscope hangs from the neck of the skeleton."
+msgstr "Стетоскоп свисает с шеи скелета."
+
+#: gamelib/scenes/bridge.py:204
+msgid "You pick up the stethoscope and verify that the doctor's heart has stopped. Probably a while ago."
+msgstr "Вы берёте стетоскоп и убеждаетесь, что сердце доктора остановилось. Вероятно уже давно."
+
+#: gamelib/scenes/bridge.py:225
+msgid "You rip off a piece of duct tape and stick it on the superconductor. It almost sticks to itself, but you successfully avoid disaster."
+msgstr "Вы отрываете кусок трубопроводной ленты и приклеиваете её к сверхпроводнику. Она почти прилипает сама к себе, но вы успешно избегаете катастрофы."
+
+#: gamelib/scenes/bridge.py:245
+msgid "The superconductor module unclips easily."
+msgstr "Чип сверхпроводника легко отделяется."
+
+#: gamelib/scenes/bridge.py:246
+#, python-format
+msgid "Prisoner %s. That chair you've destroyed was property of the ship's captain. You will surely be punished."
+msgstr "Заключённый %s. Кресло, испорченное вами, было имуществом капитана корабля. Вы обязательно будете наказаны."
+
+#: gamelib/scenes/bridge.py:278
+msgid "The lights flash in interesting patterns."
+msgstr "Огни мигают в интересных комбинациях."
+
+#: gamelib/scenes/bridge.py:279
+msgid "The flashing lights don't mean anything to you."
+msgstr "Мигающие огни ничего для вас не значат."
+
+#: gamelib/scenes/bridge.py:280
+msgid "The console lights flash and flicker."
+msgstr "Огни консоли мигают и мерцают."
+
+#: gamelib/scenes/bridge.py:323
+msgid "The sign reads 'Warning: Authorized Techinicians Only'."
+msgstr "На знаке написано 'Предупреждение: Только Авторизованные Техники'."
+
+#: gamelib/scenes/bridge.py:329
+msgid "You are unable to open the panel with your bare hands."
+msgstr "Вы не можете открыть панель голыми руками."
+
+#: gamelib/scenes/bridge.py:334
+msgid "You unplug various important-looking wires."
+msgstr "Вы отсоединяете всякие важно выглядящие провода."
+
+#: gamelib/scenes/bridge.py:343
+msgid "Using the machete, you lever the panel off."
+msgstr "Используя мачете, вы снимаете панель."
+
+#: gamelib/scenes/bridge.py:348
+msgid "You smash various delicate components with the machete."
+msgstr "Вы разбиваете разные хрупкие детали с помощью мачете."
+
+#: gamelib/scenes/bridge.py:352
+msgid "You feel a shock from the panel."
+msgstr "Вас бьёт током от панели."
+
+#: gamelib/scenes/bridge.py:353
+#, python-format
+msgid "Prisoner %s. Please step away from the panel. You are not an authorized technician."
+msgstr "Заключённый %s. Пожалуйста, отойдите от панели. Вы не являетесь авторизованным техником."
+
+#: gamelib/scenes/bridge.py:451
+msgid "You are not authorized to change the destination."
+msgstr "Вы не имеете права изменять пункт назначения."
+
+#: gamelib/scenes/bridge.py:453
+msgid "There's no good reason to choose to go to the penal colony."
+msgstr "Нет причины выбирать полёт в колонию."
+
+#: gamelib/scenes/bridge.py:455
+msgid "You could change the destination, but when JIM recovers, it'll just get reset."
+msgstr "Вы можете изменить пункт назначения, но когда JIM восстановится, он сбросит его обратно."
+
+#: gamelib/scenes/bridge.py:457
+msgid "You change the destination."
+msgstr "Вы изменяете пункт назначения."
+
+#: gamelib/scenes/crew_quarters.py:31
+msgid "The plant is doing surprisingly well for centuries of neglect"
+msgstr "Растение перенесло века забвения неожиданно хорошо."
+
+#: gamelib/scenes/crew_quarters.py:34
+msgid "A picture of a cat labelled 'Clementine'"
+msgstr "Изображение кота, подписанное 'Клементин'"
+
+#: gamelib/scenes/crew_quarters.py:73
+msgid "Duct tape. It'll stick to everything except ducts, apparently."
+msgstr "Трубопроводная лента. Она прилипает ко всему, кроме трубопровода."
+
+#: gamelib/scenes/crew_quarters.py:75
+msgid "The perfectly balanced door swings frictionlessly to and fro. What craftsmanship!"
+msgstr "Идеально сбалансированная дверь легко качается туда-сюда. Ну что за работа!"
+
+#: gamelib/scenes/crew_quarters.py:77
+msgid "The safe is locked. This might be an interesting challenge, if suitable equipment can be found."
+msgstr "Сейф закрыт. Может быть интересным вызовом для вас, если найти подходящее оборудование."
+
+#: gamelib/scenes/crew_quarters.py:82
+msgid "It's already unlocked. There's no more challenge."
+msgstr "Он уже открыт. Это больше не интересно."
+
+#: gamelib/scenes/crew_quarters.py:87
+msgid "Even after centuries of neglect, the tumblers slide almost silently into place. Turns out the combination was '1 2 3 4 5'. An idiot must keep his luggage in here."
+msgstr "Даже после веков забвения, замки двигаются почти бесшумно. Выясняется, что комбинация была '1 2 3 4 5'. Наверное, здесь хранил свой багаж идиот."
+
+#: gamelib/scenes/crew_quarters.py:91
+#, python-format
+msgid "Prisoner %s, you have been observed committing a felony violation. This will go onto your permanent record, and your sentence may be extended by up to twenty years."
+msgstr "Заключённый %s, вы были замечены за совершением уголовного преступления. Это войдёт в ваше личное дело, и ваш срок может быть увеличен до двадцати лет."
+
+#: gamelib/scenes/crew_quarters.py:96
+msgid "Ah, a vintage Knoxx & Co. model QR3. Quaint, but reasonably secure."
+msgstr "Ах, винтажная модель QR3 от Knoxx & Co. Древняя, но довольно безопасная."
+
+#: gamelib/scenes/crew_quarters.py:117
+msgid "What's the point of lugging around a very dead fish and a kilogram or so of sand?"
+msgstr "Какой смысл таскать с собой мёртвую рыбину и килограмм или около того песка?"
+
+#: gamelib/scenes/crew_quarters.py:122
+msgid "The fishbowl is useful, but its contents aren't."
+msgstr "Аквариум может пригодиться, а вот его содержимое вряд ли."
+
+#: gamelib/scenes/crew_quarters.py:126
+msgid "This fishbowl looks exactly like an old science fiction space helmet."
+msgstr "Этот аквариум выглядит в точности как космический шлем из старой научной фантастики."
+
+#: gamelib/scenes/crew_quarters.py:128
+msgid "An evicted dead fish and some sand lie forlornly on the table"
+msgstr "Выселенная мёртвая рыба и "
+
+#: gamelib/scenes/crew_quarters.py:142
+msgid "You duct tape the edges of the helmet. The seal is crude, but it will serve as a workable helmet if needed."
+msgstr "Вы прилепяете ленту к краям шлема. Крепление грубое, но оно может послужить, как рабочий шлем, если нужно."
+
+#: gamelib/scenes/crew_quarters.py:189
+msgid "This poster will go nicely on your bedroom wall."
+msgstr "Этот плакат будет неплохо смотреться на стене вашей спальни."
+
+#: gamelib/scenes/crew_quarters.py:192
+msgid "A paradoxical poster hangs below the security camera."
+msgstr "Парадоксальный плакат висит под камерой безопасности."
+
+#: gamelib/scenes/cryo.py:53
+msgid "These pipes carry cooling fluid to the cryo units."
+msgstr "По этим трубам охлаждающая жидкость подаётся к криокамерам."
+
+#: gamelib/scenes/cryo.py:64
+msgid "An empty cryo chamber."
+msgstr "Пустая криокамера."
+
+#: gamelib/scenes/cryo.py:65
+msgid "Prisoner 81E4-C8900480E635. Embezzlement. 20 years."
+msgstr "Заключённый 81E4-C8900480E635. Хищение имущества. 20 лет."
+
+#: gamelib/scenes/cryo.py:74
+#: gamelib/scenes/cryo.py:93
+msgid "A working cryo chamber. The frosted glass obscures the details of the occupant."
+msgstr "Работающая криокамера. Обитатель не виден из-за замёрзшего стекла."
+
+#: gamelib/scenes/cryo.py:75
+msgid "Prisoner 9334-CE1EB0243BAB. Murder. 40 years."
+msgstr "Заключённый 9334-CE1EB0243BAB. Убийство. 40 лет."
+
+#: gamelib/scenes/cryo.py:84
+msgid "A broken cryo chamber. The skeleton inside has been picked clean."
+msgstr "Сломанная криокамера. Скелет внутри был обчищен."
+
+#: gamelib/scenes/cryo.py:85
+msgid "Prisoner BFBC-8BF4C6B7492B. Importing illegal alien biomatter. 15 years."
+msgstr "Заключённый BFBC-8BF4C6B7492B. Импорт нелегальной биоматерии пришельцев. 15 лет."
+
+#: gamelib/scenes/cryo.py:94
+msgid "Prisoner B520-99495B8C41CE. Copyright infringement. 60 years."
+msgstr "Заключённый B520-99495B8C41CE. Нарушение авторских прав. 60 лет."
+
+#: gamelib/scenes/cryo.py:101
+msgid "An empty cryo unit. Recently filled by you."
+msgstr "Пустая криокамера. Недавно в ней были вы."
+
+#: gamelib/scenes/cryo.py:102
+#, python-format
+msgid "Prisoner %s. Safecracking, grand larceny. 30 years."
+msgstr "Заключённый %s. Взлом сейфа, кражи в крупных размерах. 30 лет."
+
+#: gamelib/scenes/cryo.py:109
+#: gamelib/scenes/cryo.py:118
+msgid "An empty cryo unit."
+msgstr "Пустая криокамера."
+
+#: gamelib/scenes/cryo.py:110
+msgid "Prisoner 83F1-CE32D3234749. Spamming. 5 years."
+msgstr "Заключённый 83F1-CE32D3234749. Спам. 5 лет."
+
+#: gamelib/scenes/cryo.py:119
+msgid "Prisoner A455-9DF9F43C43E5. Medical malpractice. 10 years."
+msgstr "Заключённый A455-9DF9F43C43E5. Медицинская халатность. 10 лет."
+
+#: gamelib/scenes/cryo.py:135
+#, python-format
+msgid "Greetings, Prisoner %s. I am the Judicial Incarceration Monitor. You have been woken early under the terms of the emergency conscription act to assist with repairs to the ship. Your behaviour during this time will be noted on your record and will be relayed to prison officials when we reach the destination. Please report to the bridge."
+msgstr "Приветствую вас, Заключённый %s. Я — JIM, Монитор Судебного Заключения. Вы были пробуждены раньше срока в соответствии с предписанием о помощи в починке корабля при чрезвычайной ситуации. Ваше поведение в течение ремонтных работ будет занесено в личное дело и рассмотрено официальными лицами по прибытии в пункт назначения. Пожалуйста, отрапортуйте на капитанский мост."
+
+#: gamelib/scenes/cryo.py:165
+msgid "It takes more effort than one would expect, but eventually the pipe is separated from the wall."
+msgstr "Это требует больше усилий, чем можно было ожидать, но в конце концов труба отделяется от стены."
+
+#: gamelib/scenes/cryo.py:171
+#, python-format
+msgid "Prisoner %s. Vandalism is an offence punishable by a minimum of an additional 6 months to your sentence."
+msgstr "Заключённый %s. Вандализм является правонарушением и карается как минимум дополнительными 6 меcяцами к вашему сроку."
+
+#: gamelib/scenes/cryo.py:181
+#: gamelib/scenes/cryo.py:211
+msgid "These pipes aren't attached to the wall very solidly."
+msgstr "Эти трубы не очень прочно прикреплены к стене."
+
+#: gamelib/scenes/cryo.py:186
+msgid "These pipes carry cooling fluid to empty cryo units."
+msgstr "По этим трубам охлаждающая жидкость подаётся к пустым криокамерам."
+
+#: gamelib/scenes/cryo.py:187
+msgid "There used to be a pipe carrying cooling fluid here."
+msgstr "Здесь была труба, подающая охлаждающую жидкость."
+
+#: gamelib/scenes/cryo.py:204
+msgid "These pipes carry fluid to the working cryo units. Chopping them down doesn't seem sensible."
+msgstr "Эти трубы подают охлаждающую жидкость к работающим криокамерам. "
+
+#: gamelib/scenes/cryo.py:214
+msgid "These pipes carry cooling fluid to the working cryo units."
+msgstr "По этим трубам охлаждающая жидкость подаётся к рабочим криокамерам."
+
+#: gamelib/scenes/cryo.py:286
+msgid "You hit the chamber that used to hold this very leg. Nothing happens as a result."
+msgstr "Вы ударяете по камере, в которой находилась эта нога. В итоге ничего не происходит."
+
+#: gamelib/scenes/cryo.py:291
+msgid "A broken cryo chamber, with a poor unfortunate corpse inside."
+msgstr "Сломанная криокамера, с бедным несчастным телом внутри."
+
+#: gamelib/scenes/cryo.py:292
+msgid "A broken cryo chamber. The corpse inside is missing a leg."
+msgstr "Сломанная криокамера. У тела внутри отсутствует нога."
+
+#: gamelib/scenes/cryo.py:313
+msgid "You bang on the chamber with the titanium femur. Nothing much happens."
+msgstr "Вы стучите по камере титановым бедром. Не происходит ничего особенного."
+
+#: gamelib/scenes/cryo.py:314
+msgid "Hitting the cryo unit with the femur doesn't achieve anything."
+msgstr "Стучание ребром по криокамере ничего не даёт."
+
+#: gamelib/scenes/cryo.py:315
+msgid "You hit the chamber with the femur. Nothing happens."
+msgstr "Вы бьёте бедром по камере. Ничего не происходит."
+
+#: gamelib/scenes/cryo.py:339
+msgid "You wedge the titanium femur into the chain and twist. With a satisfying *snap*, the chain breaks and the door opens."
+msgstr "Вы просовываете титановое бедро в цепь и поворачиваете. С удовлетворённым *хрусь*, цепь ломается, и дверь открывается."
+
+#: gamelib/scenes/cryo.py:341
+msgid "You bang on the door with the titanium femur. It makes a clanging sound."
+msgstr "Вы стучите по двери титановым бедром. Она издаёт гулкий звук."
+
+#: gamelib/scenes/cryo.py:344
+msgid "You wave the femur in the doorway. Nothing happens."
+msgstr "Вы машете бедром в дверном проходе. Ничего не происходит."
+
+#: gamelib/scenes/cryo.py:350
+msgid "It moves slightly and then stops. A chain on the other side is preventing it from opening completely."
+msgstr "Дверь немного двигается и затем останавливается. Цепь на другой стороне мешает ей полностью открыться."
+
+#: gamelib/scenes/cryo.py:368
+#: gamelib/scenes/game_widgets.py:26
+msgid "An open doorway leads to the rest of the ship."
+msgstr "Открытый дверной проём ведёт к оставшей части корабля."
+
+#: gamelib/scenes/cryo.py:370
+msgid "A rusty door. It can't open all the way because of a chain on the other side."
+msgstr "Ржавая дверь. Она не может полностью открыться из-за цепи на другой стороне."
+
+#: gamelib/scenes/cryo.py:372
+msgid "A rusty door. It is currently closed."
+msgstr "Ржавая дверь. Сейчас она закрыта."
+
+#: gamelib/scenes/cryo.py:393
+msgid "Hitting it with the leg accomplishes nothing."
+msgstr "Стучание ногой по этому не принесёт результатов."
+
+#: gamelib/scenes/cryo.py:396
+msgid "A computer terminal, with some text on it."
+msgstr "Терминал компьютера, на нём какой-то текст."
+
+#: gamelib/scenes/cryo.py:414
+msgid "The skeletal occupant of this cryo unit has an artificial femur made of titanium. You take it."
+msgstr "У скелета, обитающего в этой криокамере искусственное бедро, сделанное из титана. Вы берёте его."
+
+#: gamelib/scenes/cryo.py:417
+msgid "This femur looks synthetic."
+msgstr "Это бедро кажется искусственным."
+
+#: gamelib/scenes/cryo.py:432
+msgid "The plaque is welded to the unit. You can't shift it."
+msgstr "Пластина впаяна в камеру. Вы не можете её сдвинуть."
+
+#: gamelib/scenes/cryo.py:435
+msgid "'Prisoner 98CC-764E646391EE. War crimes. 45 years."
+msgstr "Заключённый 98CC-764E646391EE. Военные преступления. 45 лет."
+
+#: gamelib/scenes/cryo.py:459
+msgid "Coolant leaks disturbingly from the bulkheads."
+msgstr "Охладитель тревожно вытекает из-под переборки."
+
+#: gamelib/scenes/cryo.py:462
+msgid "It's gooey"
+msgstr ""
+
+#: gamelib/scenes/cryo.py:468
+msgid "You scoop up some coolant and fill the bottle."
+msgstr "Вы зачерпываете немного охладителя и наполняете бутылку."
+
+#: gamelib/scenes/engine.py:43
+msgid "Dead. Those cans must have been past their sell-by date."
+msgstr "Чёрт. Похоже все эти банки уже просрочены."
+
+#: gamelib/scenes/engine.py:50
+msgid "Superconductors. The engines must be power hogs."
+msgstr "Сверхпроводники. Двигатели наверняка прожорливы."
+
+#: gamelib/scenes/engine.py:58
+msgid "A gaping hole in the floor of the room. It is clearly irreparable."
+msgstr "Сквозная дыра в полу комнаты. Её, очевидно, невозможно починить."
+
+#: gamelib/scenes/engine.py:68
+msgid "Empty chocolate-covered bacon cans? Poor guy, he must have found them irresistible."
+msgstr "Пустые банки из под бекона в шоколаде? Бедный парень, он наверное нашёл их беззащитными."
+
+#: gamelib/scenes/engine.py:74
+msgid "The engines. They don't look like they are working."
+msgstr "Двигатели. Непохоже, что они работают."
+
+#: gamelib/scenes/engine.py:80
+msgid "A burned-out laser cutter. It may be responsible for the hole in the floor."
+msgstr "Перегоревший лазерный резак. Он может быть ответственен за дыру в полу."
+
+#: gamelib/scenes/engine.py:86
+msgid "The main fuel line for the engines."
+msgstr "Главная топливная шина для двигателей."
+
+#: gamelib/scenes/engine.py:106
+msgid "The spare fuel line. If something went wrong with the main one, you would hook that one up."
+msgstr "Запасная топливная шина. Она задействуется, если что-то случится с главной."
+
+#: gamelib/scenes/engine.py:112
+msgid "The sign says DANGER. You would be wise to listen to it."
+msgstr "Знак гласит ОПАСНОСТЬ. Будет мудро прислушаться к нему."
+
+#: gamelib/scenes/engine.py:118
+msgid "It's one of those glow-in-the-dark signs needed to satisfy the health and safety inspectors."
+msgstr "Это один из тех светящихся в темноте знаков выхода, которые там любят инспекторы СЭС."
+
+#: gamelib/scenes/engine.py:131
+#, python-format
+msgid "The engines are now operational. You havedone a satisfactory job, Prisoner %s."
+msgstr "Двигатели теперь работоспособны. Вы проделали удовлетворительную работу, Заключённый %s."
+
+#: gamelib/scenes/engine.py:139
+msgid "With your improvised helmet, the automatic airlock allows you into the engine room. Even if there wasn't a vacuum it would be eerily quiet."
+msgstr "С вашим импровизированным шлемом, автоматический шлюз допускает вас в двигательный отсек. Даже если бы здесь не было вакуума, тишина бы была жуткой."
+
+#: gamelib/scenes/engine.py:155
+msgid "All systems are go! Or at least the engines are."
+msgstr "Все системы приведены в действие! Ну, по крайней мере, двигатели."
+
+#: gamelib/scenes/engine.py:173
+msgid "A can opener. Looks like you won't be starving"
+msgstr "Открывашка для консервов. Похоже, вы не умрёте с голоду"
+
+#: gamelib/scenes/engine.py:178
+msgid "You pick up the can opener. It looks brand new; the vacuum has kept it in perfect condition."
+msgstr "Вы подбираете открывашку для консервов. Она выглядит совершенно новой; вакуум сохранил её в отличном состоянии."
+
+#: gamelib/scenes/engine.py:200
+msgid "That superconductor looks burned out. It's wedged in there pretty firmly."
+msgstr "Сверхпроводник выглядит сгоревшим. Он впаян достаточно крепко."
+
+#: gamelib/scenes/engine.py:202
+msgid "An empty superconductor socket"
+msgstr "Пустой разъём для сверхпроводника"
+
+#: gamelib/scenes/engine.py:204
+msgid "A working superconductor."
+msgstr "Рабочий сверхпроводник."
+
+#: gamelib/scenes/engine.py:208
+msgid "It's wedged in there pretty firmly, it won't come out."
+msgstr "Он впаян достаточно крепко и не вынимается."
+
+#: gamelib/scenes/engine.py:210
+msgid "You decide that working engines are more important than having a shiny superconductor."
+msgstr "Вы решаете, что иметь работающие двигатели важнее, чем сверкающий сверхпроводник."
+
+#: gamelib/scenes/engine.py:216
+msgid "With leverage, the burned-out superconductor snaps out. You discard it."
+msgstr "С помощью рычага, сгоревший сверхпроводник выскакивает. Вы выбрасываете его."
+
+#: gamelib/scenes/engine.py:221
+msgid "It might help to remove the broken superconductor first"
+msgstr "Возможно, стоит сначала вынуть сгоревший сверхпроводник"
+
+#: gamelib/scenes/engine.py:223
+msgid "You plug in the superconductor, and feel a hum as things kick into life. Unfortunately, it's the wrong size for the socket and just falls out again when you let go."
+msgstr "Вы вставляете сверхпроводник и чувствуете вибрацию, когда вещи начинают оживать. К сожалению, он не подходит к сокету по размеру и выпадает, когда вы убираете руку."
+
+#: gamelib/scenes/engine.py:234
+msgid "The chair's superconductor looks over-specced for this job, but it should work."
+msgstr "Сверхпроводник от кресла кажется слишком специфичным для этой работы, но он работает."
+
+#: gamelib/scenes/engine.py:239
+msgid "It might help to remove the broken superconductor first."
+msgstr "Может стоит сначала удалить сгоревший сверхпроводник."
+
+#: gamelib/scenes/engine.py:258
+msgid "Those are coolant reservoirs. They look empty."
+msgstr "Это резервуары для охладителя. Они пусты."
+
+#: gamelib/scenes/engine.py:259
+msgid "The coolant reservoirs are full."
+msgstr "Резервуары наполнены охладителем."
+
+#: gamelib/scenes/engine.py:279
+msgid "The receptacles for the coolant reservoirs."
+msgstr "Приёмники для резервуаров с охладителем."
+
+#: gamelib/scenes/engine.py:282
+msgid "You stick your finger in the receptacle. It almost gets stuck."
+msgstr "Вы засовываете палец в приёмник. Он почти застревает."
+
+#: gamelib/scenes/engine.py:287
+msgid "Pouring the precious cryo fluid into a container connected to a cracked pipe would be a waste."
+msgstr "Вылить драгоценный охладитель в контейнер, соединённый с треснувшей трубой, было бы расточительством."
+
+#: gamelib/scenes/engine.py:292
+msgid "You fill the reservoirs. The detergent bottle was just big enough, which is handy, because it's sprung a leak."
+msgstr "Вы наполняете резервуары. Бутылка очистителя оказалось достаточно большой, что удобно, поскольку в ней обнаружилась течь."
+
+#: gamelib/scenes/engine.py:340
+msgid "These pipes carry coolant to the superconductors. They feel warm."
+msgstr "Эти трубы подают охладитель к сверхпроводникам. Они тёплые."
+
+#: gamelib/scenes/engine.py:342
+msgid "These pipes carry coolant to the superconductors. They are very cold."
+msgstr "Эти трубы подают охладитель к сверхпроводникам. Они очень холодные."
+
+#: gamelib/scenes/engine.py:368
+msgid "Power lines. They are delivering power to the engines."
+msgstr "Шины питания. По ним подаётся питание на двигатели."
+
+#: gamelib/scenes/engine.py:369
+msgid "Power lines. It looks like they aren't working correctly."
+msgstr "Шины питания. Похоже, они не работают."
+
+#: gamelib/scenes/engine.py:458
+msgid "A gaping hole in the floor of the room. You're guessing that's why there's a vacuum in here."
+msgstr "Сквозная дыра в полу. Вы полагаете что это причина вакуума здесь."
+
+#: gamelib/scenes/engine.py:478
+msgid "The duct tape appears to be holding."
+msgstr "Похоже, клейкая лента держится."
+
+#: gamelib/scenes/engine.py:480
+msgid "The pipe looks cracked and won't hold fluid until it's fixed."
+msgstr "В трубе трещина и она не сможет удерживать жидкость, пока её не починят."
+
+#: gamelib/scenes/engine.py:485
+msgid "The duct tape already there appears to be sufficient."
+msgstr "На этом уже достаточно клейкой ленты."
+
+#: gamelib/scenes/engine.py:490
+msgid "You apply your trusty duct tape to the creak, sealing it."
+msgstr "Вы заклеиваете разрыв вашей надёжной лентой, запечатывая его."
+
+#: gamelib/scenes/engine.py:510
+msgid "A computer console. It's alarmingly close to the engine."
+msgstr "Компьютерная консоль. Она в опасной близости от двигателя."
+
+#: gamelib/scenes/engine.py:567
+msgid "The airlock leads back to the rest of the ship."
+msgstr "Шлюз ведёт к оставшей части корабля."
+
+#: gamelib/scenes/machine.py:31
+msgid "Wires run to all the machines in the room"
+msgstr "Провода идут ко всем приборам в этой комнате"
+
+#: gamelib/scenes/machine.py:51
+msgid "A wiring diagram of some sort"
+msgstr "Диаграмма какого-то соединения проводов."
+
+#: gamelib/scenes/machine.py:54
+msgid "The cables to this power point have been cut"
+msgstr "Кабели к этой точке питания были обрезаны"
+
+#: gamelib/scenes/machine.py:57
+msgid "All the machines run off this powerpoint"
+msgstr "Все приборы птаются из этой точки"
+
+#: gamelib/scenes/machine.py:60
+msgid "An impressive looking laser drill press"
+msgstr "Внушительно выглядящая лазерная дрель"
+
+#: gamelib/scenes/machine.py:73
+msgid "The block for the laser drill press"
+msgstr "Блок для лазерной дрели"
+
+#: gamelib/scenes/machine.py:119
+msgid "You really don't want to put your hand in there."
+msgstr "Вы точно не хотите класть туда свою руку."
+
+#: gamelib/scenes/machine.py:124
+msgid "There is already a can in the welder."
+msgstr "В сварочной машине уже есть банка."
+
+#: gamelib/scenes/machine.py:128
+msgid "You carefully place the can in the laser welder."
+msgstr "Вы осторожно кладёте банку в лазерную сварку."
+
+#: gamelib/scenes/machine.py:133
+msgid "There is already a tube fragment in the welder."
+msgstr "В сварочной машине уже есть фрагмент трубы."
+
+#: gamelib/scenes/machine.py:137
+msgid "You carefully place the tube fragments in the laser welder."
+msgstr "Вы осторожно кладёте фрагмент трубы в лазерную сварку."
+
+#: gamelib/scenes/machine.py:142
+msgid "This is a Smith and Wesson 'zOMG' class high-precision laser welder."
+msgstr "Это высокоточная лазерная сварочная машина Смита и Вессона класса 'zOMG'."
+
+#: gamelib/scenes/machine.py:144
+msgid "The laser welder looks hungry, somehow."
+msgstr "Лазерная сварка выглядит какой-то голодной."
+
+#: gamelib/scenes/machine.py:146
+msgid " It currently contains an empty can."
+msgstr " Сейчас она содержит пустую банку."
+
+#: gamelib/scenes/machine.py:148
+msgid " It currently contains a tube fragment."
+msgstr " Сейчас она содержит фрагмент трубы."
+
+#: gamelib/scenes/machine.py:150
+msgid "The laser welder looks expectant. "
+msgstr "Лазерная сварка выглядит выжидающей. "
+
+#: gamelib/scenes/machine.py:152
+msgid " It currently contains an empty can and a tube fragment."
+msgstr " Сейчас она содержит пустую банку и фрагмент трубы."
+
+#: gamelib/scenes/machine.py:169
+msgid "The laser welder doesn't currently contain anything weldable."
+msgstr "Лазерная сварка сейчас не содержит ничего, что можно сварить."
+
+#: gamelib/scenes/machine.py:172
+msgid "The laser welder needs something to weld the can to."
+msgstr "Лазерной сварке нужно что-нибудь, к чему можно приварить банку."
+
+#: gamelib/scenes/machine.py:174
+msgid "The laser welder needs something to weld the tube fragments to."
+msgstr "Лазерной сварке нужно что-нибудь, к чему можно приварить фрагменты трубы."
+
+#: gamelib/scenes/machine.py:180
+msgid "With high-precision spitzensparken, you weld together a second pipe. You bundle the two pipes together."
+msgstr "С высокоточным искрением, вы свариваете вторую трубу. Вы кладёте обе трубы вместе."
+
+#: gamelib/scenes/machine.py:185
+msgid "With high-precision spitzensparken, you create yet another pipe. You store it with the other two."
+msgstr "С высокоточным искрением, вы создаёте ещё одну трубу. Вы добавляете её к первым двум."
+
+#: gamelib/scenes/machine.py:193
+msgid "With high-precision spitzensparken, the can and tube are welded into a whole greater than the sum of the parts."
+msgstr "С высокоточным искрением, банка и труба свариваются в целое, большее суммы своих частей."
+
+#: gamelib/scenes/machine.py:209
+msgid "The power lights pulse expectantly."
+msgstr "Огни питания выжидающе пульсируют."
+
+#: gamelib/scenes/machine.py:247
+msgid "It looks like it eats fingers. Perhaps a different approach is in order?"
+msgstr "Похоже, эта машина ест пальцы. Может нужен другой подход?"
+
+#: gamelib/scenes/machine.py:251
+msgid "After much delicate grinding and a few close calls with various body parts, the titanium femur now resembles a machete more than a bone. Nice and sharp, too."
+msgstr "После достаточно затруднительной заточки, пару раз чуть не стоившей вам некоторых частей тела, титановое бедро теперь больше напоминает мачете, чем кость. Прелестное и острое."
+
+#: gamelib/scenes/machine.py:257
+msgid "A pretty ordinary, albeit rather industrial, grinding machine."
+msgstr "Вполне обычная, хотя и вполне промышленная, шлифовальная машина."
+
+#: gamelib/scenes/machine.py:280
+msgid "Ah! The ship's instruction manual. You'd feel better if the previous owner wasn't lying next to it with a gaping hole in his rib cage."
+msgstr "Ах! Инструкция по обращению с кораблём. Вы бы почувствовали себя лучше, если бы предыдущий владелец не лежал рядом с ней со сквозной дырой в грудной клетке."
+
+#: gamelib/scenes/map.py:42
+msgid "Under the terms of the emergency conscription act, I have downloaded the ship's schematics to your neural implant to help you navigate around the ship."
+msgstr "В соответствии с предписанием при чрезвычайных ситуациях, я загрузил схему корабля в ваш невральный имплантант, чтобы помочь вам ориентироваться на корабле."
+
+#: gamelib/scenes/map.py:47
+#, python-format
+msgid "Prisoner %s, you are a class 1 felon. Obtaining access to the ship's schematics constitutes a level 2 offence and carries a minimal penalty of an additional 3 years on your sentence."
+msgstr "Заключённый %s, вы нарушитель класса 1. Получение доступа к схемам корабля является преступлением уровня 2 и карается как минимум 3 дополнительными годами к вашему сроку."
+
+#: gamelib/scenes/map.py:129
+msgid "The airlock refuses to open. The automated voice says: \"Hull breach beyond this door. Personnel must be equipped for vacuum before entry.\""
+msgstr "Шлюз не открывается. Голос автомата произносит: «За этой дверью повреждён корпус. Перед входом персонал должен быть экипирован для вакуума.»"
+
+#: gamelib/scenes/map.py:184
+msgid "You look in the door, but just see empty space: that room appears to have been obliterated by meteors."
+msgstr "Вы смотрете в дверь, но видите только пустое пространство: эта комната была уничтожена метеоритами."
+
+#: gamelib/scenes/map.py:201
+msgid "Peering in through the window, you see that the entire chamber is overgrown with giant broccoli. It would take you years to cut a path through that."
+msgstr "Взглянув в окно, вы видите, что вся комната заросла гигантской брокколи. Вам потребуются годы, чтобы прорубить через неё дорогу."
+
+#: gamelib/scenes/mess.py:38
+msgid "A large collection of rusted, useless cans."
+msgstr "Большая коллекция ржавых бесполезных банок."
+
+#: gamelib/scenes/mess.py:44
+msgid "An impressively overgrown broccoli."
+msgstr "Впечатляюще разросшаяся брокколи."
+
+#: gamelib/scenes/mess.py:55
+msgid "You bang the cans together. It sounds like two cans being banged together."
+msgstr "Вы стучите банками друг о друга. Звучит так, словно стучат двумя банками друг о друга."
+
+#: gamelib/scenes/mess.py:64
+msgid "You'd mangle it beyond usefulness."
+msgstr "Вы раскромсаете их так, что их невозможно будет использовать."
+
+#: gamelib/scenes/mess.py:70
+msgid "You open both ends of the can, discarding the hideous contents."
+msgstr "Вы открываете оба конца банки, вытряхивая отвратительное содержимое."
+
+#: gamelib/scenes/mess.py:80
+msgid "Flattening the can doesn't look like a useful thing to do."
+msgstr "Расплющивание банки не кажется полезным занятием."
+
+#: gamelib/scenes/mess.py:83
+msgid "There's nothing left to open on this can"
+msgstr "На этой банке больше нечего открыть"
+
+#: gamelib/scenes/mess.py:96
+msgid "You club the can with the femur. The can gets dented, but doesn't open."
+msgstr "Вы долбите банку бедром. Банка становится помятой, но не открывается."
+
+#: gamelib/scenes/mess.py:106
+msgid "You club the can with the femur. The dents shift around, but it still doesn't open."
+msgstr "Вы долбите банку бедром. Она вся покрывается вмятинами, но всё же не открывается."
+
+#: gamelib/scenes/mess.py:137
+msgid "Best before a long time in the past. Better not eat these."
+msgstr "Срок годности давно прошёл. Лучше не есть это."
+
+#: gamelib/scenes/mess.py:138
+msgid "Mmmm. Nutritious bacteria stew."
+msgstr "Ммммм. Питательная тушёнка с бактериями."
+
+#: gamelib/scenes/mess.py:139
+msgid "Candied silkworms. Who stocked this place?!"
+msgstr "Засахаренные черви. Кто снабжает это место?!"
+
+#: gamelib/scenes/mess.py:142
+msgid "The rest of the cans are rusted beyond usefulness."
+msgstr "Оставшиеся банки слишком ржавые, чтобы их использовать."
+
+#: gamelib/scenes/mess.py:145
+msgid "The contents of these cans look synthetic."
+msgstr "Содержимое этих банок кажется искусственным."
+
+#: gamelib/scenes/mess.py:167
+msgid "The broccoli seems to have become entangled with something."
+msgstr "Похоже, брокколи что-то оплела."
+
+#: gamelib/scenes/mess.py:169
+msgid "These broken pipes look important."
+msgstr "Эти сломанные трубы выглядят очень важными."
+
+#: gamelib/scenes/mess.py:171
+msgid "The pipes have been repaired but are the repairs aren't airtight, yet"
+msgstr "Трубопровод починен, но всё ещё не герметичен"
+
+#: gamelib/scenes/mess.py:173
+msgid "Your fix looks like it's holding up well."
+msgstr "Похоже, ваши заплатки хорошо держатся."
+
+#: gamelib/scenes/mess.py:179
+msgid "With a flurry of disgusting mutant vegetable chunks, you clear the overgrown broccoli away from the access panel and reveal some broken tubes. They look important."
+msgstr "В туче отвратительных кусков мутировавшего овоща, вы расчищаете панель доступа от брокколи-переростка, и освобождаете некоторые сломанные трубы. Они выглядят важными."
+
+#: gamelib/scenes/mess.py:185
+msgid "It looks broken enough already."
+msgstr "Они уже достаточно сломаны."
+
+#: gamelib/scenes/mess.py:187
+msgid "Cutting holes won't repair the leaks."
+msgstr "Прорубание дыр не починит течи."
+
+#: gamelib/scenes/mess.py:189
+msgid "After all that effort fixing it, chopping it to bits doesn't seem very smart."
+msgstr "После всего труда, затраченного на их восстановление, порубить их на кусочки — не очень умный поступок."
+
+#: gamelib/scenes/mess.py:194
+#: gamelib/scenes/mess.py:207
+msgid "It would get lost in the fronds."
+msgstr "Это потеряется в зарослях."
+
+#: gamelib/scenes/mess.py:201
+msgid "The pipes slot neatly into place, but don't make an airtight seal. One of the pipes has cracked slightly as well."
+msgstr "Трубы с трудом вставляются на место и крепление не герметично. К тому же одна из труб треснула."
+
+#: gamelib/scenes/mess.py:209
+msgid "There's quite enough tape on the ducting already."
+msgstr "На трубопроводе уже вполне достаточно ленты."
+
+#: gamelib/scenes/mess.py:216
+msgid "It takes quite a lot of tape, but eventually everything is airtight and ready to hold pressure. Who'd've thought duct tape could actually be used to tape ducts?"
+msgstr "На это уходит довольно много ленты, но в конце концов всё герметично и способно выдержать давление. Кто бы мог подумать, что трубопроводная лента может быть использована для обмотки труб?"
+
+#: gamelib/scenes/mess.py:222
+msgid "The mutant broccoli resists your best efforts."
+msgstr "Мутировавшая брокколи сопротивляется вашим лучшим попыткам."
+
+#: gamelib/scenes/mess.py:224
+msgid "Shoving the broken pipes around doesn't help much."
+msgstr "Расталкивание сломанных труб не очень поможет."
+
+#: gamelib/scenes/mess.py:226
+msgid "Do you really want to hold it together for the rest of the voyage?"
+msgstr "Вы действительно хотите держать их вместе всю оставшуюся часть полёта?"
+
+#: gamelib/scenes/mess.py:229
+#, python-format
+msgid "You don't find any leaks. Good job, Prisoner %s."
+msgstr "Вы не находите никаких утечек. Отличная работа, Заключённый %s."
+
+#: gamelib/scenes/mess.py:288
+msgid "The remaining bottles leak."
+msgstr "Оставшиеся бутылки протекают."
+
+#: gamelib/scenes/mess.py:292
+msgid "You pick up an empty dishwashing liquid bottle. You can't find any sponges."
+msgstr "Вы подбираете пусую бутылку из-под чистящего средства. Вы не можете найти губку."
+
+#: gamelib/scenes/mess.py:295
+msgid "Empty plastic containers. They used to hold dishwasher soap."
+msgstr "Пустые пластиковые контейнеры. В них хранилось средство для мытья посуды."
+
+#: gamelib/scenes/game_widgets.py:51
+msgid "A security camera watches over the room"
+msgstr "Камера безопасности следит за комнатой"
+
+#: gamelib/scenes/game_widgets.py:53
+msgid "The security camera is currently offline but should be working soon"
+msgstr "Камера безопасности сейчас отключена, но скоро заработает"
+
+#: gamelib/scenes/game_widgets.py:55
+msgid "The security camera is powered down"
+msgstr "Камера безопасности отключена"
+
+#: gamelib/scenes/game_widgets.py:63
+msgid "3D scene reconstruction failed. Critical error. Entering emergency shutdown."
+msgstr "Реконструция 3D-сцены не удалась. Критическая ошибка. Начинаю аварийное отключение."
+
+#~ msgid "A control panel. It seems dead."
+#~ msgstr "Панель управления. Похоже, она не работает."
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/po/suspended-sentence.pot	Sat Jan 26 16:57:33 2013 +0200
@@ -0,0 +1,950 @@
+# SOME DESCRIPTIVE TITLE.
+# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
+# This file is distributed under the same license as the PACKAGE package.
+# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
+#
+#, fuzzy
+msgid ""
+msgstr ""
+"Project-Id-Version: PACKAGE VERSION\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2011-03-08 14:36+0200\n"
+"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
+"Language-Team: LANGUAGE <LL@li.org>\n"
+"Language: \n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=CHARSET\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+#: gamelib/widgets.py:175
+msgid "Quit Game"
+msgstr ""
+
+#: gamelib/widgets.py:176
+msgid "Exit to Main Menu"
+msgstr ""
+
+#: gamelib/gamescreen.py:146
+msgid "Close"
+msgstr ""
+
+#: gamelib/gamescreen.py:218
+msgid "Menu"
+msgstr ""
+
+#: gamelib/scenes/bridge.py:63
+msgid "The brightly coloured wires contrast with the drab walls."
+msgstr ""
+
+#: gamelib/scenes/bridge.py:66
+msgid "\"Dammit JIM, I'm a doctor, not an engineer!\""
+msgstr ""
+
+#: gamelib/scenes/bridge.py:72
+msgid "A skeleton hangs improbably from the wires."
+msgstr ""
+
+#: gamelib/scenes/bridge.py:117
+msgid "You can't break the duraplastic screen."
+msgstr ""
+
+#: gamelib/scenes/bridge.py:120
+msgid "Scratching the screen won't help you."
+msgstr ""
+
+#: gamelib/scenes/bridge.py:123
+msgid "The main bridge computer screen."
+msgstr ""
+
+#: gamelib/scenes/bridge.py:146
+msgid ""
+"A top of the line Massage-o-Matic Captain's Executive Command Chair. It's "
+"massaging a skeleton."
+msgstr ""
+
+#: gamelib/scenes/bridge.py:148
+msgid "The chair won't work any more, it has no power."
+msgstr ""
+
+#: gamelib/scenes/bridge.py:197
+msgid "A stethoscope hangs from the neck of the skeleton."
+msgstr ""
+
+#: gamelib/scenes/bridge.py:204
+msgid ""
+"You pick up the stethoscope and verify that the doctor's heart has stopped. "
+"Probably a while ago."
+msgstr ""
+
+#: gamelib/scenes/bridge.py:225
+msgid ""
+"You rip off a piece of duct tape and stick it on the superconductor. It "
+"almost sticks to itself, but you successfully avoid disaster."
+msgstr ""
+
+#: gamelib/scenes/bridge.py:245
+msgid "The superconductor module unclips easily."
+msgstr ""
+
+#: gamelib/scenes/bridge.py:246
+#, python-format
+msgid ""
+"Prisoner %s. That chair you've destroyed was property of the ship's captain. "
+"You will surely be punished."
+msgstr ""
+
+#: gamelib/scenes/bridge.py:278
+msgid "The lights flash in interesting patterns."
+msgstr ""
+
+#: gamelib/scenes/bridge.py:279
+msgid "The flashing lights don't mean anything to you."
+msgstr ""
+
+#: gamelib/scenes/bridge.py:280
+msgid "The console lights flash and flicker."
+msgstr ""
+
+#: gamelib/scenes/bridge.py:323
+msgid "The sign reads 'Warning: Authorized Techinicians Only'."
+msgstr ""
+
+#: gamelib/scenes/bridge.py:329
+msgid "You are unable to open the panel with your bare hands."
+msgstr ""
+
+#: gamelib/scenes/bridge.py:334
+msgid "You unplug various important-looking wires."
+msgstr ""
+
+#: gamelib/scenes/bridge.py:343
+msgid "Using the machete, you lever the panel off."
+msgstr ""
+
+#: gamelib/scenes/bridge.py:348
+msgid "You smash various delicate components with the machete."
+msgstr ""
+
+#: gamelib/scenes/bridge.py:352
+msgid "You feel a shock from the panel."
+msgstr ""
+
+#: gamelib/scenes/bridge.py:353
+#, python-format
+msgid ""
+"Prisoner %s. Please step away from the panel. You are not an authorized "
+"technician."
+msgstr ""
+
+#: gamelib/scenes/bridge.py:451
+msgid "You are not authorized to change the destination."
+msgstr ""
+
+#: gamelib/scenes/bridge.py:453
+msgid "There's no good reason to choose to go to the penal colony."
+msgstr ""
+
+#: gamelib/scenes/bridge.py:455
+msgid ""
+"You could change the destination, but when JIM recovers, it'll just get "
+"reset."
+msgstr ""
+
+#: gamelib/scenes/bridge.py:457
+msgid "You change the destination."
+msgstr ""
+
+#: gamelib/scenes/crew_quarters.py:31
+msgid "The plant is doing surprisingly well for centuries of neglect"
+msgstr ""
+
+#: gamelib/scenes/crew_quarters.py:34
+msgid "A picture of a cat labelled 'Clementine'"
+msgstr ""
+
+#: gamelib/scenes/crew_quarters.py:73
+msgid "Duct tape. It'll stick to everything except ducts, apparently."
+msgstr ""
+
+#: gamelib/scenes/crew_quarters.py:75
+msgid ""
+"The perfectly balanced door swings frictionlessly to and fro. What "
+"craftsmanship!"
+msgstr ""
+
+#: gamelib/scenes/crew_quarters.py:77
+msgid ""
+"The safe is locked. This might be an interesting challenge, if suitable "
+"equipment can be found."
+msgstr ""
+
+#: gamelib/scenes/crew_quarters.py:82
+msgid "It's already unlocked. There's no more challenge."
+msgstr ""
+
+#: gamelib/scenes/crew_quarters.py:87
+msgid ""
+"Even after centuries of neglect, the tumblers slide almost silently into "
+"place. Turns out the combination was '1 2 3 4 5'. An idiot must keep his "
+"luggage in here."
+msgstr ""
+
+#: gamelib/scenes/crew_quarters.py:91
+#, python-format
+msgid ""
+"Prisoner %s, you have been observed committing a felony violation. This will "
+"go onto your permanent record, and your sentence may be extended by up to "
+"twenty years."
+msgstr ""
+
+#: gamelib/scenes/crew_quarters.py:96
+msgid "Ah, a vintage Knoxx & Co. model QR3. Quaint, but reasonably secure."
+msgstr ""
+
+#: gamelib/scenes/crew_quarters.py:117
+msgid ""
+"What's the point of lugging around a very dead fish and a kilogram or so of "
+"sand?"
+msgstr ""
+
+#: gamelib/scenes/crew_quarters.py:122
+msgid "The fishbowl is useful, but its contents aren't."
+msgstr ""
+
+#: gamelib/scenes/crew_quarters.py:126
+msgid "This fishbowl looks exactly like an old science fiction space helmet."
+msgstr ""
+
+#: gamelib/scenes/crew_quarters.py:128
+msgid "An evicted dead fish and some sand lie forlornly on the table"
+msgstr ""
+
+#: gamelib/scenes/crew_quarters.py:142
+msgid ""
+"You duct tape the edges of the helmet. The seal is crude, but it will serve "
+"as a workable helmet if needed."
+msgstr ""
+
+#: gamelib/scenes/crew_quarters.py:189
+msgid "This poster will go nicely on your bedroom wall."
+msgstr ""
+
+#: gamelib/scenes/crew_quarters.py:192
+msgid "A paradoxical poster hangs below the security camera."
+msgstr ""
+
+#: gamelib/scenes/cryo.py:53
+msgid "These pipes carry cooling fluid to the cryo units."
+msgstr ""
+
+#: gamelib/scenes/cryo.py:64
+msgid "An empty cryo chamber."
+msgstr ""
+
+#: gamelib/scenes/cryo.py:65
+msgid "Prisoner 81E4-C8900480E635. Embezzlement. 20 years."
+msgstr ""
+
+#: gamelib/scenes/cryo.py:74 gamelib/scenes/cryo.py:93
+msgid ""
+"A working cryo chamber. The frosted glass obscures the details of the "
+"occupant."
+msgstr ""
+
+#: gamelib/scenes/cryo.py:75
+msgid "Prisoner 9334-CE1EB0243BAB. Murder. 40 years."
+msgstr ""
+
+#: gamelib/scenes/cryo.py:84
+msgid "A broken cryo chamber. The skeleton inside has been picked clean."
+msgstr ""
+
+#: gamelib/scenes/cryo.py:85
+msgid ""
+"Prisoner BFBC-8BF4C6B7492B. Importing illegal alien biomatter. 15 years."
+msgstr ""
+
+#: gamelib/scenes/cryo.py:94
+msgid "Prisoner B520-99495B8C41CE. Copyright infringement. 60 years."
+msgstr ""
+
+#: gamelib/scenes/cryo.py:101
+msgid "An empty cryo unit. Recently filled by you."
+msgstr ""
+
+#: gamelib/scenes/cryo.py:102
+#, python-format
+msgid "Prisoner %s. Safecracking, grand larceny. 30 years."
+msgstr ""
+
+#: gamelib/scenes/cryo.py:109 gamelib/scenes/cryo.py:118
+msgid "An empty cryo unit."
+msgstr ""
+
+#: gamelib/scenes/cryo.py:110
+msgid "Prisoner 83F1-CE32D3234749. Spamming. 5 years."
+msgstr ""
+
+#: gamelib/scenes/cryo.py:119
+msgid "Prisoner A455-9DF9F43C43E5. Medical malpractice. 10 years."
+msgstr ""
+
+#: gamelib/scenes/cryo.py:135
+#, python-format
+msgid ""
+"Greetings, Prisoner %s. I am the Judicial Incarceration Monitor. You have "
+"been woken early under the terms of the emergency conscription act to assist "
+"with repairs to the ship. Your behaviour during this time will be noted on "
+"your record and will be relayed to prison officials when we reach the "
+"destination. Please report to the bridge."
+msgstr ""
+
+#: gamelib/scenes/cryo.py:165
+msgid ""
+"It takes more effort than one would expect, but eventually the pipe is "
+"separated from the wall."
+msgstr ""
+
+#: gamelib/scenes/cryo.py:171
+#, python-format
+msgid ""
+"Prisoner %s. Vandalism is an offence punishable by a minimum of an "
+"additional 6 months to your sentence."
+msgstr ""
+
+#: gamelib/scenes/cryo.py:181 gamelib/scenes/cryo.py:211
+msgid "These pipes aren't attached to the wall very solidly."
+msgstr ""
+
+#: gamelib/scenes/cryo.py:186
+msgid "These pipes carry cooling fluid to empty cryo units."
+msgstr ""
+
+#: gamelib/scenes/cryo.py:187
+msgid "There used to be a pipe carrying cooling fluid here."
+msgstr ""
+
+#: gamelib/scenes/cryo.py:204
+msgid ""
+"These pipes carry fluid to the working cryo units. Chopping them down "
+"doesn't seem sensible."
+msgstr ""
+
+#: gamelib/scenes/cryo.py:214
+msgid "These pipes carry cooling fluid to the working cryo units."
+msgstr ""
+
+#: gamelib/scenes/cryo.py:286
+msgid ""
+"You hit the chamber that used to hold this very leg. Nothing happens as a "
+"result."
+msgstr ""
+
+#: gamelib/scenes/cryo.py:291
+msgid "A broken cryo chamber, with a poor unfortunate corpse inside."
+msgstr ""
+
+#: gamelib/scenes/cryo.py:292
+msgid "A broken cryo chamber. The corpse inside is missing a leg."
+msgstr ""
+
+#: gamelib/scenes/cryo.py:313
+msgid "You bang on the chamber with the titanium femur. Nothing much happens."
+msgstr ""
+
+#: gamelib/scenes/cryo.py:314
+msgid "Hitting the cryo unit with the femur doesn't achieve anything."
+msgstr ""
+
+#: gamelib/scenes/cryo.py:315
+msgid "You hit the chamber with the femur. Nothing happens."
+msgstr ""
+
+#: gamelib/scenes/cryo.py:339
+msgid ""
+"You wedge the titanium femur into the chain and twist. With a satisfying "
+"*snap*, the chain breaks and the door opens."
+msgstr ""
+
+#: gamelib/scenes/cryo.py:341
+msgid ""
+"You bang on the door with the titanium femur. It makes a clanging sound."
+msgstr ""
+
+#: gamelib/scenes/cryo.py:344
+msgid "You wave the femur in the doorway. Nothing happens."
+msgstr ""
+
+#: gamelib/scenes/cryo.py:350
+msgid ""
+"It moves slightly and then stops. A chain on the other side is preventing it "
+"from opening completely."
+msgstr ""
+
+#: gamelib/scenes/cryo.py:368 gamelib/scenes/game_widgets.py:26
+msgid "An open doorway leads to the rest of the ship."
+msgstr ""
+
+#: gamelib/scenes/cryo.py:370
+msgid ""
+"A rusty door. It can't open all the way because of a chain on the other side."
+msgstr ""
+
+#: gamelib/scenes/cryo.py:372
+msgid "A rusty door. It is currently closed."
+msgstr ""
+
+#: gamelib/scenes/cryo.py:393
+msgid "Hitting it with the leg accomplishes nothing."
+msgstr ""
+
+#: gamelib/scenes/cryo.py:396
+msgid "A computer terminal, with some text on it."
+msgstr ""
+
+#: gamelib/scenes/cryo.py:414
+msgid ""
+"The skeletal occupant of this cryo unit has an artificial femur made of "
+"titanium. You take it."
+msgstr ""
+
+#: gamelib/scenes/cryo.py:417
+msgid "This femur looks synthetic."
+msgstr ""
+
+#: gamelib/scenes/cryo.py:432
+msgid "The plaque is welded to the unit. You can't shift it."
+msgstr ""
+
+#: gamelib/scenes/cryo.py:435
+msgid "'Prisoner 98CC-764E646391EE. War crimes. 45 years."
+msgstr ""
+
+#: gamelib/scenes/cryo.py:459
+msgid "Coolant leaks disturbingly from the bulkheads."
+msgstr ""
+
+#: gamelib/scenes/cryo.py:462
+msgid "It's gooey"
+msgstr ""
+
+#: gamelib/scenes/cryo.py:468
+msgid "You scoop up some coolant and fill the bottle."
+msgstr ""
+
+#: gamelib/scenes/engine.py:43
+msgid "Dead. Those cans must have been past their sell-by date."
+msgstr ""
+
+#: gamelib/scenes/engine.py:50
+msgid "Superconductors. The engines must be power hogs."
+msgstr ""
+
+#: gamelib/scenes/engine.py:58
+msgid "A gaping hole in the floor of the room. It is clearly irreparable."
+msgstr ""
+
+#: gamelib/scenes/engine.py:68
+msgid ""
+"Empty chocolate-covered bacon cans? Poor guy, he must have found them "
+"irresistible."
+msgstr ""
+
+#: gamelib/scenes/engine.py:74
+msgid "The engines. They don't look like they are working."
+msgstr ""
+
+#: gamelib/scenes/engine.py:80
+msgid ""
+"A burned-out laser cutter. It may be responsible for the hole in the floor."
+msgstr ""
+
+#: gamelib/scenes/engine.py:86
+msgid "The main fuel line for the engines."
+msgstr ""
+
+#: gamelib/scenes/engine.py:106
+msgid ""
+"The spare fuel line. If something went wrong with the main one, you would "
+"hook that one up."
+msgstr ""
+
+#: gamelib/scenes/engine.py:112
+msgid "The sign says DANGER. You would be wise to listen to it."
+msgstr ""
+
+#: gamelib/scenes/engine.py:118
+msgid ""
+"It's one of those glow-in-the-dark signs needed to satisfy the health and "
+"safety inspectors."
+msgstr ""
+
+#: gamelib/scenes/engine.py:131
+#, python-format
+msgid ""
+"The engines are now operational. You havedone a satisfactory job, Prisoner "
+"%s."
+msgstr ""
+
+#: gamelib/scenes/engine.py:139
+msgid ""
+"With your improvised helmet, the automatic airlock allows you into the "
+"engine room. Even if there wasn't a vacuum it would be eerily quiet."
+msgstr ""
+
+#: gamelib/scenes/engine.py:155
+msgid "All systems are go! Or at least the engines are."
+msgstr ""
+
+#: gamelib/scenes/engine.py:173
+msgid "A can opener. Looks like you won't be starving"
+msgstr ""
+
+#: gamelib/scenes/engine.py:178
+msgid ""
+"You pick up the can opener. It looks brand new; the vacuum has kept it in "
+"perfect condition."
+msgstr ""
+
+#: gamelib/scenes/engine.py:200
+msgid ""
+"That superconductor looks burned out. It's wedged in there pretty firmly."
+msgstr ""
+
+#: gamelib/scenes/engine.py:202
+msgid "An empty superconductor socket"
+msgstr ""
+
+#: gamelib/scenes/engine.py:204
+msgid "A working superconductor."
+msgstr ""
+
+#: gamelib/scenes/engine.py:208
+msgid "It's wedged in there pretty firmly, it won't come out."
+msgstr ""
+
+#: gamelib/scenes/engine.py:210
+msgid ""
+"You decide that working engines are more important than having a shiny "
+"superconductor."
+msgstr ""
+
+#: gamelib/scenes/engine.py:216
+msgid "With leverage, the burned-out superconductor snaps out. You discard it."
+msgstr ""
+
+#: gamelib/scenes/engine.py:221
+msgid "It might help to remove the broken superconductor first"
+msgstr ""
+
+#: gamelib/scenes/engine.py:223
+msgid ""
+"You plug in the superconductor, and feel a hum as things kick into life. "
+"Unfortunately, it's the wrong size for the socket and just falls out again "
+"when you let go."
+msgstr ""
+
+#: gamelib/scenes/engine.py:234
+msgid ""
+"The chair's superconductor looks over-specced for this job, but it should "
+"work."
+msgstr ""
+
+#: gamelib/scenes/engine.py:239
+msgid "It might help to remove the broken superconductor first."
+msgstr ""
+
+#: gamelib/scenes/engine.py:258
+msgid "Those are coolant reservoirs. They look empty."
+msgstr ""
+
+#: gamelib/scenes/engine.py:259
+msgid "The coolant reservoirs are full."
+msgstr ""
+
+#: gamelib/scenes/engine.py:279
+msgid "The receptacles for the coolant reservoirs."
+msgstr ""
+
+#: gamelib/scenes/engine.py:282
+msgid "You stick your finger in the receptacle. It almost gets stuck."
+msgstr ""
+
+#: gamelib/scenes/engine.py:287
+msgid ""
+"Pouring the precious cryo fluid into a container connected to a cracked pipe "
+"would be a waste."
+msgstr ""
+
+#: gamelib/scenes/engine.py:292
+msgid ""
+"You fill the reservoirs. The detergent bottle was just big enough, which is "
+"handy, because it's sprung a leak."
+msgstr ""
+
+#: gamelib/scenes/engine.py:340
+msgid "These pipes carry coolant to the superconductors. They feel warm."
+msgstr ""
+
+#: gamelib/scenes/engine.py:342
+msgid "These pipes carry coolant to the superconductors. They are very cold."
+msgstr ""
+
+#: gamelib/scenes/engine.py:368
+msgid "Power lines. They are delivering power to the engines."
+msgstr ""
+
+#: gamelib/scenes/engine.py:369
+msgid "Power lines. It looks like they aren't working correctly."
+msgstr ""
+
+#: gamelib/scenes/engine.py:458
+msgid ""
+"A gaping hole in the floor of the room. You're guessing that's why there's a "
+"vacuum in here."
+msgstr ""
+
+#: gamelib/scenes/engine.py:478
+msgid "The duct tape appears to be holding."
+msgstr ""
+
+#: gamelib/scenes/engine.py:480
+msgid "The pipe looks cracked and won't hold fluid until it's fixed."
+msgstr ""
+
+#: gamelib/scenes/engine.py:485
+msgid "The duct tape already there appears to be sufficient."
+msgstr ""
+
+#: gamelib/scenes/engine.py:490
+msgid "You apply your trusty duct tape to the creak, sealing it."
+msgstr ""
+
+#: gamelib/scenes/engine.py:510
+msgid "A computer console. It's alarmingly close to the engine."
+msgstr ""
+
+#: gamelib/scenes/engine.py:567
+msgid "The airlock leads back to the rest of the ship."
+msgstr ""
+
+#: gamelib/scenes/machine.py:31
+msgid "Wires run to all the machines in the room"
+msgstr ""
+
+#: gamelib/scenes/machine.py:51
+msgid "A wiring diagram of some sort"
+msgstr ""
+
+#: gamelib/scenes/machine.py:54
+msgid "The cables to this power point have been cut"
+msgstr ""
+
+#: gamelib/scenes/machine.py:57
+msgid "All the machines run off this powerpoint"
+msgstr ""
+
+#: gamelib/scenes/machine.py:60
+msgid "An impressive looking laser drill press"
+msgstr ""
+
+#: gamelib/scenes/machine.py:73
+msgid "The block for the laser drill press"
+msgstr ""
+
+#: gamelib/scenes/machine.py:119
+msgid "You really don't want to put your hand in there."
+msgstr ""
+
+#: gamelib/scenes/machine.py:124
+msgid "There is already a can in the welder."
+msgstr ""
+
+#: gamelib/scenes/machine.py:128
+msgid "You carefully place the can in the laser welder."
+msgstr ""
+
+#: gamelib/scenes/machine.py:133
+msgid "There is already a tube fragment in the welder."
+msgstr ""
+
+#: gamelib/scenes/machine.py:137
+msgid "You carefully place the tube fragments in the laser welder."
+msgstr ""
+
+#: gamelib/scenes/machine.py:142
+msgid "This is a Smith and Wesson 'zOMG' class high-precision laser welder."
+msgstr ""
+
+#: gamelib/scenes/machine.py:144
+msgid "The laser welder looks hungry, somehow."
+msgstr ""
+
+#: gamelib/scenes/machine.py:146
+msgid " It currently contains an empty can."
+msgstr ""
+
+#: gamelib/scenes/machine.py:148
+msgid " It currently contains a tube fragment."
+msgstr ""
+
+#: gamelib/scenes/machine.py:150
+msgid "The laser welder looks expectant. "
+msgstr ""
+
+#: gamelib/scenes/machine.py:152
+msgid " It currently contains an empty can and a tube fragment."
+msgstr ""
+
+#: gamelib/scenes/machine.py:169
+msgid "The laser welder doesn't currently contain anything weldable."
+msgstr ""
+
+#: gamelib/scenes/machine.py:172
+msgid "The laser welder needs something to weld the can to."
+msgstr ""
+
+#: gamelib/scenes/machine.py:174
+msgid "The laser welder needs something to weld the tube fragments to."
+msgstr ""
+
+#: gamelib/scenes/machine.py:180
+msgid ""
+"With high-precision spitzensparken, you weld together a second pipe. You "
+"bundle the two pipes together."
+msgstr ""
+
+#: gamelib/scenes/machine.py:185
+msgid ""
+"With high-precision spitzensparken, you create yet another pipe. You store "
+"it with the other two."
+msgstr ""
+
+#: gamelib/scenes/machine.py:193
+msgid ""
+"With high-precision spitzensparken, the can and tube are welded into a whole "
+"greater than the sum of the parts."
+msgstr ""
+
+#: gamelib/scenes/machine.py:209
+msgid "The power lights pulse expectantly."
+msgstr ""
+
+#: gamelib/scenes/machine.py:247
+msgid ""
+"It looks like it eats fingers. Perhaps a different approach is in order?"
+msgstr ""
+
+#: gamelib/scenes/machine.py:251
+msgid ""
+"After much delicate grinding and a few close calls with various body parts, "
+"the titanium femur now resembles a machete more than a bone. Nice and sharp, "
+"too."
+msgstr ""
+
+#: gamelib/scenes/machine.py:257
+msgid "A pretty ordinary, albeit rather industrial, grinding machine."
+msgstr ""
+
+#: gamelib/scenes/machine.py:280
+msgid ""
+"Ah! The ship's instruction manual. You'd feel better if the previous owner "
+"wasn't lying next to it with a gaping hole in his rib cage."
+msgstr ""
+
+#: gamelib/scenes/map.py:42
+msgid ""
+"Under the terms of the emergency conscription act, I have downloaded the "
+"ship's schematics to your neural implant to help you navigate around the "
+"ship."
+msgstr ""
+
+#: gamelib/scenes/map.py:47
+#, python-format
+msgid ""
+"Prisoner %s, you are a class 1 felon. Obtaining access to the ship's "
+"schematics constitutes a level 2 offence and carries a minimal penalty of an "
+"additional 3 years on your sentence."
+msgstr ""
+
+#: gamelib/scenes/map.py:129
+msgid ""
+"The airlock refuses to open. The automated voice says: \"Hull breach beyond "
+"this door. Personnel must be equipped for vacuum before entry.\""
+msgstr ""
+
+#: gamelib/scenes/map.py:184
+msgid ""
+"You look in the door, but just see empty space: that room appears to have "
+"been obliterated by meteors."
+msgstr ""
+
+#: gamelib/scenes/map.py:201
+msgid ""
+"Peering in through the window, you see that the entire chamber is overgrown "
+"with giant broccoli. It would take you years to cut a path through that."
+msgstr ""
+
+#: gamelib/scenes/mess.py:38
+msgid "A large collection of rusted, useless cans."
+msgstr ""
+
+#: gamelib/scenes/mess.py:44
+msgid "An impressively overgrown broccoli."
+msgstr ""
+
+#: gamelib/scenes/mess.py:55
+msgid ""
+"You bang the cans together. It sounds like two cans being banged together."
+msgstr ""
+
+#: gamelib/scenes/mess.py:64
+msgid "You'd mangle it beyond usefulness."
+msgstr ""
+
+#: gamelib/scenes/mess.py:70
+msgid "You open both ends of the can, discarding the hideous contents."
+msgstr ""
+
+#: gamelib/scenes/mess.py:80
+msgid "Flattening the can doesn't look like a useful thing to do."
+msgstr ""
+
+#: gamelib/scenes/mess.py:83
+msgid "There's nothing left to open on this can"
+msgstr ""
+
+#: gamelib/scenes/mess.py:96
+msgid "You club the can with the femur. The can gets dented, but doesn't open."
+msgstr ""
+
+#: gamelib/scenes/mess.py:106
+msgid ""
+"You club the can with the femur. The dents shift around, but it still "
+"doesn't open."
+msgstr ""
+
+#: gamelib/scenes/mess.py:137
+msgid "Best before a long time in the past. Better not eat these."
+msgstr ""
+
+#: gamelib/scenes/mess.py:138
+msgid "Mmmm. Nutritious bacteria stew."
+msgstr ""
+
+#: gamelib/scenes/mess.py:139
+msgid "Candied silkworms. Who stocked this place?!"
+msgstr ""
+
+#: gamelib/scenes/mess.py:142
+msgid "The rest of the cans are rusted beyond usefulness."
+msgstr ""
+
+#: gamelib/scenes/mess.py:145
+msgid "The contents of these cans look synthetic."
+msgstr ""
+
+#: gamelib/scenes/mess.py:167
+msgid "The broccoli seems to have become entangled with something."
+msgstr ""
+
+#: gamelib/scenes/mess.py:169
+msgid "These broken pipes look important."
+msgstr ""
+
+#: gamelib/scenes/mess.py:171
+msgid "The pipes have been repaired but are the repairs aren't airtight, yet"
+msgstr ""
+
+#: gamelib/scenes/mess.py:173
+msgid "Your fix looks like it's holding up well."
+msgstr ""
+
+#: gamelib/scenes/mess.py:179
+msgid ""
+"With a flurry of disgusting mutant vegetable chunks, you clear the overgrown "
+"broccoli away from the access panel and reveal some broken tubes. They look "
+"important."
+msgstr ""
+
+#: gamelib/scenes/mess.py:185
+msgid "It looks broken enough already."
+msgstr ""
+
+#: gamelib/scenes/mess.py:187
+msgid "Cutting holes won't repair the leaks."
+msgstr ""
+
+#: gamelib/scenes/mess.py:189
+msgid ""
+"After all that effort fixing it, chopping it to bits doesn't seem very smart."
+msgstr ""
+
+#: gamelib/scenes/mess.py:194 gamelib/scenes/mess.py:207
+msgid "It would get lost in the fronds."
+msgstr ""
+
+#: gamelib/scenes/mess.py:201
+msgid ""
+"The pipes slot neatly into place, but don't make an airtight seal. One of "
+"the pipes has cracked slightly as well."
+msgstr ""
+
+#: gamelib/scenes/mess.py:209
+msgid "There's quite enough tape on the ducting already."
+msgstr ""
+
+#: gamelib/scenes/mess.py:216
+msgid ""
+"It takes quite a lot of tape, but eventually everything is airtight and "
+"ready to hold pressure. Who'd've thought duct tape could actually be used to "
+"tape ducts?"
+msgstr ""
+
+#: gamelib/scenes/mess.py:222
+msgid "The mutant broccoli resists your best efforts."
+msgstr ""
+
+#: gamelib/scenes/mess.py:224
+msgid "Shoving the broken pipes around doesn't help much."
+msgstr ""
+
+#: gamelib/scenes/mess.py:226
+msgid "Do you really want to hold it together for the rest of the voyage?"
+msgstr ""
+
+#: gamelib/scenes/mess.py:229
+#, python-format
+msgid "You don't find any leaks. Good job, Prisoner %s."
+msgstr ""
+
+#: gamelib/scenes/mess.py:288
+msgid "The remaining bottles leak."
+msgstr ""
+
+#: gamelib/scenes/mess.py:292
+msgid ""
+"You pick up an empty dishwashing liquid bottle. You can't find any sponges."
+msgstr ""
+
+#: gamelib/scenes/mess.py:295
+msgid "Empty plastic containers. They used to hold dishwasher soap."
+msgstr ""
+
+#: gamelib/scenes/game_widgets.py:51
+msgid "A security camera watches over the room"
+msgstr ""
+
+#: gamelib/scenes/game_widgets.py:53
+msgid "The security camera is currently offline but should be working soon"
+msgstr ""
+
+#: gamelib/scenes/game_widgets.py:55
+msgid "The security camera is powered down"
+msgstr ""
+
+#: gamelib/scenes/game_widgets.py:63
+msgid ""
+"3D scene reconstruction failed. Critical error. Entering emergency shutdown."
+msgstr ""
--- a/pyntnclick/constants.py	Sat Jan 26 13:24:01 2013 +0200
+++ b/pyntnclick/constants.py	Sat Jan 26 16:57:33 2013 +0200
@@ -15,6 +15,7 @@
 
 class GameConstants(object):
     title = None
+    i18n_name = 'pyntnclick'
     # Icon for the main window, in the icons basedir
     icon = None
 
--- a/pyntnclick/gamescreen.py	Sat Jan 26 13:24:01 2013 +0200
+++ b/pyntnclick/gamescreen.py	Sat Jan 26 16:57:33 2013 +0200
@@ -7,6 +7,7 @@
 from pygame.color import Color
 from pygame.locals import MOUSEBUTTONDOWN, MOUSEMOTION, KEYDOWN, K_ESCAPE
 
+from pyntnclick.i18n import _
 from pyntnclick.cursor import CursorScreen
 from pyntnclick.engine import Screen
 from pyntnclick.widgets.base import (
@@ -146,7 +147,7 @@
         self.add_callback(MOUSEMOTION, self.mouse_move)
         self.is_detail = is_detail
         if is_detail:
-            self.close_button = TextButton((0, 0), self.gd, "Close")
+            self.close_button = TextButton((0, 0), self.gd, _("Close"))
             self.close_button.do_prepare()
             self.close_button.rect.midbottom = self.rect.midbottom
             self.close_button.add_callback('clicked', self.close)
@@ -204,7 +205,7 @@
         self.left = self.rect.left
 
         self.menu_button = self.add_tool(
-            0, TextButton, gd, "Menu", fontname=gd.constants.bold_font,
+            0, TextButton, gd, _("Menu"), fontname=gd.constants.bold_font,
             color="red", padding=1, border=0, bg_color="black")
         self.menu_button.add_callback(MOUSEBUTTONDOWN, self.menu_callback)
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/pyntnclick/i18n.py	Sat Jan 26 16:57:33 2013 +0200
@@ -0,0 +1,7 @@
+# internationalization
+
+from gettext import gettext
+
+
+def _(s):
+    return unicode(gettext(s), "utf-8")
--- a/pyntnclick/main.py	Sat Jan 26 13:24:01 2013 +0200
+++ b/pyntnclick/main.py	Sat Jan 26 16:57:33 2013 +0200
@@ -4,6 +4,8 @@
 
 '''
 import sys
+import gettext
+import locale
 from optparse import OptionParser
 
 import pygame
@@ -60,9 +62,18 @@
         self._debug_rects = False
         self._screens = self.SCREENS.copy()
         self._screens['game'] = GameScreen
-        self.resource = Resources(self._resource_module)
+        self.constants = self.game_constants()
+
+        locale.setlocale(locale.LC_ALL, "")
+        lang = locale.getlocale()[0]
+        if '_' in lang:
+            lang = lang.split('_', 1)[0]
+        self.resource = Resources(self._resource_module, lang)
+        gettext.bindtextdomain(self.constants.i18n_name,
+                               self.resource.get_resource_path('locale'))
+        gettext.textdomain(self.constants.i18n_name)
+
         self.sound = Sound(self.resource)
-        self.constants = self.game_constants()
         self.debug_options = []
         self.running = False
 
--- a/pyntnclick/resources.py	Sat Jan 26 13:24:01 2013 +0200
+++ b/pyntnclick/resources.py	Sat Jan 26 16:57:33 2013 +0200
@@ -33,9 +33,9 @@
 
         The following directories are searched, in order:
 
-         * <resource_module>/<lang>/
+         * /<lang>/<resource_module>/
          * <resource_module>/
-         * <default_resource_module>/<lang>/
+         * /<lang>/<default_resource_module>/
          * <default_resource_module>/
 
         If the `language` attribute is `None`, the paths with <lang> in them
@@ -44,7 +44,7 @@
         resource_name = '/'.join(resource_path_fragments)
         resource_name = os.path.join(*resource_name.split('/'))
         for path in self.get_paths(resource_name):
-            if os.path.isfile(path):
+            if os.path.exists(path):
                 return path
         raise ResourceNotFound(resource_name)
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/update-po.sh	Sat Jan 26 16:57:33 2013 +0200
@@ -0,0 +1,9 @@
+#!/bin/sh
+
+# Updates translation catalogs
+
+xgettext -f po/POTFILES -o po/suspended-sentence.pot
+
+for f in po/*.po; do
+  msgmerge -U $f po/suspended-sentence.pot;
+done